diff --git a/.github/workflows/compiler-differential.yml b/.github/workflows/compiler-differential.yml index 140548c944..843a4abb22 100644 --- a/.github/workflows/compiler-differential.yml +++ b/.github/workflows/compiler-differential.yml @@ -37,14 +37,8 @@ jobs: run: uv python install 3.12 - name: Install dependencies run: uv sync --locked --all-groups --all-extras - - name: Compare dense projects with and without custom rules on the preview engine + - name: Compare dense projects with and without custom rules (native vs native-preview) env: MODELS: ${{ matrix.models }} run: make compiler-differential-dense COMPILER_DIFFERENTIAL_DENSE_MODELS="${MODELS}" - - name: Compare dense projects with and without custom rules on the shipped engine - env: - MODELS: ${{ matrix.models }} - run: >- - make compiler-differential-dense COMPILER_DIFFERENTIAL_DENSE_MODELS="${MODELS}" - COMPILER_DIFFERENTIAL_ARGS="--engines python native" diff --git a/.github/workflows/verify.yml b/.github/workflows/verify.yml index 7289df00c6..1ab78f7234 100644 --- a/.github/workflows/verify.yml +++ b/.github/workflows/verify.yml @@ -303,7 +303,7 @@ jobs: run: uv python install 3.12 - name: Install dependencies run: uv sync --locked --all-groups --all-extras - - name: Compare fixtures, examples, generated seeds and the failure corpus (python vs native-preview) + - name: Compare fixtures, examples, generated seeds and the failure corpus (native vs native-preview, goldens) run: >- make compiler-differential COMPILER_DIFFERENTIAL_ARGS="--stage-captures --require-discovery-coverage @@ -318,12 +318,6 @@ jobs: path: ${{ runner.temp }}/compiler-differential-wheel-sites.json if-no-files-found: warn retention-days: 30 - - name: Compare fixtures, examples, generated seeds and the failure corpus (python vs shipped native) - run: >- - make compiler-differential-shipped - COMPILER_DIFFERENTIAL_ARGS="--stage-captures --require-discovery-coverage - --require-render-coverage --require-analysis-coverage - --evidence-dir ${{ runner.temp }}/compiler-differential-evidence/shipped" - name: Upload differing projects' targets, stderr and compiled-test stats if: failure() uses: actions/upload-artifact@v4 @@ -370,19 +364,13 @@ jobs: uv run --no-sync pytest tests/integration/src/sqlbuild/compiler/test_native_python_compat_oracle.py -n auto --dist loadfile - - name: Compare python with native-preview on fixtures, examples, the failure corpus and a few seeds + - name: Compare native with native-preview and the goldens on fixtures, examples, the failure corpus and a few seeds env: PYTHONUNBUFFERED: "1" run: >- uv run --no-sync python -m scripts.run_compiler_differential - --engines python native-preview + --engines native native-preview --goldens check --corpus fixtures examples failures seeds --seeds 4 --jobs 4 - - name: Compare python with shipped native on the failure corpus and a few seeds - env: - PYTHONUNBUFFERED: "1" - run: >- - uv run --no-sync python -m scripts.run_compiler_differential - --engines python native --corpus failures seeds --seeds 4 --jobs 4 native_discovery_windows: name: Native compiler on Windows @@ -420,14 +408,14 @@ jobs: tests/integration/src/sqlbuild/compiler/discovery/test_native_yaml_oracle.py tests/integration/src/sqlbuild/compiler/discovery/test_native_toml_oracle.py -n auto --dist loadfile - - name: Compile playground projects on the default and Python engines, and build + - name: Compile playground projects on the default and preview engines, and build run: | project="${RUNNER_TEMP}/waffle-shop" - oracle="${RUNNER_TEMP}/waffle-shop-python" + oracle="${RUNNER_TEMP}/waffle-shop-preview" uv run --no-sync sqb playground "${project}" cp -r "${project}" "${oracle}" uv run --no-sync sqb --project-dir "${project}" --no-color compile - SQLBUILD_COMPILER_ENGINE=python uv run --no-sync sqb --project-dir "${oracle}" --no-color compile + SQLBUILD_COMPILER_ENGINE=native-preview uv run --no-sync sqb --project-dir "${oracle}" --no-color compile diff -r "${oracle}/target/compiled" "${project}/target/compiled" if ! test -f "${project}/target/cache/compiler-native-v1/macro-calls.bin"; then echo "The default compile did not write the macro-call store; macro bridge debug log:" @@ -611,24 +599,18 @@ jobs: - kind: fresh max_ratio: "1.10" - kind: dense - label: native contracts vs python - base_engine: python - head_engine: native + label: contracts CPU vs base gate_phase: contracts_cpu_ms - max_ratio: "1.00" + max_ratio: "1.10" - kind: dense - label: native model analysis vs python - base_engine: python - head_engine: native + label: model analysis CPU vs base gate_phase: model_analysis_cpu_ms compile_args: --compile-arg=--select=* - max_ratio: "1.50" + max_ratio: "1.10" - kind: dense - label: native custom rules vs python - base_engine: python - head_engine: native + label: custom rules CPU vs base gate_phase: custom_rules_cpu_ms - max_ratio: "1.25" + max_ratio: "1.10" steps: - uses: actions/checkout@v4 - name: Check out the comparison base @@ -655,13 +637,11 @@ jobs: - name: Install base dependencies working-directory: base run: uv sync --locked --all-groups --all-extras - - name: Compare python and native phase CPU on head + - name: Compare base and head phase CPU if: matrix.gate_phase env: KIND: ${{ matrix.kind }} MAX_RATIO: ${{ matrix.max_ratio }} - BASE_ENGINE: ${{ matrix.base_engine }} - HEAD_ENGINE: ${{ matrix.head_engine }} GATE_PHASE: ${{ matrix.gate_phase }} COMPILE_ARGS: ${{ matrix.compile_args }} run: | @@ -670,10 +650,9 @@ jobs: --modes cold \ --max-ratio "${MAX_RATIO}" \ --models 3000 \ - --base-python .venv/bin/python \ + --base-root base \ + --base-python base/.venv/bin/python \ --head-python .venv/bin/python \ - --base-engine "${BASE_ENGINE}" \ - --head-engine "${HEAD_ENGINE}" \ --gate-phase "${GATE_PHASE}" \ ${COMPILE_ARGS:+"${COMPILE_ARGS}"} - name: Compare base and head cold, warm and one-model edit compiles diff --git a/Cargo.lock b/Cargo.lock index 0d533db2ee..b21ba42d8e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -705,6 +705,7 @@ dependencies = [ "sqlbuild-cache", "sqlbuild-core", "sqlbuild-model-config", + "sqlbuild-render", "sqlbuild-scopes", "sqlbuild-sqltext", ] diff --git a/Cargo.toml b/Cargo.toml index cb2519d85b..75f7a092a9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -55,12 +55,7 @@ pyo3 = { version = "0.26", features = ["abi3-py312"] } polyglot-sql = { git = "https://github.com/chio-labs/polyglot.git", rev = "ca9e7b6e405fb6f5484472bb08780268789c5e04", default-features = false, features = [ "ast-tools", "builder", - "dialect-bigquery", - "dialect-databricks", - "dialect-duckdb", - "dialect-postgresql", - "dialect-snowflake", - "dialect-tsql", + "all-dialects", "semantic", "stacker", ] } diff --git a/Makefile b/Makefile index c084b7a977..b8dea2f83b 100644 --- a/Makefile +++ b/Makefile @@ -7,7 +7,7 @@ SHELL := /bin/bash test-e2e-duckdb-integrations test-e2e-performance \ test-e2e-cold-compile-performance test-e2e-cache-compile-performance \ test-e2e-dense-compile-performance test-e2e-varied-cache-performance \ - compiler-differential compiler-differential-shipped compiler-differential-dense \ + compiler-differential compiler-differential-dense \ compiler-baselines format: @@ -291,7 +291,6 @@ test-e2e-varied-cache-performance: COMPILER_DIFFERENTIAL_JOBS ?= 4 COMPILER_DIFFERENTIAL_SEEDS ?= 12 -COMPILER_DIFFERENTIAL_SHIPPED_SEEDS ?= 12 COMPILER_DIFFERENTIAL_DENSE_MODELS ?= 3000 COMPILER_DIFFERENTIAL_ARGS ?= # Native-to-Python fallbacks and analysis deferrals must match the allow-list exactly, and every @@ -303,23 +302,13 @@ compiler-differential: --jobs $(COMPILER_DIFFERENTIAL_JOBS) --seeds $(COMPILER_DIFFERENTIAL_SEEDS) \ $(COMPILER_DIFFERENTIAL_GATES) $(COMPILER_DIFFERENTIAL_ARGS) -# python vs native-preview above covers every native stage; this keeps the shipped `native` default -# (native discovery, rendering and analysis) and its goldens covered on the same corpus. -compiler-differential-shipped: - env PYTHONUNBUFFERED=1 uv run python -m scripts.run_compiler_differential \ - --engines python native --corpus fixtures examples seeds failures \ - --jobs $(COMPILER_DIFFERENTIAL_JOBS) --seeds $(COMPILER_DIFFERENTIAL_SHIPPED_SEEDS) \ - $(COMPILER_DIFFERENTIAL_GATES) $(COMPILER_DIFFERENTIAL_ARGS) - -# Rewrite the goldens (from the python oracle) and the fallback allow-list from both CI runs. +# Rewrite the goldens (from the native oracle) and the fallback allow-list from the CI run. # Review the diff like code; see scripts/compiler_differential/README.md. COMPILER_DIFFERENTIAL_CI_ARGS := --stage-captures --require-discovery-coverage --require-render-coverage compiler-baselines: rm -rf tests/goldens/compiler $(MAKE) compiler-differential COMPILER_DIFFERENTIAL_ARGS="$(COMPILER_DIFFERENTIAL_CI_ARGS) \ --require-analysis-coverage --native-fallbacks update --goldens update" - $(MAKE) compiler-differential-shipped COMPILER_DIFFERENTIAL_ARGS="$(COMPILER_DIFFERENTIAL_CI_ARGS) \ - --require-analysis-coverage --native-fallbacks update --goldens update" compiler-differential-dense: env PYTHONUNBUFFERED=1 uv run python -m scripts.run_compiler_differential \ diff --git a/crates/README.md b/crates/README.md index f990c2da28..161417bc63 100644 --- a/crates/README.md +++ b/crates/README.md @@ -58,19 +58,18 @@ stages run natively: | Engine | Runs | |---|---| -| `python` | The Python compiler only. It is the oracle every native stage must match byte for byte. | -| `native` | The default: native stages that passed their flip gate (`shipped` tier). | +| `native` | The default: discovery, rendering and analysis, and every native stage that passed its flip gate (`shipped` tier). | | `native-preview` | Opt-in: shipped stages plus stages still in development (`preview` tier). | -The shipped tier covers discovery, rendering and analysis: declaration files and scopes, model -config, reference extraction, the model loop, macro calls and the macro-call store, attachments, -the type system, model analysis and its `model-analyses.bin` cache, semantic checks, contracts, -lineage facts, SQL-test glue and project assembly. A failing -render raises its first error directly, as the Python stage would, and runs each macro call at -most once; a divergence the bridge detects is reported as a native stage mismatch. Because the -macro-call store is shipped, the +The Python compiler and its `python` engine were removed once discovery, rendering and analysis +shipped natively; setting `python` is an error that says so. Native stages still hand inputs they +cannot reproduce exactly back to Python helpers (the allow-list in +`scripts/compiler_differential/native_fallbacks.toml` lists every such deferral the corpus +reaches). A failing render raises its first error directly and runs each macro call at most +once; a divergence the bridge detects is reported as a native stage mismatch. Because the +macro-call store is always on, the [macro determinism contract](../website/src/content/docs/docs/concepts/macros.mdx) applies to -every default compile; `SQLBUILD_COMPILER_ENGINE=python` runs every macro call each time. +every compile. Each native stage declares its tier once, in `NATIVE_STAGE_TIERS` in `src/sqlbuild/compiler/frontier/constants.py`. A stage moves from `preview` to `shipped` by @@ -78,12 +77,10 @@ changing that line, after its flip gate passes: a byte-identical real project, a differential, and no measured slowdown on cold, edit and no-change compiles. Every engine keeps its own compiler, Rules and compile-reuse stores, so preview output is never reused by `native`. -`make compiler-differential` compares `python` with `native-preview` on the full per-PR corpus. -`make compiler-differential-shipped` compares `python` with `native` on the generated seeds and -the failure corpus, so the shipped default stays covered on its own; CI runs it with stage -captures and requires full discovery and render coverage. CI runs both, compares `python` with -`native` and `native-preview` on Python 3.13 and 3.14 as well, and on Windows checks that the -default compiles a playground project to the same files as `python`. +`make compiler-differential` compares `native` with `native-preview` on the full per-PR corpus +and checks both against the goldens in `tests/goldens/compiler`, with stage captures and full +discovery, render and analysis coverage required. CI also runs it on Python 3.13 and 3.14, and +on Windows checks that both engines compile a playground project to the same files. ## Working on the crates diff --git a/crates/sqlbuild-analysis/Cargo.toml b/crates/sqlbuild-analysis/Cargo.toml index 4a1d764352..ff48a44396 100644 --- a/crates/sqlbuild-analysis/Cargo.toml +++ b/crates/sqlbuild-analysis/Cargo.toml @@ -23,6 +23,7 @@ sha2.workspace = true sqlbuild-cache.workspace = true sqlbuild-core.workspace = true sqlbuild-model-config.workspace = true +sqlbuild-render.workspace = true sqlbuild-scopes.workspace = true sqlbuild-sqltext.workspace = true diff --git a/crates/sqlbuild-analysis/src/assembly/analysis_session/_helpers/analysis_cache.rs b/crates/sqlbuild-analysis/src/assembly/analysis_session/_helpers/analysis_cache.rs index a58be1e7af..21cc9eb6c3 100644 --- a/crates/sqlbuild-analysis/src/assembly/analysis_session/_helpers/analysis_cache.rs +++ b/crates/sqlbuild-analysis/src/assembly/analysis_session/_helpers/analysis_cache.rs @@ -33,7 +33,6 @@ impl AnalysisSession { session_digest: session_digest(&self.request), keys: vec![None; models], hits: vec![false; models], - uncacheable: vec![false; models], legacy_tables: vec![None; models], stats: AnalysisCacheStats::default(), }); @@ -100,6 +99,7 @@ impl AnalysisSession { } } key.flag(self.dependency_ordered); + key.flag(self.cyclic); key.finish() } @@ -411,12 +411,11 @@ impl<'a> Decoder<'a> { pub(crate) fn encode_outcome( outcome: &ModelOutcome, legacy_tables: Option<&ContentDigest>, -) -> Option> { +) -> Vec { let analysis: &ModelAnalysis = &outcome.analysis; let (tag, rows) = match &analysis.lineage { LineageFacts::Native(rows) => (LINEAGE_NATIVE, rows), LineageFacts::NativeFacts(rows) => (LINEAGE_FACTS, rows), - LineageFacts::PythonAnalysis | LineageFacts::PythonEnrichment => return None, }; let mut encoder: Encoder<'_> = Encoder::default(); match legacy_tables { @@ -464,7 +463,7 @@ pub(crate) fn encode_outcome( encoder.text(severity); } encoder.flag(analysis.binding_validated); - Some(encoder.into_bytes()) + encoder.into_bytes() } /// The outcome [`encode_outcome`] stored, validated against `schema`, without cleaned SQL. diff --git a/crates/sqlbuild-analysis/src/assembly/analysis_session/_helpers/catalog_state.rs b/crates/sqlbuild-analysis/src/assembly/analysis_session/_helpers/catalog_state.rs index 2ab86d737f..47310708ff 100644 --- a/crates/sqlbuild-analysis/src/assembly/analysis_session/_helpers/catalog_state.rs +++ b/crates/sqlbuild-analysis/src/assembly/analysis_session/_helpers/catalog_state.rs @@ -1,13 +1,15 @@ -//! A session copy of the compile's binding catalog that records what Python's would gain. +//! The session's binding catalog copy and Python's published relation shapes. use std::collections::{HashMap, HashSet}; use crate::assembly::analysis_session::_helpers::compact_batch::{MemoKey, SharedResult}; use crate::assembly::analysis_session::_helpers::mappings::{ - ShapeTable, catalog_columns, catalog_relations, same_mapping, + ShapeTable, catalog_columns, catalog_relations, same_mapping, with_pair, }; +use crate::assembly::analysis_session::constants::{QUOTED_IDENTIFIER_DELIMITER, UNKNOWN_TYPE}; use crate::assembly::analysis_session::types::{Pairs, Shapes}; -use crate::semantic_validation::models::{Columns, ProjectCatalog}; +use crate::semantic_validation::main::normalize::normalize_analysis_sql; +use crate::semantic_validation::models::{Columns, NormalizationInput, ProjectCatalog}; use crate::semantic_validation::types::{BindingRequest, Relations}; /// Python's `BindingCatalog` state that model analysis reads and changes. @@ -143,3 +145,71 @@ impl SessionCatalog { (self.additions, self.analysis_names) } } + +/// How a session publishes relation shapes. +pub(crate) struct ShapeOptions<'a> { + pub(crate) dialect: &'a str, + pub(crate) case_sensitive: bool, +} + +/// One relation's inferred columns and the SQL and inputs they came from. +pub(crate) struct ShapeSource<'a> { + pub(crate) sql: &'a str, + pub(crate) columns: Pairs, + pub(crate) inputs: &'a Shapes, + pub(crate) snapshot_columns: Option<&'a (String, String)>, +} + +impl SessionCatalog { + /// A model relation's shape, including snapshot validity columns. + pub(crate) fn published_model_shape( + &self, + options: &ShapeOptions<'_>, + source: ShapeSource<'_>, + ) -> Result { + let snapshot_columns: Option<&(String, String)> = source.snapshot_columns; + let mut shape: Pairs = self.inferred_binding_shape(options, source)?; + if let Some((valid_from, valid_to)) = snapshot_columns { + shape = with_pair(shape, valid_from, UNKNOWN_TYPE); + shape = with_pair(shape, valid_to, UNKNOWN_TYPE); + } + Ok(shape) + } + + /// Column names keep authored quoting only where the dialect binds quoted names exactly. + pub(crate) fn inferred_binding_shape( + &self, + options: &ShapeOptions<'_>, + source: ShapeSource<'_>, + ) -> Result { + if !options.case_sensitive { + return Ok(source.columns); + } + let normalized: String = normalize_analysis_sql(NormalizationInput { + sql: source.sql.to_owned(), + dialect: options.dialect.to_owned(), + stubs: HashMap::new(), + placeholders: HashMap::new(), + })?; + if !normalized.contains(QUOTED_IDENTIFIER_DELIMITER) && !has_exact_input(source.inputs) { + return Ok(source.columns); + } + Ok(self + .native + .inferred_schema( + &normalized, + catalog_columns(&source.columns), + catalog_relations(source.inputs), + )? + .into_iter() + .map(|(name, data_type)| (name, data_type.unwrap_or_default())) + .collect()) + } +} + +fn has_exact_input(inputs: &Shapes) -> bool { + inputs + .iter() + .flat_map(|(_, shape)| shape.iter()) + .any(|(name, _)| name.contains(QUOTED_IDENTIFIER_DELIMITER)) +} diff --git a/crates/sqlbuild-analysis/src/assembly/analysis_session/_helpers/cte_facts.rs b/crates/sqlbuild-analysis/src/assembly/analysis_session/_helpers/cte_facts.rs index 83ec0e1a0e..536c87100d 100644 --- a/crates/sqlbuild-analysis/src/assembly/analysis_session/_helpers/cte_facts.rs +++ b/crates/sqlbuild-analysis/src/assembly/analysis_session/_helpers/cte_facts.rs @@ -1,12 +1,14 @@ //! Python's CTE fact recovery and filtered non-null outputs, over the wheel's expression view. -use std::cell::Cell; use std::collections::HashSet; use std::rc::Rc; use polyglot_sql::Expression; use polyglot_sql::traversal::ExpressionWalk; use serde_json::{Map, Value}; +use sqlbuild_core::text::main::active_python_text::active_python_text; +use sqlbuild_core::text::main::python_casefold::python_casefold; +use sqlbuild_core::text::main::python_upper::python_upper; use crate::assembly::analysis_session::_helpers::dict_walk::{ PyValue, alias_or_name, arg, children, column_table_name, direct_tables, expression_args, @@ -21,15 +23,16 @@ use crate::assembly::analysis_session::constants::{ CONCAT_AST_KIND, CONDITIONAL_RESULT_RULE, COUNT_AST_KIND, CUSTOM_TYPE_NAME, DECIMAL_TYPE, FIRST_ARG_RULE, FUNCTION_AST_KIND, IF_FUNC_AST_KIND, IS_NULL_AST_KIND, JOIN_FULL, JOIN_LEFT, JOIN_RIGHT, LITERAL_AST_KIND, NON_NULL_NULLABILITY, NULL_AST_KIND, NULL_SET_OPERATION_TYPE, - NULLABLE_NULLABILITY, NULLIF_FUNCTION_NAME, POLYGLOT_TYPE_NAMES, SELECT_AST_KIND, - SET_OPERATION_AST_KINDS, STRING_LITERAL_TYPE, SUBSTRING_AST_KIND, TABLE_AST_KIND, TEXT_TYPE, - TIMESTAMP_TYPE_NAME, TIMESTAMP_TZ_TYPE, TRY_CAST_AST_KIND, TYPE_PASSTHROUGH_AST_KINDS, - UNKNOWN_NULLABILITY, VARCHAR_DATA_TYPES, WILDCARD, + NULLABLE_NULLABILITY, NULLIF_FUNCTION_NAME, POLYGLOT_TYPE_NAMES, PYTHON_RULE, SAFE_CAST_RULE, + SELECT_AST_KIND, SET_OPERATION_AST_KINDS, STRING_LITERAL_TYPE, SUBSTRING_AST_KIND, + TABLE_AST_KIND, TEXT_TYPE, TIMESTAMP_TYPE_NAME, TIMESTAMP_TZ_TYPE, TRY_CAST_AST_KIND, + TYPE_PASSTHROUGH_AST_KINDS, UNKNOWN_NULLABILITY, VARCHAR_DATA_TYPES, WILDCARD, }; use crate::assembly::analysis_session::constants::{ CONFIDENCE_HIGH, CONFIDENCE_MEDIUM, CONFIDENCE_UNKNOWN, TRANSFORM_AGGREGATION, TRANSFORM_CAST, TRANSFORM_CONSTANT, TRANSFORM_DIRECT, TRANSFORM_EXPRESSION, TRANSFORM_STAR, }; +use crate::assembly::analysis_session::models::NullabilityCallback; use crate::assembly::analysis_session::models::{ColumnFact, LineageRow}; use crate::assembly::analysis_session::types::{Pairs, Shapes}; use crate::type_system::main::normalize_type::normalize_type; @@ -51,8 +54,10 @@ type Fact = Result; pub(crate) struct RecoveryProfile<'a> { pub(crate) dialect: &'a str, pub(crate) function_return_types: &'a Pairs, - /// Adapter nullability rules by function name; None where a rule is not one Python ships. + /// Adapter nullability rules by function name. pub(crate) rules: Option<&'a Pairs>, + /// Runs the adapter's own rules, those with the `python` rule id. + pub(crate) callback: Option<&'a NullabilityCallback>, } /// One enrichment's recovery request. @@ -77,20 +82,6 @@ pub(crate) struct Recovery { /// Python's CTE pass-through facts and filtered non-null outputs, or why they defer. pub(crate) fn recovery(input: &RecoveryInput<'_>) -> Fact { - NON_ASCII_FOLDED.set(false); - let recovered: Fact = recovered(input); - if NON_ASCII_FOLDED.replace(false) { - return Err("non-ASCII text Python casefolds or upper-cases differently".to_owned()); - } - recovered -} - -thread_local! { - /// Whether this recovery folded non-ASCII text, where Python's `casefold`/`upper` may differ. - static NON_ASCII_FOLDED: Cell = const { Cell::new(false) }; -} - -fn recovered(input: &RecoveryInput<'_>) -> Fact { let mut recovery: Recovery = Recovery::default(); let mut parsed: Option> = None; if input.recover { @@ -118,6 +109,8 @@ pub(crate) struct LegacyInput<'a> { /// Python's `lineage_reference_map` items. pub(crate) lineage_references: &'a [(String, String, String)], pub(crate) recover: bool, + /// Python's `_infer_columns_from_polyglot_ast`: nullability inferred through input columns. + pub(crate) full_nullability: bool, /// Python's `column_types_by_table`: every known relation's types. pub(crate) types: &'a ShapeTable, /// Python's `column_nullability_by_table`, in its dict order. @@ -138,15 +131,6 @@ pub(crate) struct LegacyAnalysis { /// Python's legacy analysis of a model the native engine handed back, or why it defers. pub(crate) fn legacy_analysis(input: &LegacyInput<'_>) -> Fact { - NON_ASCII_FOLDED.set(false); - let analysed: Fact = legacy_analysed(input); - if NON_ASCII_FOLDED.replace(false) { - return Err("non-ASCII text Python casefolds or upper-cases differently".to_owned()); - } - analysed -} - -fn legacy_analysed(input: &LegacyInput<'_>) -> Fact { let Some(parsed) = parse_one(input.cleaned_sql, input.profile.dialect)? else { return Ok(LegacyAnalysis { succeeded: false, @@ -216,7 +200,7 @@ fn legacy_analysed(input: &LegacyInput<'_>) -> Fact { NON_NULL_NULLABILITY } else if let Some(cte_nullability) = dict_get(&cte_nullability, output) { cte_nullability - } else if known { + } else if known || input.full_nullability { context.nullability(inner, &aliases, &nullability)? } else { context.shallow_nullability(inner)? @@ -450,9 +434,6 @@ fn passthrough_facts( if ctes.is_empty() { return Ok(recovery); } - if input.profile.rules.is_none() { - return Err("an adapter nullability rule Python does not ship".to_owned()); - } let context = Context { profile: &input.profile, }; @@ -665,7 +646,7 @@ impl Context<'_, '_> { fn normalized(&self, type_sql: &str) -> Fact { normalize_type(type_sql, self.profile.dialect) .map(|normalization| normalization.normalized) - .ok_or_else(|| format!("type normalization of {type_sql} defers")) + .map_err(|error| error.message()) } /// Python's `_polyglot_direct_select_output_types`. @@ -850,14 +831,6 @@ impl Context<'_, '_> { /// Python's `ExpressionInferenceProfile.function_return_type`. fn function_return_type(&self, function_name: &str) -> Fact> { - let ascii_keys: bool = self - .profile - .function_return_types - .iter() - .all(|(declared, _)| declared.is_ascii()); - if ascii_keys && keeps_non_ascii_upper(function_name) { - return Ok(None); - } let upper: String = upper(function_name); Ok(self .profile @@ -964,7 +937,7 @@ impl Context<'_, '_> { None => Ok(UNKNOWN_NULLABILITY), }; } - let rule: Option<&str> = self.rule(node_kind)?; + let rule: Option<(&str, &str)> = self.rule(node_kind)?; if node_kind != COALESCE_AST_KIND && rule.is_none() { return Ok(UNKNOWN_NULLABILITY); } @@ -972,7 +945,7 @@ impl Context<'_, '_> { for child in expression_args(expression) { arguments.push(self.nullability(Some(child), aliases, scoped)?); } - Ok(combined(node_kind, rule, &arguments)) + self.combined(node_kind, rule, &arguments) } /// Python's `_infer_polyglot_shallow_nullability`. @@ -992,7 +965,7 @@ impl Context<'_, '_> { None => Ok(UNKNOWN_NULLABILITY), }; } - let rule: Option<&str> = self.rule(node_kind)?; + let rule: Option<(&str, &str)> = self.rule(node_kind)?; if node_kind != COALESCE_AST_KIND && rule.is_none() { return Ok(UNKNOWN_NULLABILITY); } @@ -1000,20 +973,38 @@ impl Context<'_, '_> { for child in expression_args(expression) { arguments.push(self.shallow_nullability(Some(child))?); } - Ok(combined(node_kind, rule, &arguments)) + self.combined(node_kind, rule, &arguments) } /// `inference_profile.function_nullability_rule(kind)`. - fn rule(&self, node_kind: &str) -> Fact> { - let rules: &Pairs = self + fn rule(&self, node_kind: &str) -> Fact> { + let upper: String = upper(node_kind); + Ok(self .profile .rules - .ok_or("an adapter nullability rule Python does not ship")?; - let upper: String = upper(node_kind); - Ok(rules - .iter() + .into_iter() + .flatten() .find(|(declared, _)| *declared == upper) - .map(|(_, rule)| rule.as_str())) + .map(|(declared, rule)| (declared.as_str(), rule.as_str()))) + } + + /// COALESCE's or an adapter rule's nullability over the argument nullabilities. + fn combined( + &self, + node_kind: &str, + rule: Option<(&str, &str)>, + arguments: &[&'static str], + ) -> Fact<&'static str> { + match rule { + Some((declared, PYTHON_RULE)) if node_kind != COALESCE_AST_KIND => { + let callback: &NullabilityCallback = self + .profile + .callback + .ok_or("an adapter nullability rule without its callback")?; + (callback.0)(declared, arguments) + } + _ => Ok(combined(node_kind, rule.map(|(_, rule)| rule), arguments)), + } } } @@ -1034,10 +1025,20 @@ fn combined(node_kind: &str, rule: Option<&str>, arguments: &[&'static str]) -> match rule { Some(FIRST_ARG_RULE) => arguments.first().copied().unwrap_or(UNKNOWN_NULLABILITY), Some(CONDITIONAL_RESULT_RULE) => conditional_result(arguments), + Some(SAFE_CAST_RULE) => safe_cast(arguments), _ => UNKNOWN_NULLABILITY, } } +/// Python's `safe_cast_nullability`. +fn safe_cast(arguments: &[&'static str]) -> &'static str { + if arguments.first() == Some(&NULLABLE_NULLABILITY) { + NULLABLE_NULLABILITY + } else { + UNKNOWN_NULLABILITY + } +} + /// Python's `conditional_result_nullability`. fn conditional_result(arguments: &[&'static str]) -> &'static str { let [_, when_true, when_false, ..] = arguments else { @@ -1534,31 +1535,14 @@ fn cast_target_type(target: &Map) -> Option { Some(type_name) } -/// Python's `str.casefold`, exact for ASCII; non-ASCII text marks the recovery deferred. +/// Python's `str.casefold`. fn casefold(text: &str) -> String { - flag_non_ascii(text); - text.to_ascii_lowercase() + python_casefold(active_python_text(), text) } -/// Python's `str.upper`, exact for ASCII; non-ASCII text marks the recovery deferred. +/// Python's `str.upper`. fn upper(text: &str) -> String { - flag_non_ascii(text); - text.to_ascii_uppercase() -} - -/// Whether `text.upper()` keeps a non-ASCII character, so it can equal no ASCII key. -fn keeps_non_ascii_upper(text: &str) -> bool { - text.chars().any(upper_is_non_ascii) -} - -fn upper_is_non_ascii(character: char) -> bool { - !character.to_uppercase().all(|upper| upper.is_ascii()) -} - -fn flag_non_ascii(text: &str) { - if !text.is_ascii() { - NON_ASCII_FOLDED.set(true); - } + python_upper(active_python_text(), text) } fn dict_get<'a, V>(dict: &'a [(String, V)], key: &str) -> Option<&'a V> { diff --git a/crates/sqlbuild-analysis/src/assembly/analysis_session/_helpers/dict_walk.rs b/crates/sqlbuild-analysis/src/assembly/analysis_session/_helpers/dict_walk.rs index 96b1a60d02..51afc0030c 100644 --- a/crates/sqlbuild-analysis/src/assembly/analysis_session/_helpers/dict_walk.rs +++ b/crates/sqlbuild-analysis/src/assembly/analysis_session/_helpers/dict_walk.rs @@ -4,11 +4,20 @@ use polyglot_sql::expressions::Cte; use polyglot_sql::traversal::ExpressionWalk; use polyglot_sql::{ComplexityGuardOptions, Dialect, Expression, ParseOptions, ast_json}; use serde_json::{Map, Value, json}; +use sqlbuild_core::text::main::active_python_text::active_python_text; +use sqlbuild_core::text::main::python_casefold::python_casefold; +use sqlbuild_core::text::main::python_upper::python_upper; +use sqlbuild_core::text::models::PythonText; + +use crate::assembly::analysis_session::models::ProjectionFacts; use crate::assembly::analysis_session::constants::{ - ALIAS_AST_KIND, ANNOTATED_AST_KIND, COLUMN_AST_KIND, DEPENDENCY_FUNCTION_NAMES, - FUNCTION_AST_KIND, MAX_FUNCTION_CALL_DEPTH, RENDERED_TYPE_NAMES, STAR_AST_KIND, TABLE_AST_KIND, - WILDCARD, + ALIAS_AST_KIND, ANNOTATED_AST_KIND, ARRAY_FIXTURE_TYPE, ARRAY_PAYLOAD_KIND, CATALOG_TABLE_ARG, + COLUMN_AST_KIND, CTE_ALIAS_PAYLOAD_KEY, CTE_LIST_PAYLOAD_KEY, DEPENDENCY_FUNCTION_NAMES, + FUNCTION_AST_KIND, FUNCTION_FIXTURE_TYPES, FUNCTION_PAYLOAD_KIND, HELPER_READS_DIALECT, + LITERAL_FIXTURE_TYPES, LITERAL_PAYLOAD_KIND, MAX_FUNCTION_CALL_DEPTH, NAME_PAYLOAD_KEY, + NULL_PAYLOAD_KIND, RENDERED_TYPE_NAMES, SCHEMA_TABLE_ARG, SELECT_PAYLOAD_KEY, STAR_AST_KIND, + STRUCTURED_PAYLOAD_KINDS, TABLE_AST_KIND, VARIANT_FIXTURE_TYPE, WILDCARD, }; /// Python's `bool(value)`. @@ -130,7 +139,7 @@ pub(crate) fn render_type(node: Option<&Value>) -> Option { .iter() .find(|(name, _)| *name == folded) .map_or_else( - || raw_type.replace('_', " ").to_ascii_uppercase(), + || upper(&raw_type.replace('_', " ")), |(_, rendered)| (*rendered).to_owned(), ); if let Some(length) = python_int(node.get("length")) { @@ -154,9 +163,14 @@ pub(crate) fn python_int(value: Option<&Value>) -> Option { } } -/// Python's `str.casefold` for the ASCII text a pivot proof compares. +/// Python's `str.casefold`. pub(crate) fn casefold(text: &str) -> String { - text.to_ascii_lowercase() + python_casefold(active_python_text(), text) +} + +/// Python's `str.upper`. +pub(crate) fn upper(text: &str) -> String { + python_upper(active_python_text(), text) } /// A value the wheel hands Python for one payload key: an expression, a list of them, or data. @@ -169,6 +183,17 @@ pub(crate) enum PyValue { /// The wheel's guarded `parse_one`; Ok(None) is the `PolyglotError` Python catches. pub(crate) fn parse_one(sql: &str, dialect: &str) -> Result, String> { + match parse_one_or_error(sql, dialect)? { + Ok(parsed) => Ok(Some(parsed)), + Err(_polyglot_error) => Ok(None), + } +} + +/// The wheel's guarded `parse_one`, with the message of the `PolyglotError` it raises. +pub(crate) fn parse_one_or_error( + sql: &str, + dialect: &str, +) -> Result, String> { let guard: ComplexityGuardOptions = serde_json::from_value(json!({"maxFunctionCallDepth": MAX_FUNCTION_CALL_DEPTH})) .map_err(|error| error.to_string())?; @@ -180,12 +205,15 @@ pub(crate) fn parse_one(sql: &str, dialect: &str) -> Result, .parse_with_options(sql, &options); let mut expressions: Vec = match parsed { Ok(expressions) => expressions, - Err(_) => return Ok(None), + Err(error) => return Ok(Err(error.to_string())), }; if expressions.len() != 1 { - return Ok(None); + return Ok(Err(format!( + "Expected 1 statement, found {}", + expressions.len() + ))); } - Ok(expressions.pop()) + Ok(expressions.pop().ok_or_else(|| "no statement".to_owned())) } /// `str(getattr(node, "kind", ""))`. @@ -391,3 +419,185 @@ pub(crate) fn where_clause(node: &Expression) -> Result, String> { .map(|clause| serde_json::to_value(clause).map_err(|error| error.to_string())) .transpose() } + +/// Python's `_simple_projection_facts` of the first `SELECT`; empty where the parse fails. +pub(crate) fn fixture_projection_facts( + sql: &str, + dialect: Option<&str>, +) -> Result { + let dialect: &str = dialect.filter(|name| !name.is_empty()).unwrap_or("generic"); + let Some(parsed) = parse_one(sql, dialect)? else { + return Ok(ProjectionFacts::default()); + }; + let payload: Value = to_dict(&parsed)?; + let Some(select) = first_select(&payload) else { + return Ok(ProjectionFacts::default()); + }; + let mut facts: ProjectionFacts = collected_facts(select); + let direct: bool = matches!( + payload + .as_object() + .and_then(|map| map.get(SELECT_PAYLOAD_KEY)), + Some(Value::Object(_)) + ); + if !direct { + facts.null_literal_names.clear(); + } + Ok(facts) +} + +/// Python's recursive `_first_select`, depth first in payload order, without recursion. +fn first_select(payload: &Value) -> Option<&Map> { + let mut pending: Vec<&Value> = vec![payload]; + while let Some(node) = pending.pop() { + match node { + Value::Object(map) => { + if let Some(Value::Object(select)) = map.get(SELECT_PAYLOAD_KEY) { + return Some(select); + } + pending.extend(map.values().rev()); + } + Value::Array(items) => pending.extend(items.iter().rev()), + _ => {} + } + } + None +} + +fn collected_facts(select: &Map) -> ProjectionFacts { + let python = active_python_text(); + let mut facts: ProjectionFacts = ProjectionFacts::default(); + let mut quoted: Vec = Vec::new(); + let mut nulls: Vec = Vec::new(); + let expressions: &[Value] = select + .get("expressions") + .and_then(Value::as_array) + .map_or(&[], Vec::as_slice); + for expression in expressions { + let Some(Value::Object(alias_payload)) = expression.get("alias") else { + continue; + }; + let (Some(Value::Object(alias)), Some(Value::Object(value))) = + (alias_payload.get("alias"), alias_payload.get("this")) + else { + continue; + }; + let Some(Value::String(name)) = alias.get("name") else { + continue; + }; + let folded: String = python_casefold(python, name); + if alias.get("quoted") == Some(&Value::Bool(true)) { + quoted.push(folded.clone()); + } + let Some((kind, value_payload)) = value.iter().next() else { + continue; + }; + if kind == NULL_PAYLOAD_KIND { + nulls.push(folded); + continue; + } + if let Some(inferred) = simple_type(kind, value_payload) { + facts.types.push((folded, inferred.to_owned())); + } + } + facts.quoted_names = unique(quoted); + facts.null_literal_names = unique(nulls); + facts +} + +/// Python's `_simple_expression_type`. +fn simple_type(kind: &str, payload: &Value) -> Option<&'static str> { + if kind == LITERAL_PAYLOAD_KIND { + let literal_type: &str = payload.get("literal_type")?.as_str()?; + return lookup(&LITERAL_FIXTURE_TYPES, literal_type); + } + if kind == ARRAY_PAYLOAD_KIND { + return Some(ARRAY_FIXTURE_TYPE); + } + if STRUCTURED_PAYLOAD_KINDS.contains(&kind) { + return Some(VARIANT_FIXTURE_TYPE); + } + if kind == FUNCTION_PAYLOAD_KIND { + let name: &str = payload + .as_object()? + .get("name") + .and_then(Value::as_str) + .unwrap_or_default(); + return lookup( + &FUNCTION_FIXTURE_TYPES, + &python_upper(active_python_text(), name), + ); + } + None +} + +fn lookup(table: &[(&str, &'static str)], key: &str) -> Option<&'static str> { + table + .iter() + .find(|(candidate, _)| *candidate == key) + .map(|(_, value)| *value) +} + +fn unique(names: Vec) -> Vec { + let mut kept: Vec = Vec::with_capacity(names.len()); + for name in names { + if !kept.contains(&name) { + kept.push(name); + } + } + kept +} + +/// Python's `_parsed_reads`: helper keys `sql` reads, first first; None where `parse_one` raises. +pub(crate) fn helper_parsed_reads( + sql: &str, + keys: &[String], +) -> Result>, String> { + let python: PythonText = active_python_text(); + let folded: String = python_casefold(python, sql); + if !keys.iter().any(|key| folded.contains(key.as_str())) { + return Ok(Some(Vec::new())); + } + let Some(parsed) = parse_one(sql, HELPER_READS_DIALECT)? else { + return Ok(None); + }; + let nested: Vec = defined_cte_keys(python, &to_dict(&parsed)?); + let mut reads: Vec = Vec::new(); + for table in find_all(&parsed, TABLE_AST_KIND) { + if arg(Some(table), SCHEMA_TABLE_ARG)?.is_some() + || arg(Some(table), CATALOG_TABLE_ARG)?.is_some() + { + continue; + } + let key: String = python_casefold(python, name(Some(table))); + if keys.contains(&key) && !nested.contains(&key) && !reads.contains(&key) { + reads.push(key); + } + } + Ok(Some(reads)) +} + +/// Python's `_defined_cte_keys`: every CTE alias at any depth, casefolded. +fn defined_cte_keys(python: PythonText, tree: &Value) -> Vec { + let mut keys: Vec = Vec::new(); + let mut pending: Vec<&Value> = vec![tree]; + while let Some(value) = pending.pop() { + match value { + Value::Array(items) => pending.extend(items.iter()), + Value::Object(map) => { + if let Some(Value::Array(ctes)) = map.get(CTE_LIST_PAYLOAD_KEY) { + keys.extend(ctes.iter().filter_map(|cte| { + let alias: &Value = cte.as_object()?.get(CTE_ALIAS_PAYLOAD_KEY)?; + Some(python_casefold( + python, + alias.as_object()?.get(NAME_PAYLOAD_KEY)?.as_str()?, + )) + })); + } + pending.extend(map.values()); + } + _ => {} + } + } + keys +} diff --git a/crates/sqlbuild-analysis/src/assembly/analysis_session/_helpers/dynamic_pivot.rs b/crates/sqlbuild-analysis/src/assembly/analysis_session/_helpers/dynamic_pivot.rs index fe152f03ee..d1589b8930 100644 --- a/crates/sqlbuild-analysis/src/assembly/analysis_session/_helpers/dynamic_pivot.rs +++ b/crates/sqlbuild-analysis/src/assembly/analysis_session/_helpers/dynamic_pivot.rs @@ -1,16 +1,16 @@ //! Python's `analyze_dynamic_column_contract` over the crate's parse of the model SQL. use std::collections::{HashMap, HashSet}; -use std::panic::{AssertUnwindSafe, catch_unwind}; use rayon::ThreadPool; use rayon::iter::{IntoParallelRefIterator, ParallelIterator}; use serde_json::{Map, Value}; use sqlbuild_core::panics::main::catch_compiler_panic::catch_compiler_panic; +use sqlbuild_core::panics::main::native_failure::native_failure; use crate::assembly::analysis_session::_helpers::dict_walk::{ casefold, column_name, dict_list, identifier_name, is_single_wildcard, nested, node_key, - parse_one, payload, relation_name, render_type, to_dict, truthy, + parse_one_or_error, payload, relation_name, render_type, to_dict, truthy, upper, }; use crate::assembly::analysis_session::constants::{ ALIAS_AST_KIND, CAST_AST_KIND, CTE_AST_KIND, DUCKDB_DIALECT, DYNAMIC_VALUE_SOURCE_KINDS, @@ -21,7 +21,10 @@ use crate::assembly::analysis_session::constants::{ use crate::assembly::analysis_session::models::{ ColumnFact, ContractProof, DynamicFamily, PivotModel, PivotOutcome, PivotTables, }; -use crate::assembly::analysis_session::types::{Pairs, Shapes}; +use crate::assembly::analysis_session::types::Shapes; + +/// What an internal native failure of a pivot proof names. +const PIVOT_CONTEXT: &str = "native dynamic pivot proof"; /// Stands in for Python's `{}`: neither has a node key. static MISSING_EXPRESSION: Value = Value::Null; @@ -35,28 +38,32 @@ pub(crate) struct PivotFacts<'a> { pub(crate) families_by_table: &'a [(String, Vec)], } -/// Each model's proof in order; a model whose proof panics is deferred to Python. -pub(crate) fn pivot_outcomes(models: &[PivotModel], tables: &PivotTables) -> Vec { +/// Each model's proof in order; the first model whose proof fails internally fails them all. +pub(crate) fn pivot_outcomes( + models: &[PivotModel], + tables: &PivotTables, +) -> Result, String> { let facts = pivot_facts(tables); models .iter() - .map(|model| guarded_outcome(model, &facts)) + .map(|model| pivot_outcome(&model.sql, &model.families, &facts)) .collect() } -/// Each model's proof in order on `pool`; a model whose proof panics is deferred to Python. +/// Each model's proof in order on `pool`; the first internal failure in model order fails them all. pub(crate) fn pooled_pivot_outcomes( pool: &ThreadPool, models: &[PivotModel], tables: &PivotTables, -) -> Vec { +) -> Result, String> { let facts = pivot_facts(tables); - pool.install(|| { + let outcomes: Vec> = pool.install(|| { models .par_iter() - .map(|model| guarded_outcome(model, &facts)) + .map(|model| pivot_outcome(&model.sql, &model.families, &facts)) .collect() - }) + }); + outcomes.into_iter().collect() } fn pivot_facts(tables: &PivotTables) -> PivotFacts<'_> { @@ -69,13 +76,6 @@ fn pivot_facts(tables: &PivotTables) -> PivotFacts<'_> { } } -fn guarded_outcome(model: &PivotModel, facts: &PivotFacts<'_>) -> PivotOutcome { - catch_unwind(AssertUnwindSafe(|| { - pivot_outcome(&model.sql, &model.families, facts) - })) - .unwrap_or(PivotOutcome::Deferred) -} - /// One CTE body by folded name; None for a CTE with column aliases. type CteMap<'a> = HashMap>; @@ -85,68 +85,41 @@ enum Boundary<'a> { Passthrough(&'a str), } -/// The proof Python computes, or a deferral where its result is not reproduced exactly. +/// The proof Python computes; fails on a panic or a parsed tree the proof cannot read. pub(crate) fn pivot_outcome( sql: &str, families: &[DynamicFamily], facts: &PivotFacts<'_>, -) -> PivotOutcome { +) -> Result { if families.is_empty() { - return PivotOutcome::Absent; + return Ok(PivotOutcome::Absent); } let folded_dialect: String = casefold(facts.dialect); if !SUPPORTED_PIVOT_DIALECTS.contains(&folded_dialect.as_str()) { - return failure(format!( + return Ok(failure(format!( "adapter dialect '{}' does not support compiler-proven dynamic pivots", facts.dialect - )); - } - if !ascii_inputs(sql, families, facts) { - return PivotOutcome::Deferred; + ))); } let parse_dialect: &str = if folded_dialect == MOTHERDUCK_DIALECT { DUCKDB_DIALECT } else { folded_dialect.as_str() }; - let outcome: Result = catch_compiler_panic(|| { + catch_compiler_panic(|| { Ok(match parsed(sql, parse_dialect)? { - Some(root) => proof(&root, &folded_dialect, families, facts), - None => PivotOutcome::Deferred, + Ok(root) => proof(&root, &folded_dialect, families, facts), + Err(error) => failure(format!("dynamic pivot SQL could not be parsed: {error}")), }) - }); - match outcome { - Ok(outcome) => outcome, - Err(_) => PivotOutcome::Deferred, - } + }) + .map_err(|reason| native_failure(PIVOT_CONTEXT, &reason)) } -/// Python's `parse_one(...).to_dict()`, or None where Python reports a parse error. -fn parsed(sql: &str, dialect: &str) -> Result, String> { - parse_one(sql, dialect)? +/// Python's `parse_one(...).to_dict()`, or the parse error Python reports. +fn parsed(sql: &str, dialect: &str) -> Result, String> { + parse_one_or_error(sql, dialect)? .map(|expression| to_dict(&expression)) - .transpose() -} - -/// Casefolding equals Python's only for ASCII text. -fn ascii_inputs(sql: &str, families: &[DynamicFamily], facts: &PivotFacts<'_>) -> bool { - let shapes = [ - facts.column_types, - facts.authoritative_types, - facts.column_nullability, - ]; - sql.is_ascii() - && families.iter().all(ascii_family) - && facts.families_by_table.iter().all(ascii_families) - && shapes.into_iter().flatten().all(ascii_shape) -} - -fn ascii_families((name, families): &(String, Vec)) -> bool { - name.is_ascii() && families.iter().all(ascii_family) -} - -fn ascii_shape((name, shape): &(String, Pairs)) -> bool { - name.is_ascii() && shape.iter().all(|(column, _)| column.is_ascii()) + .map_or_else(|error| Ok(Err(error)), |value| value.map(Ok)) } fn proof( @@ -378,7 +351,7 @@ fn aggregate_fact<'a>( source_columns: &[ColumnFact], ) -> (String, Option<&'a str>, Option) { let key: &str = node_key(Some(aggregate)); - let mut name: String = key.to_ascii_uppercase(); + let mut name: String = upper(key); let Some(payload) = aggregate.get(key).and_then(Value::as_object) else { return (name, None, None); }; @@ -387,7 +360,7 @@ fn aggregate_fact<'a>( .and_then(Value::as_str) .filter(|authored| !authored.is_empty()) { - name = authored.to_ascii_uppercase(); + name = upper(authored); } let preserving: bool = TYPE_PRESERVING_AGGREGATES.contains(&name.as_str()); let value: Option<&Value> = payload.get("this"); @@ -677,18 +650,6 @@ fn failure(reason: String) -> PivotOutcome { }) } -fn ascii_family(family: &DynamicFamily) -> bool { - [ - &family.name, - &family.pivot_column, - &family.value_column, - &family.aggregate, - &family.data_type, - ] - .iter() - .all(|text| text.is_ascii()) -} - /// Python's `_families_equal` key for one family. fn normalized(family: &DynamicFamily) -> (String, String, String, String, String, Option<&str>) { ( diff --git a/crates/sqlbuild-analysis/src/assembly/analysis_session/_helpers/enrichment.rs b/crates/sqlbuild-analysis/src/assembly/analysis_session/_helpers/enrichment.rs index 38ff6dfa2a..45f4427c36 100644 --- a/crates/sqlbuild-analysis/src/assembly/analysis_session/_helpers/enrichment.rs +++ b/crates/sqlbuild-analysis/src/assembly/analysis_session/_helpers/enrichment.rs @@ -10,7 +10,7 @@ use crate::assembly::analysis_session::_helpers::cte_facts::{ LegacyAnalysis, LegacyInput, Recovery, RecoveryInput, RecoveryProfile, legacy_analysis, recovery, }; -use crate::assembly::analysis_session::_helpers::dict_walk::truthy; +use crate::assembly::analysis_session::_helpers::dict_walk::{truthy, upper}; use crate::assembly::analysis_session::_helpers::mappings::ShapeTable; use crate::assembly::analysis_session::constants::{ CAST_TRANSFORM, CONFIDENCE_HIGH, CONFIDENCE_MEDIUM, CONFIDENCE_UNKNOWN, FILTER_CONTEXT, @@ -19,6 +19,7 @@ use crate::assembly::analysis_session::constants::{ TRANSFORM_DIRECT, TRANSFORM_EXPRESSION, TRANSFORM_STAR, UNKNOWN_NULLABILITY, UNKNOWN_TYPE, WILDCARD, }; +use crate::assembly::analysis_session::models::NullabilityCallback; use crate::assembly::analysis_session::models::{ColumnFact, LineageRow, ModelRequest}; use crate::assembly::analysis_session::types::{Pairs, Shapes}; use crate::semantic_validation::main::normalize::normalize_analysis_sql; @@ -30,8 +31,9 @@ pub(crate) struct EnrichmentInput<'a> { pub(crate) input_schemas: &'a Shapes, pub(crate) dialect: &'a str, pub(crate) function_return_types: &'a Pairs, - /// Adapter nullability rules by function name; None where one is not a rule Python ships. + /// Adapter nullability rules by function name. pub(crate) nullability_rules: Option<&'a Pairs>, + pub(crate) nullability_callback: Option<&'a NullabilityCallback>, } /// Python's re-analysis: its outcome, columns, plain lineage facts and the star flag. @@ -43,34 +45,28 @@ pub(crate) struct Enrichment { pub(crate) has_star: bool, } -/// Python's compact re-analysis: answered, declined to the legacy analysis, or deferred. +/// Python's compact re-analysis: answered, or declined to the legacy analysis. enum Projected { Native(Enrichment), Declined, - Deferred, } /// One projection's upstream sources and confidence code. type Upstream = (Vec<(String, String, String)>, u8); -/// Python's compact re-analysis, or None where Python would take another path. -pub(crate) fn enrichment(input: &EnrichmentInput<'_>) -> Option { - let enrichment: Result, String> = catch_compiler_panic(|| analysed(input)); - enrichment.unwrap_or_default() +/// Python's compact re-analysis. # Errors An internal native failure, panics included. +pub(crate) fn enrichment(input: &EnrichmentInput<'_>) -> Result { + catch_compiler_panic(|| analysed(input)) } -/// The re-analysis; Ok(None) where Python takes another path, Err for an unexpected failure. -fn analysed(input: &EnrichmentInput<'_>) -> Result, String> { - let normalized: Result = normalize_analysis_sql(NormalizationInput { +fn analysed(input: &EnrichmentInput<'_>) -> Result { + let cleaned: String = normalize_analysis_sql(NormalizationInput { sql: input.model.query_sql.clone(), dialect: input.dialect.to_owned(), stubs: HashMap::new(), placeholders: input.model.placeholders.iter().cloned().collect(), - }); - let cleaned: String = match normalized { - Ok(cleaned) => cleaned, - Err(_) => return Ok(None), - }; + }) + .map_err(|_| "the analysed SQL no longer normalizes".to_owned())?; let mut options: Map = Map::new(); options.insert( "dialect".to_owned(), @@ -83,22 +79,21 @@ fn analysed(input: &EnrichmentInput<'_>) -> Result, String> { "complexityGuard".to_owned(), json!({"maxFunctionCallDepth": MAX_FUNCTION_CALL_DEPTH}), ); - let options: AnalyzeQueryOptions = - serde_json::from_value(Value::Object(options)).map_err(|error| error.to_string())?; + let options: AnalyzeQueryOptions = serde_json::from_value(Value::Object(options)) + .map_err(|error| format!("query analysis options: {error}"))?; let analysis = match analyze_query(&cleaned, options) { Ok(analysis) => analysis, - Err(_) => return Ok(legacy(input, &cleaned)), + Err(_) => return legacy(input, &cleaned), }; let analysis: Value = serde_json::to_value(analysis).map_err(|error| error.to_string())?; - Ok(match projected(input, &analysis, &cleaned) { - Projected::Native(enrichment) => Some(enrichment), + match projected(input, &analysis, &cleaned)? { + Projected::Native(enrichment) => Ok(enrichment), Projected::Declined => legacy(input, &cleaned), - Projected::Deferred => None, - }) + } } /// Python's legacy analysis once compact analysis declines, over the input shapes. -fn legacy(input: &EnrichmentInput<'_>, cleaned: &str) -> Option { +fn legacy(input: &EnrichmentInput<'_>, cleaned: &str) -> Result { let types: ShapeTable = ShapeTable::from_shapes(input.input_schemas); let unknown: Shapes = input .input_schemas @@ -106,22 +101,21 @@ fn legacy(input: &EnrichmentInput<'_>, cleaned: &str) -> Option { .map(|(name, shape)| (name.clone(), unknown_shape(shape))) .collect(); let nullability: ShapeTable = ShapeTable::from_shapes(&unknown); - let analysis: LegacyAnalysis = match legacy_analysis(&LegacyInput { + let analysis: LegacyAnalysis = legacy_analysis(&LegacyInput { cleaned_sql: cleaned, lineage_references: &input.model.lineage_references, recover: input.model.recover_cte_facts, + full_nullability: false, types: &types, nullability: &nullability, profile: RecoveryProfile { dialect: input.dialect, function_return_types: input.function_return_types, rules: input.nullability_rules, + callback: input.nullability_callback, }, - }) { - Ok(analysis) => analysis, - Err(_deferred) => return None, - }; - Some(Enrichment { + })?; + Ok(Enrichment { analysis_succeeded: analysis.succeeded, columns: analysis.columns, lineage: analysis.lineage, @@ -167,29 +161,30 @@ fn analysis_schema(input: &EnrichmentInput<'_>) -> Option { } /// Python's projection of `analyze_query` facts into columns and lineage. -fn projected(input: &EnrichmentInput<'_>, analysis: &Value, cleaned: &str) -> Projected { +fn projected( + input: &EnrichmentInput<'_>, + analysis: &Value, + cleaned: &str, +) -> Result { let Some(projections) = analysis.get("projections").and_then(Value::as_array) else { - return Projected::Declined; + return Ok(Projected::Declined); }; let shape: Option<&str> = analysis.get("shape").and_then(Value::as_str); if !matches!(shape, Some(SELECT_SHAPE | SET_OPERATION_SHAPE)) || !eligible(projections) { - return Projected::Declined; - } - match native_projection(input, analysis, cleaned, projections) { - Some(enrichment) => Projected::Native(enrichment), - None => Projected::Deferred, + return Ok(Projected::Declined); } + native_projection(input, analysis, cleaned, projections).map(Projected::Native) } -/// The compact facts as Python's columns and lineage, None where native defers. +/// The compact facts as Python's columns and lineage. fn native_projection( input: &EnrichmentInput<'_>, analysis: &Value, cleaned: &str, projections: &[Value], -) -> Option { +) -> Result { let shape: Option<&str> = analysis.get("shape").and_then(Value::as_str); - let recovery: Recovery = match recovery(&RecoveryInput { + let recovery: Recovery = recovery(&RecoveryInput { cleaned_sql: cleaned, input_schemas: input.input_schemas, recover: recovers_cte_facts(input, analysis), @@ -198,11 +193,9 @@ fn native_projection( dialect: input.dialect, function_return_types: input.function_return_types, rules: input.nullability_rules, + callback: input.nullability_callback, }, - }) { - Ok(recovery) => recovery, - Err(_deferred) => return None, - }; + })?; let resources: HashMap<&str, (&str, &str)> = input .model .lineage_references @@ -213,7 +206,9 @@ fn native_projection( let mut columns: Vec = Vec::new(); let mut lineage: Vec = Vec::new(); for projection in projections { - let projection: &Map = projection.as_object()?; + let projection: &Map = projection + .as_object() + .ok_or("an eligible projection that is not an object")?; if truthy(projection.get("isStar")) { continue; } @@ -225,7 +220,7 @@ fn native_projection( let data_type: Option = if direct { recovered(&recovery.types, name).cloned() } else { - projection_type(projection, input.function_return_types)? + projection_type(projection, input.function_return_types) }; let nullability: &str = if recovery.non_null_outputs.contains(name) { NON_NULL_NULLABILITY @@ -268,7 +263,7 @@ fn native_projection( .unwrap_or(fallback) }); } - Some(Enrichment { + Ok(Enrichment { analysis_succeeded: true, columns: Some(columns), lineage, @@ -326,10 +321,10 @@ fn has_null_filter(analysis: &Value) -> bool { fn projection_type( projection: &Map, function_return_types: &Pairs, -) -> Option> { +) -> Option { let cast_type: &str = text(projection.get("castType")); if !cast_type.is_empty() && cast_type != UNKNOWN_TYPE { - return Some(Some(cast_type.to_owned())); + return Some(cast_type.to_owned()); } let function_name: Option<&str> = projection .get("transformFunction") @@ -337,22 +332,16 @@ fn projection_type( .and_then(|function| function.get("name")) .and_then(Value::as_str); if let Some(function_name) = function_name { - if !function_name.is_ascii() { - return None; - } - let upper: String = function_name.to_ascii_uppercase(); + let upper: String = upper(function_name); if let Some((_, declared)) = function_return_types .iter() .find(|(name, _)| *name == upper) { - return Some(Some(declared.clone())); + return Some(declared.clone()); } } let type_hint: &str = text(projection.get("typeHint")); - if !type_hint.is_empty() && type_hint != UNKNOWN_TYPE { - return Some(Some(type_hint.to_owned())); - } - Some(None) + (!type_hint.is_empty() && type_hint != UNKNOWN_TYPE).then(|| type_hint.to_owned()) } fn projection_nullability(projection: &Map, infer: bool) -> &'static str { diff --git a/crates/sqlbuild-analysis/src/assembly/analysis_session/_helpers/mod.rs b/crates/sqlbuild-analysis/src/assembly/analysis_session/_helpers/mod.rs index 30aa4a8a3e..61615bd519 100644 --- a/crates/sqlbuild-analysis/src/assembly/analysis_session/_helpers/mod.rs +++ b/crates/sqlbuild-analysis/src/assembly/analysis_session/_helpers/mod.rs @@ -6,5 +6,5 @@ pub(crate) mod dict_walk; pub(crate) mod dynamic_pivot; pub(crate) mod enrichment; pub(crate) mod mappings; -pub(crate) mod publication; +pub(crate) mod query_columns; pub(crate) mod session; diff --git a/crates/sqlbuild-analysis/src/assembly/analysis_session/_helpers/publication.rs b/crates/sqlbuild-analysis/src/assembly/analysis_session/_helpers/publication.rs deleted file mode 100644 index 5032309904..0000000000 --- a/crates/sqlbuild-analysis/src/assembly/analysis_session/_helpers/publication.rs +++ /dev/null @@ -1,80 +0,0 @@ -//! Python's `published_model_shape` and `inferred_binding_shape`. - -use std::collections::HashMap; - -use crate::assembly::analysis_session::_helpers::catalog_state::SessionCatalog; -use crate::assembly::analysis_session::_helpers::mappings::{ - catalog_columns, catalog_relations, with_pair, -}; -use crate::assembly::analysis_session::constants::{QUOTED_IDENTIFIER_DELIMITER, UNKNOWN_TYPE}; -use crate::assembly::analysis_session::types::{Pairs, Shapes}; -use crate::semantic_validation::main::normalize::normalize_analysis_sql; -use crate::semantic_validation::models::NormalizationInput; - -/// How a session publishes relation shapes. -pub(crate) struct ShapeOptions<'a> { - pub(crate) dialect: &'a str, - pub(crate) case_sensitive: bool, -} - -/// One relation's inferred columns and the SQL and inputs they came from. -pub(crate) struct ShapeSource<'a> { - pub(crate) sql: &'a str, - pub(crate) columns: Pairs, - pub(crate) inputs: &'a Shapes, - pub(crate) snapshot_columns: Option<&'a (String, String)>, -} - -impl SessionCatalog { - /// A model relation's shape, including snapshot validity columns. - pub(crate) fn published_model_shape( - &self, - options: &ShapeOptions<'_>, - source: ShapeSource<'_>, - ) -> Result { - let snapshot_columns: Option<&(String, String)> = source.snapshot_columns; - let mut shape: Pairs = self.inferred_binding_shape(options, source)?; - if let Some((valid_from, valid_to)) = snapshot_columns { - shape = with_pair(shape, valid_from, UNKNOWN_TYPE); - shape = with_pair(shape, valid_to, UNKNOWN_TYPE); - } - Ok(shape) - } - - /// Column names keep authored quoting only where the dialect binds quoted names exactly. - pub(crate) fn inferred_binding_shape( - &self, - options: &ShapeOptions<'_>, - source: ShapeSource<'_>, - ) -> Result { - if !options.case_sensitive { - return Ok(source.columns); - } - let normalized: String = normalize_analysis_sql(NormalizationInput { - sql: source.sql.to_owned(), - dialect: options.dialect.to_owned(), - stubs: HashMap::new(), - placeholders: HashMap::new(), - })?; - if !normalized.contains(QUOTED_IDENTIFIER_DELIMITER) && !has_exact_input(source.inputs) { - return Ok(source.columns); - } - Ok(self - .native - .inferred_schema( - &normalized, - catalog_columns(&source.columns), - catalog_relations(source.inputs), - )? - .into_iter() - .map(|(name, data_type)| (name, data_type.unwrap_or_default())) - .collect()) - } -} - -fn has_exact_input(inputs: &Shapes) -> bool { - inputs - .iter() - .flat_map(|(_, shape)| shape.iter()) - .any(|(name, _)| name.contains(QUOTED_IDENTIFIER_DELIMITER)) -} diff --git a/crates/sqlbuild-analysis/src/assembly/analysis_session/_helpers/query_columns.rs b/crates/sqlbuild-analysis/src/assembly/analysis_session/_helpers/query_columns.rs new file mode 100644 index 0000000000..7a20a27572 --- /dev/null +++ b/crates/sqlbuild-analysis/src/assembly/analysis_session/_helpers/query_columns.rs @@ -0,0 +1,194 @@ +//! Python's per-query column analysis outside the session, behind its entry point. + +use std::collections::HashMap; + +use sqlbuild_core::panics::main::catch_compiler_panic::catch_compiler_panic; +use sqlbuild_sqltext::compiler::main::placeholder_defaults::placeholder_defaults; + +use crate::assembly::analysis_session::_helpers::catalog_state::SessionCatalog; +use crate::assembly::analysis_session::_helpers::compact_batch::{ + Batch, BatchMember, MemberAnalysis, MemberResult, +}; +use crate::assembly::analysis_session::_helpers::cte_facts::{ + LegacyAnalysis, LegacyInput, RecoveryProfile, legacy_analysis, +}; +use crate::assembly::analysis_session::_helpers::enrichment::{ + Enrichment, EnrichmentInput, enrichment, +}; +use crate::assembly::analysis_session::_helpers::mappings::ShapeTable; +use crate::assembly::analysis_session::models::{ + ModelReference, ModelRequest, QueryColumns, QueryColumnsInput, QueryColumnsMode, + QueryColumnsRequest, +}; +use crate::semantic_validation::main::normalize::normalize_analysis_sql; +use crate::semantic_validation::models::{NormalizationInput, ProjectCatalog}; + +/// The request with `Parse` and `Legacy` SQL normalized in order; Err is the first rejection. +pub(crate) fn normalized_request( + request: &QueryColumnsRequest, +) -> Result { + let mut normalized: QueryColumnsRequest = request.clone(); + for query in &mut normalized.queries { + if matches!( + query.mode, + QueryColumnsMode::Parse | QueryColumnsMode::Legacy + ) { + query.sql = normalize_analysis_sql(NormalizationInput { + sql: std::mem::take(&mut query.sql), + dialect: request.normalization_dialect.clone(), + stubs: HashMap::new(), + placeholders: HashMap::new(), + })?; + } + } + Ok(normalized) +} + +/// Each query's columns, in order; only `Batch` queries read the catalog. +pub(crate) fn query_columns( + catalog: Option<&ProjectCatalog>, + request: &QueryColumnsRequest, +) -> Result, String> { + let types: ShapeTable = ShapeTable::from_shapes(&request.types); + let nullability: ShapeTable = ShapeTable::from_shapes(&request.nullability); + let analysed: Vec<(usize, &QueryColumnsInput)> = request + .queries + .iter() + .enumerate() + .filter(|(_, query)| query.mode == QueryColumnsMode::Batch) + .collect(); + let mut batch_results: HashMap = HashMap::new(); + if !analysed.is_empty() { + let catalog: &ProjectCatalog = + catalog.ok_or("a compact query batch without an analysis catalog")?; + let mut session_catalog: SessionCatalog = SessionCatalog::new(catalog, &Vec::new()); + let batch = Batch { + dialect: &request.dialect, + function_return_types: &request.function_return_types, + rich_type_inference: true, + members: analysed + .iter() + .map(|(_, query)| BatchMember { + query_sql: &query.sql, + placeholders: &query.placeholders, + analysis_names: query.analysis_names.iter().map(String::as_str).collect(), + lineage_references: &query.lineage_references, + recover_cte_facts: query.recover_cte_facts, + binding_schema: None, + }) + .collect(), + types: &types, + nullability: &nullability, + }; + let results: Vec = session_catalog.analyze_batch(&batch)?; + batch_results.extend(analysed.iter().map(|(index, _)| *index).zip(results)); + } + let tables = Tables { + request, + types: &types, + nullability: &nullability, + }; + request + .queries + .iter() + .enumerate() + .map(|(index, query)| match batch_results.remove(&index) { + None if query.mode == QueryColumnsMode::Reanalysis => tables.reanalysed(query), + None => tables.parsed( + query, + &parse_cleaned_sql(query), + query.mode == QueryColumnsMode::Parse, + ), + Some(result) => match result.analysis { + MemberAnalysis::Projected { + columns, has_star, .. + } => Ok(QueryColumns { + succeeded: true, + columns: Some(columns), + has_star, + }), + MemberAnalysis::Legacy { .. } => tables.parsed(query, &result.cleaned_sql, false), + MemberAnalysis::Failed => Ok(QueryColumns::default()), + }, + }) + .collect() +} + +/// Python's `substitute_placeholder_defaults` over SQL its caller already normalized. +fn parse_cleaned_sql(query: &QueryColumnsInput) -> String { + if query.placeholders.is_empty() { + query.sql.clone() + } else { + placeholder_defaults(&query.sql, &query.placeholders) + } +} + +struct Tables<'a> { + request: &'a QueryColumnsRequest, + types: &'a ShapeTable, + nullability: &'a ShapeTable, +} + +impl Tables<'_> { + /// Python's `analyze_columns_and_lineage_with_polyglot` without a precomputed analysis. + fn reanalysed(&self, query: &QueryColumnsInput) -> Result { + let model = ModelRequest { + query_sql: query.sql.clone(), + placeholders: query.placeholders.clone(), + references: query + .analysis_names + .iter() + .map(|analysis_name| ModelReference { + analysis_name: analysis_name.clone(), + model_ref: false, + }) + .collect(), + lineage_references: query.lineage_references.clone(), + recover_cte_facts: query.recover_cte_facts, + ..ModelRequest::default() + }; + let enriched: Enrichment = enrichment(&EnrichmentInput { + model: &model, + input_schemas: &self.request.types, + dialect: &self.request.dialect, + function_return_types: &self.request.function_return_types, + nullability_rules: self.request.nullability_rules.as_ref(), + nullability_callback: self.request.nullability_callback.as_ref(), + })?; + Ok(QueryColumns { + succeeded: enriched.analysis_succeeded, + columns: enriched.columns, + has_star: enriched.has_star, + }) + } + + /// Python's analysis of the parsed tree. + fn parsed( + &self, + query: &QueryColumnsInput, + cleaned_sql: &str, + full_nullability: bool, + ) -> Result { + let analysis: LegacyAnalysis = catch_compiler_panic(|| { + legacy_analysis(&LegacyInput { + cleaned_sql, + lineage_references: &query.lineage_references, + recover: query.recover_cte_facts, + full_nullability, + types: self.types, + nullability: self.nullability, + profile: RecoveryProfile { + dialect: &self.request.dialect, + function_return_types: &self.request.function_return_types, + rules: self.request.nullability_rules.as_ref(), + callback: self.request.nullability_callback.as_ref(), + }, + }) + })?; + Ok(QueryColumns { + succeeded: analysis.succeeded, + columns: analysis.columns, + has_star: analysis.has_star, + }) + } +} diff --git a/crates/sqlbuild-analysis/src/assembly/analysis_session/_helpers/session.rs b/crates/sqlbuild-analysis/src/assembly/analysis_session/_helpers/session.rs index b9530e6ab9..54eadd5488 100644 --- a/crates/sqlbuild-analysis/src/assembly/analysis_session/_helpers/session.rs +++ b/crates/sqlbuild-analysis/src/assembly/analysis_session/_helpers/session.rs @@ -8,11 +8,13 @@ use rayon::iter::{IndexedParallelIterator, IntoParallelRefIterator, ParallelIter use sqlbuild_cache::digest::types::ContentDigest; use sqlbuild_cache::store::errors::StoreDecodeError; use sqlbuild_core::panics::main::catch_compiler_panic::catch_compiler_panic; +use sqlbuild_core::panics::main::native_failure::native_failure; use crate::assembly::analysis_session::_helpers::analysis_cache::{ CachedOutcome, decode_outcome, encode_outcome, }; use crate::assembly::analysis_session::_helpers::catalog_state::SessionCatalog; +use crate::assembly::analysis_session::_helpers::catalog_state::{ShapeOptions, ShapeSource}; use crate::assembly::analysis_session::_helpers::compact_batch::{ Batch, BatchMember, MemberAnalysis, MemberResult, }; @@ -27,44 +29,47 @@ use crate::assembly::analysis_session::_helpers::mappings::{ ShapeTable, dict_from_pairs, same_keys, same_relations, }; use crate::assembly::analysis_session::_helpers::mappings::{producers, waves}; -use crate::assembly::analysis_session::_helpers::publication::{ShapeOptions, ShapeSource}; -use crate::assembly::analysis_session::constants::{ - DEFERRAL_ANALYSIS, DEFERRAL_ENRICHMENT, UNKNOWN_NULLABILITY, UNKNOWN_TYPE, -}; +use crate::assembly::analysis_session::constants::{UNKNOWN_NULLABILITY, UNKNOWN_TYPE}; use crate::assembly::analysis_session::models::{ - AnalysisSession, Awaiting, ColumnFact, Deferral, DeferredAnalysis, FinishedSession, - LineageFacts, LineageRow, ModelAnalysis, ModelOutcome, ModelRequest, Phase, PivotOutcome, - PivotTables, SessionModelFacts, SessionOutcome, SessionRequest, SessionStep, + AnalysisSession, ColumnFact, ContractProof, FinishedSession, LineageFacts, LineageRow, + ModelAnalysis, ModelOutcome, ModelRequest, Phase, PivotOutcome, PivotTables, SessionModelFacts, + SessionOutcome, SessionRequest, SessionStep, }; use crate::assembly::analysis_session::types::{Pairs, Shapes}; use crate::semantic_validation::models::ProjectCatalog; use crate::semantic_validation::types::DiagnosticRow; -/// The enrichment deferrals of one wave and whether each model's star was pending. -type Enrichments = (Vec, HashMap); +/// What an internal native failure of the session names. +const SESSION_CONTEXT: &str = "native model analysis"; impl AnalysisSession { - /// A session over `request`, or None where Python's cycle handling must analyse. - pub(crate) fn start(request: SessionRequest, catalog: &ProjectCatalog) -> Option { - let waves: Vec> = waves(&producers(&request.models)?)?; + /// A session over `request`; a `ref` cycle is one wave. + pub(crate) fn start(request: SessionRequest, catalog: &ProjectCatalog) -> Result { + let producers: Vec> = producers(&request.models) + .ok_or_else(|| native_failure(SESSION_CONTEXT, "two analysed models share a name"))?; + let scheduled: Option>> = waves(&producers); let complete_shapes: ShapeTable = ShapeTable::from_shapes(&request.complete_schemas); - let dependency_ordered: bool = request - .models - .iter() - .flat_map(|model| model.required_names.iter()) - .any(|name| complete_shapes.get(name).is_none_or(Vec::is_empty)); - Some(Self { + let dependency_ordered: bool = scheduled.is_some() + && request + .models + .iter() + .flat_map(|model| model.required_names.iter()) + .any(|name| complete_shapes.get(name).is_none_or(Vec::is_empty)); + let cyclic: bool = scheduled.is_none(); + let waves: Vec> = scheduled.unwrap_or_default(); + Ok(Self { catalog: SessionCatalog::new(catalog, &request.catalog_schemas), available_types: ShapeTable::from_shapes(&request.column_types), available_nullability: ShapeTable::from_shapes(&request.column_nullability), complete_shapes, outcomes: vec![None; request.models.len()], - waves: if dependency_ordered || waves.is_empty() { + waves: if dependency_ordered || request.models.is_empty() { waves } else { vec![(0..request.models.len()).collect()] }, dependency_ordered, + cyclic, next_wave: 0, phase: Phase::Analyze, publications: Vec::new(), @@ -74,41 +79,23 @@ impl AnalysisSession { }) } - /// Advance until Python must answer deferrals; a step without deferrals means done. + /// Analyse every wave; any internal native failure fails the whole analysis. pub(crate) fn run(&mut self) -> Result { loop { match std::mem::replace(&mut self.phase, Phase::Done) { - Phase::Await(awaiting) => { - self.phase = Phase::Await(awaiting); - return Err("the session is waiting for deferred analyses".to_owned()); - } - Phase::Done => return Ok(self.step(Vec::new())), + Phase::Done => return Ok(self.step()), Phase::Analyze => { let Some(models) = self.waves.get(self.next_wave).cloned() else { - return Ok(self.step(Vec::new())); + return Ok(self.step()); }; let wave: usize = self.next_wave; self.next_wave += 1; - let deferrals: Vec = self.analyze_wave(&models)?; - if deferrals.is_empty() { - self.phase = Phase::Complete(wave); - continue; - } - let deferred: Vec = deferrals.iter().map(Deferral::model).collect(); - self.phase = Phase::Await(Awaiting::Analyses { - wave, - models: deferred, - }); - return Ok(self.step(deferrals)); + self.analyze_wave(&models)?; + self.phase = Phase::Complete(wave); } Phase::Complete(wave) => { - let (deferrals, star_pending) = self.complete_wave(wave)?; - if deferrals.is_empty() { - self.phase = Phase::Finish(wave); - continue; - } - self.phase = Phase::Await(Awaiting::Enrichments { wave, star_pending }); - return Ok(self.step(deferrals)); + self.complete_wave(wave)?; + self.phase = Phase::Finish(wave); } Phase::Finish(wave) => { self.finish_wave(wave)?; @@ -118,50 +105,6 @@ impl AnalysisSession { } } - /// Answer the deferrals of the last step. - pub(crate) fn provide(&mut self, results: Vec) -> Result<(), String> { - let Phase::Await(awaiting) = std::mem::replace(&mut self.phase, Phase::Done) else { - return Err("the session is not waiting for deferred analyses".to_owned()); - }; - match awaiting { - Awaiting::Analyses { wave, models } => { - let mut answered: Vec = results.iter().map(|result| result.model).collect(); - answered.sort_unstable(); - let mut expected: Vec = models; - expected.sort_unstable(); - if answered != expected { - return Err("deferred analyses do not match the deferrals".to_owned()); - } - for result in results { - let model: usize = result.model; - self.mark_uncacheable(model); - self.outcome_mut(model)?.analysis = python_analysis(result); - } - self.phase = Phase::Complete(wave); - } - Awaiting::Enrichments { wave, star_pending } => { - if results.len() != star_pending.len() { - return Err("deferred enrichments do not match the deferrals".to_owned()); - } - for result in results { - let pending: bool = *star_pending - .get(&result.model) - .ok_or("an enrichment answers no deferral")?; - self.mark_uncacheable(result.model); - let outcome: &mut ModelOutcome = self.outcome_mut(result.model)?; - outcome.analysis = enriched_analysis( - &outcome.analysis, - result, - pending, - LineageFacts::PythonEnrichment, - ); - } - self.phase = Phase::Finish(wave); - } - } - Ok(()) - } - /// Every model's outcome and the binding catalog changes Python records. pub(crate) fn finish(self) -> Result<(SessionOutcome, FinishedSession), String> { if !matches!(self.phase, Phase::Done) { @@ -177,10 +120,15 @@ impl AnalysisSession { let (schema_additions, analysis_names) = self.catalog.into_changes(); let request: SessionRequest = self.request; let mut model_facts: HashMap = HashMap::new(); - for (model, outcome) in request.models.iter().zip(&models) { + let mut dynamic_proofs: HashMap = HashMap::new(); + for ((model, outcome), proof) in request.models.iter().zip(&models).zip(&dynamic_contracts) + { if let Some(facts) = session_model_facts(&outcome.analysis) { model_facts.insert(model.name.clone(), facts); } + if let PivotOutcome::Proof(proof) = proof { + dynamic_proofs.insert(model.name.clone(), proof.clone()); + } } let finished = FinishedSession { tables: PivotTables { @@ -192,6 +140,7 @@ impl AnalysisSession { }, pool, models: model_facts, + dynamic_proofs, }; let outcome = SessionOutcome { models, @@ -216,18 +165,18 @@ impl AnalysisSession { families_by_table: &self.request.dynamic_families_by_table, }; let pool = self.catalog.native.analysis_pool()?; - Ok(pool.install(|| { + let outcomes: Vec> = pool.install(|| { models .par_iter() .map(|model| pivot_outcome(&model.pivot_sql, &model.dynamic_families, &facts)) .collect() - })) + }); + outcomes.into_iter().collect() } - fn step(&mut self, deferrals: Vec) -> SessionStep { + fn step(&mut self) -> SessionStep { SessionStep { publications: std::mem::take(&mut self.publications), - deferrals, failures: std::mem::take(&mut self.failures), } } @@ -236,11 +185,11 @@ impl AnalysisSession { self.outcomes .get_mut(model) .and_then(Option::as_mut) - .ok_or_else(|| "a deferral names an unanalysed model".to_owned()) + .ok_or_else(|| native_failure(SESSION_CONTEXT, "a model was left unanalysed")) } /// Python's `_analyze_model_sql_requests` for one wave, less the models the cache answers. - fn analyze_wave(&mut self, models: &[usize]) -> Result, String> { + fn analyze_wave(&mut self, models: &[usize]) -> Result<(), String> { let schemas: Vec = models .iter() .map(|model| self.binding_schema(&self.request.models[*model])) @@ -260,7 +209,6 @@ impl AnalysisSession { nullability: &self.available_nullability, }; let results: Vec = self.catalog.analyze_batch(&batch)?; - let mut deferrals: Vec = Vec::new(); let mut tables: Option = None; for (position, result) in misses.into_iter().zip(results) { let model: &usize = &models[position]; @@ -288,22 +236,12 @@ impl AnalysisSession { failed_analysis(LineageFacts::Native(Vec::new()), diagnostics) } MemberAnalysis::Legacy { lineage } => { - match self.native_legacy(&self.request.models[*model], &result.cleaned_sql) { - Ok(legacy) => { - self.record_legacy_tables(*model, &mut tables); - legacy_outcome(legacy, lineage, diagnostics) - } - Err(_deferred) => { - deferrals.push(Deferral::Analysis { - model: *model, - cleaned_sql: result.cleaned_sql.clone(), - binding_schema: schema.clone(), - binding_diagnostics: diagnostics.clone(), - lineage, - }); - failed_analysis(LineageFacts::PythonAnalysis, diagnostics) - } - } + let request: &ModelRequest = &self.request.models[*model]; + let legacy: LegacyAnalysis = + self.native_legacy(request, &result.cleaned_sql) + .map_err(|reason| native_failure(&model_context(request), &reason))?; + self.record_legacy_tables(*model, &mut tables); + legacy_outcome(legacy, lineage, diagnostics) } }; self.outcomes[*model] = Some(ModelOutcome { @@ -313,7 +251,7 @@ impl AnalysisSession { fused_binding_validated: true, }); } - Ok(deferrals) + Ok(()) } /// Python's legacy analysis of a model the engine handed back, or why Python must answer. @@ -327,12 +265,14 @@ impl AnalysisSession { cleaned_sql, lineage_references: &model.lineage_references, recover: model.recover_cte_facts, + full_nullability: false, types: &self.available_types, nullability: &self.available_nullability, profile: RecoveryProfile { dialect: &self.request.dialect, function_return_types: &self.request.function_return_types, rules: self.request.nullability_rules.as_ref(), + callback: self.request.nullability_callback.as_ref(), }, }) }) @@ -353,9 +293,10 @@ impl AnalysisSession { } /// Python's `_complete_inferred_bindings` star and type pass for one wave. - fn complete_wave(&mut self, wave: usize) -> Result { - let mut deferrals: Vec = Vec::new(); - let mut star_pending_by_model: HashMap = HashMap::new(); + fn complete_wave(&mut self, wave: usize) -> Result<(), String> { + if self.cyclic { + return Ok(()); + } let mut candidates: Vec<(usize, Shapes, bool)> = Vec::new(); for model in self.waves[wave].clone() { if self.cached(model) { @@ -387,39 +328,19 @@ impl AnalysisSession { candidates.push((model, input_schemas, star_pending)); } } - let enrichments: Vec> = self.native_enrichments(&candidates)?; - for ((model, input_schemas, star_pending), native) in - candidates.into_iter().zip(enrichments) - { - let Some(native) = native else { - star_pending_by_model.insert(model, star_pending); - deferrals.push(Deferral::Enrichment { - model, - input_schemas, - }); - continue; - }; + let enrichments: Vec = self.native_enrichments(&candidates)?; + for ((model, _, star_pending), native) in candidates.into_iter().zip(enrichments) { let outcome: &mut ModelOutcome = self.outcome_mut(model)?; - outcome.analysis = enriched_analysis( - &outcome.analysis, - native_answer( - model, - native.analysis_succeeded, - native.columns, - native.has_star, - ), - star_pending, - LineageFacts::NativeFacts(native.lineage), - ); + outcome.analysis = enriched_analysis(&outcome.analysis, native, star_pending); } - Ok((deferrals, star_pending_by_model)) + Ok(()) } - /// Python's re-analysis of each candidate natively, None where Python must answer it. + /// Python's re-analysis of each candidate; the first failure in model order fails it. fn native_enrichments( &self, candidates: &[(usize, Shapes, bool)], - ) -> Result>, String> { + ) -> Result, String> { if candidates.is_empty() { return Ok(Vec::new()); } @@ -431,10 +352,24 @@ impl AnalysisSession { dialect: &self.request.dialect, function_return_types: &self.request.function_return_types, nullability_rules: self.request.nullability_rules.as_ref(), + nullability_callback: self.request.nullability_callback.as_ref(), }) .collect(); let pool = self.catalog.native.analysis_pool()?; - Ok(pool.install(|| inputs.par_iter().map(enrichment).collect())) + let enrichments: Vec> = + pool.install(|| inputs.par_iter().map(enrichment).collect()); + enrichments + .into_iter() + .zip(&inputs) + .map(|(enrichment, input)| { + enrichment.map_err(|reason| { + native_failure( + &format!("{} enrichment", model_context(input.model)), + &reason, + ) + }) + }) + .collect() } fn input_schemas(&self, required: &[String]) -> Shapes { @@ -460,7 +395,8 @@ impl AnalysisSession { fn finish_wave(&mut self, wave: usize) -> Result<(), String> { let models: Vec = self.waves[wave].clone(); let mut validations: Vec<(usize, String, Shapes)> = Vec::new(); - for model in &models { + let validated: &[usize] = if self.cyclic { &[] } else { &models }; + for model in validated { let schema: Shapes = self.binding_schema(&self.request.models[*model]); let outcome: &ModelOutcome = self.outcomes[*model] .as_ref() @@ -598,23 +534,16 @@ impl AnalysisSession { return; }; for model in models { - if cache.hits[*model] || cache.uncacheable[*model] { + if cache.hits[*model] { continue; } let (Some(key), Some(outcome)) = (cache.keys[*model], self.outcomes[*model].as_ref()) else { continue; }; - if let Some(bytes) = encode_outcome(outcome, cache.legacy_tables[*model].as_ref()) { - cache.store.put(key, bytes); - cache.stats.stored += 1; - } - } - } - - fn mark_uncacheable(&mut self, model: usize) { - if let Some(cache) = self.cache.as_mut() { - cache.uncacheable[model] = true; + let bytes: Vec = encode_outcome(outcome, cache.legacy_tables[*model].as_ref()); + cache.store.put(key, bytes); + cache.stats.stored += 1; } } @@ -756,41 +685,11 @@ fn legacy_outcome( } } -fn python_analysis(result: DeferredAnalysis) -> ModelAnalysis { - ModelAnalysis { - analysis_succeeded: result.analysis_succeeded, - columns: result.columns, - lineage: LineageFacts::PythonAnalysis, - has_star: result.has_star, - star_resolved: result.star_resolved, - binding_diagnostics: result.binding_diagnostics, - binding_validated: result.binding_validated, - } -} - -impl Deferral { - /// The deferred model's request index. - pub fn model(&self) -> usize { - match self { - Self::Analysis { model, .. } | Self::Enrichment { model, .. } => *model, - } - } - - /// Python's name for the deferral's kind. - pub fn kind(&self) -> &'static str { - match self { - Self::Analysis { .. } => DEFERRAL_ANALYSIS, - Self::Enrichment { .. } => DEFERRAL_ENRICHMENT, - } - } -} - /// Python's merge of a re-analysis with known inputs into the model's analysis. fn enriched_analysis( analysis: &ModelAnalysis, - enriched: DeferredAnalysis, + enriched: Enrichment, star_pending: bool, - lineage: LineageFacts, ) -> ModelAnalysis { let mut recovered: HashMap = HashMap::new(); for column in enriched @@ -810,9 +709,9 @@ fn enriched_analysis( ModelAnalysis { analysis_succeeded: enriched.analysis_succeeded, columns: enriched.columns, - lineage, + lineage: LineageFacts::NativeFacts(enriched.lineage), has_star: enriched.has_star, - star_resolved: enriched.star_resolved, + star_resolved: false, binding_diagnostics: analysis.binding_diagnostics.clone(), binding_validated: analysis.binding_validated, } @@ -830,40 +729,15 @@ fn enriched_analysis( merged } -/// A native re-analysis as Python's successful answer. -fn native_answer( - model: usize, - analysis_succeeded: bool, - columns: Option>, - has_star: bool, -) -> DeferredAnalysis { - DeferredAnalysis { - model, - analysis_succeeded, - columns, - has_star, - star_resolved: false, - binding_diagnostics: Vec::new(), - binding_validated: false, - } -} - -/// A compiled model's output names and lineage from a successful analysis with native lineage. +/// A model's typed output columns and lineage from a successful native-lineage analysis. fn session_model_facts(analysis: &ModelAnalysis) -> Option { - let rows: &Vec = match &analysis.lineage { - LineageFacts::Native(rows) | LineageFacts::NativeFacts(rows) => rows, - LineageFacts::PythonAnalysis | LineageFacts::PythonEnrichment => return None, - }; + let (LineageFacts::Native(rows) | LineageFacts::NativeFacts(rows)) = &analysis.lineage; analysis.analysis_succeeded.then(|| SessionModelFacts { - columns: analysis.columns.as_deref().map(column_names), + columns: analysis.columns.clone(), lineage: rows.iter().map(output_sources).collect(), }) } -fn column_names(columns: &[ColumnFact]) -> Vec { - columns.iter().map(|column| column.name.clone()).collect() -} - /// One lineage row as `(output column, [(resource name, column name)])`. fn output_sources(row: &LineageRow) -> (String, Vec<(String, String)>) { let mut sources: Vec<(String, String)> = Vec::with_capacity(row.sources.len()); @@ -872,3 +746,8 @@ fn output_sources(row: &LineageRow) -> (String, Vec<(String, String)>) { } (row.output_column.clone(), sources) } + +/// The failure context naming one model. +fn model_context(model: &ModelRequest) -> String { + format!("{SESSION_CONTEXT} of model '{}'", model.name) +} diff --git a/crates/sqlbuild-analysis/src/assembly/analysis_session/constants.rs b/crates/sqlbuild-analysis/src/assembly/analysis_session/constants.rs index 4bc16c6823..9417d4071e 100644 --- a/crates/sqlbuild-analysis/src/assembly/analysis_session/constants.rs +++ b/crates/sqlbuild-analysis/src/assembly/analysis_session/constants.rs @@ -37,9 +37,6 @@ pub(crate) const DIALECT_ALIASES: [(&str, &str); 3] = [ ]; /// The quote that marks an exact identifier. pub(crate) const QUOTED_IDENTIFIER_DELIMITER: char = '"'; -/// Python's names for a legacy-analysis and an enrichment deferral. -pub(crate) const DEFERRAL_ANALYSIS: &str = "analysis"; -pub(crate) const DEFERRAL_ENRICHMENT: &str = "enrichment"; /// Python's `ColumnTransformKind` compact codes. pub(crate) const TRANSFORM_DIRECT: u8 = 0; pub(crate) const TRANSFORM_CAST: u8 = 1; @@ -193,6 +190,10 @@ pub(crate) const JOIN_FULL: &str = "FULL"; /// Ids of the adapter nullability rules Python registers, by the function it calls. pub(crate) const FIRST_ARG_RULE: &str = "first_arg"; pub(crate) const CONDITIONAL_RESULT_RULE: &str = "conditional_result"; +/// The rule id of `safe_cast_nullability`. +pub(crate) const SAFE_CAST_RULE: &str = "safe_cast"; +/// The rule id of a project-local adapter's own rule, which the callback runs. +pub(crate) const PYTHON_RULE: &str = "python"; pub(crate) const NON_NULL_NULLABILITY: &str = "non_null"; pub(crate) const NULLABLE_NULLABILITY: &str = "nullable"; /// Bumped whenever the stored outcome or a key's fields change; older entries never match. @@ -205,3 +206,31 @@ pub(crate) const VARINT_PAYLOAD_MASK: u8 = 0x7f; pub(crate) const VARINT_PAYLOAD_BITS: u32 = 7; /// The most bytes one stored `u64` varint takes. pub(crate) const VARINT_MAX_BYTES: usize = 10; +/// Payload kinds and literal types Python's fixture projection facts read. +pub(crate) const NULL_PAYLOAD_KIND: &str = "null"; +pub(crate) const LITERAL_PAYLOAD_KIND: &str = "literal"; +pub(crate) const ARRAY_PAYLOAD_KIND: &str = "array_func"; +pub(crate) const STRUCTURED_PAYLOAD_KINDS: [&str; 2] = ["parse_json", "struct"]; +pub(crate) const FUNCTION_PAYLOAD_KIND: &str = "function"; +pub(crate) const SELECT_PAYLOAD_KEY: &str = "select"; +/// `{literal_type: type}` Python's `_simple_expression_type` maps a literal to. +pub(crate) const LITERAL_FIXTURE_TYPES: [(&str, &str); 3] = [ + ("string", "VARCHAR"), + ("number", "NUMBER"), + ("boolean", "BOOLEAN"), +]; +/// `{function name: type}` Python's `_simple_expression_type` maps a function to. +pub(crate) const FUNCTION_FIXTURE_TYPES: [(&str, &str); 3] = [ + ("ARRAY_CONSTRUCT", "ARRAY"), + ("OBJECT_CONSTRUCT", "OBJECT"), + ("PARSE_JSON", "VARIANT"), +]; +pub(crate) const ARRAY_FIXTURE_TYPE: &str = "ARRAY"; +pub(crate) const VARIANT_FIXTURE_TYPE: &str = "VARIANT"; +/// Dialect, payload keys and table args Python's SQL-test `_parsed_reads` reads. +pub(crate) const HELPER_READS_DIALECT: &str = "generic"; +pub(crate) const CTE_LIST_PAYLOAD_KEY: &str = "ctes"; +pub(crate) const CTE_ALIAS_PAYLOAD_KEY: &str = "alias"; +pub(crate) const NAME_PAYLOAD_KEY: &str = "name"; +pub(crate) const SCHEMA_TABLE_ARG: &str = "schema"; +pub(crate) const CATALOG_TABLE_ARG: &str = "catalog"; diff --git a/crates/sqlbuild-analysis/src/assembly/analysis_session/errors.rs b/crates/sqlbuild-analysis/src/assembly/analysis_session/errors.rs new file mode 100644 index 0000000000..5fe6f12f33 --- /dev/null +++ b/crates/sqlbuild-analysis/src/assembly/analysis_session/errors.rs @@ -0,0 +1,8 @@ +//! Why per-query column analysis outside the session fails. + +/// A query Python's normalization rejects (its `ValueError`), or an internal native failure. +#[derive(Debug, Clone, PartialEq, Eq)] +pub enum QueryColumnsFailure { + Normalization(String), + Internal(String), +} diff --git a/crates/sqlbuild-analysis/src/assembly/analysis_session/main/expression_shapes.rs b/crates/sqlbuild-analysis/src/assembly/analysis_session/main/expression_shapes.rs index 973018ff0f..b65c4a0ad7 100644 --- a/crates/sqlbuild-analysis/src/assembly/analysis_session/main/expression_shapes.rs +++ b/crates/sqlbuild-analysis/src/assembly/analysis_session/main/expression_shapes.rs @@ -1,11 +1,16 @@ //! Python's `get_expression_source_shapes` for expressions its catalog has not inferred. use crate::assembly::analysis_session::_helpers::catalog_state::SessionCatalog; +use sqlbuild_core::panics::main::catch_compiler_panic::catch_compiler_panic; + +use crate::assembly::analysis_session::_helpers::catalog_state::{ShapeOptions, ShapeSource}; use crate::assembly::analysis_session::_helpers::compact_batch::{ Batch, BatchMember, MemberAnalysis, MemberResult, }; +use crate::assembly::analysis_session::_helpers::cte_facts::{ + LegacyAnalysis, LegacyInput, RecoveryProfile, legacy_analysis, +}; use crate::assembly::analysis_session::_helpers::mappings::ShapeTable; -use crate::assembly::analysis_session::_helpers::publication::{ShapeOptions, ShapeSource}; use crate::assembly::analysis_session::_helpers::session::shape_columns; use crate::assembly::analysis_session::models::{ExpressionShape, ExpressionShapeRequest}; use crate::assembly::analysis_session::types::{Pairs, Shapes}; @@ -47,7 +52,38 @@ pub fn expression_shapes( let mut shapes: Vec = Vec::with_capacity(results.len()); for (expression, result) in request.expressions.iter().zip(results) { shapes.push(match result.analysis { - MemberAnalysis::Legacy { .. } => ExpressionShape::Deferred, + MemberAnalysis::Legacy { .. } => { + let legacy: LegacyAnalysis = catch_compiler_panic(|| { + legacy_analysis(&LegacyInput { + cleaned_sql: &result.cleaned_sql, + lineage_references: &[], + recover: true, + full_nullability: false, + types: &empty, + nullability: &empty, + profile: RecoveryProfile { + dialect: &request.dialect, + function_return_types: &request.function_return_types, + rules: request.nullability_rules.as_ref(), + callback: request.nullability_callback.as_ref(), + }, + }) + })?; + match legacy.columns { + Some(columns) if !columns.is_empty() && !legacy.has_star => { + ExpressionShape::Inferred(session_catalog.inferred_binding_shape( + &options, + ShapeSource { + sql: expression, + columns: shape_columns(&columns), + inputs: &no_inputs, + snapshot_columns: None, + }, + )?) + } + _ => ExpressionShape::Absent, + } + } MemberAnalysis::Projected { columns, has_star, .. } if !columns.is_empty() && !has_star => { diff --git a/crates/sqlbuild-analysis/src/assembly/analysis_session/main/finished_model_facts.rs b/crates/sqlbuild-analysis/src/assembly/analysis_session/main/finished_model_facts.rs index bac994679b..0d42f7e923 100644 --- a/crates/sqlbuild-analysis/src/assembly/analysis_session/main/finished_model_facts.rs +++ b/crates/sqlbuild-analysis/src/assembly/analysis_session/main/finished_model_facts.rs @@ -1,4 +1,4 @@ -//! The output names and lineage a finished analysis session kept for compiled models. +//! The typed output columns and lineage a finished analysis session kept for compiled models. use crate::assembly::analysis_session::models::{FinishedSession, SessionModelFacts}; diff --git a/crates/sqlbuild-analysis/src/assembly/analysis_session/main/mod.rs b/crates/sqlbuild-analysis/src/assembly/analysis_session/main/mod.rs index b65df1707f..a2aee74abf 100644 --- a/crates/sqlbuild-analysis/src/assembly/analysis_session/main/mod.rs +++ b/crates/sqlbuild-analysis/src/assembly/analysis_session/main/mod.rs @@ -3,11 +3,13 @@ pub mod expression_shapes; pub mod finish_analysis_session; pub mod finished_fact_models; pub mod finished_model_facts; +pub mod projection_facts; pub mod prove_dynamic_contracts; pub mod prove_finished_dynamic_contracts; -pub mod provide_deferred_analyses; +pub mod query_columns; pub mod recover_cte_facts; pub mod run_analysis_session; pub mod session_sharing; +pub mod sql_test_helper_reads; pub mod start_analysis_session; pub mod take_analysis_cache; diff --git a/crates/sqlbuild-analysis/src/assembly/analysis_session/main/projection_facts.rs b/crates/sqlbuild-analysis/src/assembly/analysis_session/main/projection_facts.rs new file mode 100644 index 0000000000..ada48a169a --- /dev/null +++ b/crates/sqlbuild-analysis/src/assembly/analysis_session/main/projection_facts.rs @@ -0,0 +1,9 @@ +//! Python's `_simple_projection_facts`: literal types, NULL literals and quoted aliases of a query. + +use crate::assembly::analysis_session::_helpers::dict_walk::fixture_projection_facts; +use crate::assembly::analysis_session::models::ProjectionFacts; + +/// The facts of the first `SELECT`; empty where the wheel's parse raises `PolyglotError`. +pub fn projection_facts(sql: &str, dialect: Option<&str>) -> Result { + fixture_projection_facts(sql, dialect) +} diff --git a/crates/sqlbuild-analysis/src/assembly/analysis_session/main/prove_dynamic_contracts.rs b/crates/sqlbuild-analysis/src/assembly/analysis_session/main/prove_dynamic_contracts.rs index bbbb199898..00af66fa58 100644 --- a/crates/sqlbuild-analysis/src/assembly/analysis_session/main/prove_dynamic_contracts.rs +++ b/crates/sqlbuild-analysis/src/assembly/analysis_session/main/prove_dynamic_contracts.rs @@ -1,10 +1,12 @@ //! Python's `analyze_dynamic_column_contract` for models no analysis session analysed. +use sqlbuild_core::constants::PANIC_MESSAGE; + use crate::assembly::analysis_session::_helpers::dynamic_pivot::pivot_outcomes; use crate::assembly::analysis_session::constants::PIVOT_WORKER_STACK_BYTES; use crate::assembly::analysis_session::models::{PivotBatchRequest, PivotOutcome}; -/// Each model's proof in order; a model whose proof panics is deferred to Python. +/// Each model's proof in order; an internal failure of any proof fails them all. pub fn prove_dynamic_contracts(request: &PivotBatchRequest) -> Result, String> { std::thread::scope(|scope| { std::thread::Builder::new() @@ -12,6 +14,6 @@ pub fn prove_dynamic_contracts(request: &PivotBatchRequest) -> Result Result, String> { let pool = session.pool.as_ref().map_err(Clone::clone)?; - Ok(pooled_pivot_outcomes(pool, models, &session.tables)) + pooled_pivot_outcomes(pool, models, &session.tables) } diff --git a/crates/sqlbuild-analysis/src/assembly/analysis_session/main/provide_deferred_analyses.rs b/crates/sqlbuild-analysis/src/assembly/analysis_session/main/provide_deferred_analyses.rs deleted file mode 100644 index ba205cd7c0..0000000000 --- a/crates/sqlbuild-analysis/src/assembly/analysis_session/main/provide_deferred_analyses.rs +++ /dev/null @@ -1,11 +0,0 @@ -//! Resume a native model analysis session with Python's answers. - -use crate::assembly::analysis_session::models::{AnalysisSession, DeferredAnalysis}; - -/// Answer the deferrals of the session's last step. -pub fn provide_deferred_analyses( - session: &mut AnalysisSession, - results: Vec, -) -> Result<(), String> { - session.provide(results) -} diff --git a/crates/sqlbuild-analysis/src/assembly/analysis_session/main/query_columns.rs b/crates/sqlbuild-analysis/src/assembly/analysis_session/main/query_columns.rs new file mode 100644 index 0000000000..33f14c2463 --- /dev/null +++ b/crates/sqlbuild-analysis/src/assembly/analysis_session/main/query_columns.rs @@ -0,0 +1,16 @@ +//! Python's per-query column analysis outside the session. + +use crate::assembly::analysis_session::_helpers::query_columns as columns; +use crate::assembly::analysis_session::errors::QueryColumnsFailure; +use crate::assembly::analysis_session::models::{QueryColumns, QueryColumnsRequest}; +use crate::semantic_validation::models::ProjectCatalog; + +/// Each query's columns, in order; `Parse` and `Legacy` SQL is normalized first, in order. +pub fn query_columns( + catalog: Option<&ProjectCatalog>, + request: &QueryColumnsRequest, +) -> Result, QueryColumnsFailure> { + let request: QueryColumnsRequest = + columns::normalized_request(request).map_err(QueryColumnsFailure::Normalization)?; + columns::query_columns(catalog, &request).map_err(QueryColumnsFailure::Internal) +} diff --git a/crates/sqlbuild-analysis/src/assembly/analysis_session/main/recover_cte_facts.rs b/crates/sqlbuild-analysis/src/assembly/analysis_session/main/recover_cte_facts.rs index 84aace7ca4..92b9f05478 100644 --- a/crates/sqlbuild-analysis/src/assembly/analysis_session/main/recover_cte_facts.rs +++ b/crates/sqlbuild-analysis/src/assembly/analysis_session/main/recover_cte_facts.rs @@ -28,6 +28,7 @@ fn recovered_facts(request: &CteFactRequest) -> Result { dialect: &request.dialect, function_return_types: &request.function_return_types, rules: request.nullability_rules.as_ref(), + callback: None, }, })?; let mut direct_outputs: Vec = recovered.direct_outputs.into_iter().collect(); diff --git a/crates/sqlbuild-analysis/src/assembly/analysis_session/main/run_analysis_session.rs b/crates/sqlbuild-analysis/src/assembly/analysis_session/main/run_analysis_session.rs index 0c3c2a5c68..9176377634 100644 --- a/crates/sqlbuild-analysis/src/assembly/analysis_session/main/run_analysis_session.rs +++ b/crates/sqlbuild-analysis/src/assembly/analysis_session/main/run_analysis_session.rs @@ -1,8 +1,8 @@ -//! Advance a native model analysis session to its next deferrals. +//! Run a native model analysis session over every wave. use crate::assembly::analysis_session::models::{AnalysisSession, SessionStep}; -/// Advance until Python must answer deferrals; a step without deferrals means done. +/// Analyse every wave; any internal native failure fails the whole analysis. pub fn run_analysis_session(session: &mut AnalysisSession) -> Result { session.run() } diff --git a/crates/sqlbuild-analysis/src/assembly/analysis_session/main/sql_test_helper_reads.rs b/crates/sqlbuild-analysis/src/assembly/analysis_session/main/sql_test_helper_reads.rs new file mode 100644 index 0000000000..cae1fdcf3b --- /dev/null +++ b/crates/sqlbuild-analysis/src/assembly/analysis_session/main/sql_test_helper_reads.rs @@ -0,0 +1,8 @@ +//! Unqualified reads of SQL-test helper CTE keys in one CTE body. + +use crate::assembly::analysis_session::_helpers::dict_walk::helper_parsed_reads; + +/// The `keys` (casefolded) `sql` reads, first read first; None where the SQL does not parse. +pub fn sql_test_helper_reads(sql: &str, keys: &[String]) -> Result>, String> { + helper_parsed_reads(sql, keys) +} diff --git a/crates/sqlbuild-analysis/src/assembly/analysis_session/main/start_analysis_session.rs b/crates/sqlbuild-analysis/src/assembly/analysis_session/main/start_analysis_session.rs index 3d716c5fe3..1eabc81c30 100644 --- a/crates/sqlbuild-analysis/src/assembly/analysis_session/main/start_analysis_session.rs +++ b/crates/sqlbuild-analysis/src/assembly/analysis_session/main/start_analysis_session.rs @@ -3,10 +3,10 @@ use crate::assembly::analysis_session::models::{AnalysisSession, SessionRequest}; use crate::semantic_validation::models::ProjectCatalog; -/// A session over `request` on a copy of `catalog`, or None where Python must analyse. +/// A session over `request` on a copy of `catalog`; fails on broken session invariants. pub fn start_analysis_session( request: SessionRequest, catalog: &ProjectCatalog, -) -> Option { +) -> Result { AnalysisSession::start(request, catalog) } diff --git a/crates/sqlbuild-analysis/src/assembly/analysis_session/mod.rs b/crates/sqlbuild-analysis/src/assembly/analysis_session/mod.rs index 536cf2088d..283fdb1307 100644 --- a/crates/sqlbuild-analysis/src/assembly/analysis_session/mod.rs +++ b/crates/sqlbuild-analysis/src/assembly/analysis_session/mod.rs @@ -2,6 +2,7 @@ pub(crate) mod _helpers; pub(crate) mod constants; +pub mod errors; pub mod main; pub mod models; pub mod types; diff --git a/crates/sqlbuild-analysis/src/assembly/analysis_session/models.rs b/crates/sqlbuild-analysis/src/assembly/analysis_session/models.rs index 4e020bdf17..bd0a141b75 100644 --- a/crates/sqlbuild-analysis/src/assembly/analysis_session/models.rs +++ b/crates/sqlbuild-analysis/src/assembly/analysis_session/models.rs @@ -1,6 +1,7 @@ //! Plain-data request, deferrals and outcomes of the native model analysis session. use std::collections::HashMap; +use std::fmt; use std::sync::Arc; use rayon::ThreadPool; @@ -9,7 +10,7 @@ use sqlbuild_cache::store::models::NativeStore; use crate::assembly::analysis_session::_helpers::catalog_state::SessionCatalog; use crate::assembly::analysis_session::_helpers::mappings::ShapeTable; -use crate::assembly::analysis_session::types::{OutputSources, Pairs, Shapes}; +use crate::assembly::analysis_session::types::{NullabilityRuleFn, OutputSources, Pairs, Shapes}; use crate::semantic_validation::types::DiagnosticRow; /// One `ref`, `source`, `seed`, `table_fn` or `udf` call a model's SQL makes. @@ -22,7 +23,7 @@ pub struct ModelReference { } /// One analysed model, with the facts Python derives from its compile input. -#[derive(Debug, Clone)] +#[derive(Debug, Clone, Default)] pub struct ModelRequest { pub name: String, /// Cursor-intrinsic analysis SQL. @@ -96,20 +97,50 @@ pub struct FinishedSession { pub(crate) tables: PivotTables, pub(crate) pool: Result, String>, pub(crate) models: HashMap, + /// Each model's dynamic pivot proof from the session's own relation facts, by model name. + pub(crate) dynamic_proofs: HashMap, +} + +/// The session's typed result for one compiled model, borrowed from the finished session. +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub struct SessionModelAnalysis<'a> { + /// Whether the session's analysis of the model succeeded; false also for unanalysed names. + pub succeeded: bool, + /// A proven pivot's fixed columns, else a successful analysis's; None where later decided. + pub columns: Option<&'a [ColumnFact]>, + /// The session's dynamic pivot proof, for a model declaring dynamic families. + pub dynamic_proof: Option<&'a ContractProof>, } -/// A compiled model's output names and lineage from an analysis the session completed natively. +impl FinishedSession { + /// The session's typed columns and dynamic proof for model `name`, without re-analysis. + #[must_use] + pub fn model_analysis(&self, name: &str) -> SessionModelAnalysis<'_> { + let dynamic_proof: Option<&ContractProof> = self.dynamic_proofs.get(name); + let proven: Option<&[ColumnFact]> = dynamic_proof + .filter(|proof| proof.output_proven) + .map(|proof| proof.fixed_columns.as_slice()); + let facts: Option<&SessionModelFacts> = self.models.get(name); + let analysed: Option<&[ColumnFact]> = facts.and_then(|facts| facts.columns.as_deref()); + SessionModelAnalysis { + succeeded: facts.is_some(), + columns: proven.or(analysed), + dynamic_proof, + } + } +} + +/// A compiled model's typed output columns and lineage from a native session analysis. #[derive(Debug, Clone, PartialEq, Eq)] pub struct SessionModelFacts { - pub columns: Option>, + pub columns: Option>, pub lineage: OutputSources, } -/// A model's dynamic pivot proof: none declared, left to Python, or proven natively. +/// A model's dynamic pivot proof: none declared, or proven natively. #[derive(Debug, Clone, PartialEq, Eq)] pub enum PivotOutcome { Absent, - Deferred, Proof(ContractProof), } @@ -121,8 +152,10 @@ pub struct SessionRequest { /// Whether published shapes keep authored quoting, Python's `inferred_binding_shape` test. pub case_sensitive_shapes: bool, pub function_return_types: Pairs, - /// Adapter nullability rules as `(function name, rule id)`; None where one is not Python's. + /// Adapter nullability rules as `(function name, rule id)`. pub nullability_rules: Option, + /// Runs the adapter's own rules, those with the `python` rule id. + pub nullability_callback: Option, pub rich_type_inference: bool, pub column_types: Shapes, pub column_nullability: Shapes, @@ -156,10 +189,6 @@ pub struct LineageRow { pub enum LineageFacts { /// Native compact rows. Native(Vec), - /// The lineage of the analysis Python returned for this model's analysis deferral. - PythonAnalysis, - /// The lineage of the analysis Python returned for this model's enrichment deferral. - PythonEnrichment, /// Plain lineage facts of a native re-analysis or legacy analysis. NativeFacts(Vec), } @@ -185,40 +214,11 @@ pub struct ModelOutcome { pub fused_binding_validated: bool, } -/// Work native analysis hands back to Python for one model. -#[derive(Debug, Clone, PartialEq, Eq)] -pub enum Deferral { - /// The native engine asked for Python's legacy analysis of this model. - Analysis { - model: usize, - cleaned_sql: String, - binding_schema: Shapes, - binding_diagnostics: Vec, - /// Lineage Python projects from native rows, when the engine kept them. - lineage: Option>, - }, - /// Re-analysis with the model's known input shapes. - Enrichment { model: usize, input_schemas: Shapes }, -} - -/// Python's answer to one deferral, without the lineage Python keeps. -#[derive(Debug, Clone, PartialEq, Eq)] -pub struct DeferredAnalysis { - pub model: usize, - pub analysis_succeeded: bool, - pub columns: Option>, - pub has_star: bool, - pub star_resolved: bool, - pub binding_diagnostics: Vec, - pub binding_validated: bool, -} - -/// One phase of the session: the deferrals Python must answer, or none when it is done. +/// The finished run of the session: what Python records from it. #[derive(Debug, Clone, Default, PartialEq, Eq)] pub struct SessionStep { - /// Shapes published since the previous step, in publication order. + /// Shapes published by the run, in publication order. pub publications: Shapes, - pub deferrals: Vec, /// Native analysis failures Python logs at debug level. pub failures: Vec, } @@ -240,7 +240,6 @@ pub struct SessionOutcome { pub enum ExpressionShape { Inferred(Pairs), Absent, - Deferred, } /// What expression-source shape inference reads from the inference profile. @@ -249,29 +248,19 @@ pub struct ExpressionShapeRequest { pub dialect: String, pub case_sensitive_shapes: bool, pub function_return_types: Pairs, + /// Adapter nullability rules as `(function name, rule id)`. + pub nullability_rules: Option, + /// Runs the adapter's own rules, those with the `python` rule id. + pub nullability_callback: Option, pub expressions: Vec, } -/// Deferrals the session waits on before it continues a wave. -#[derive(Debug)] -pub(crate) enum Awaiting { - Analyses { - wave: usize, - models: Vec, - }, - Enrichments { - wave: usize, - star_pending: HashMap, - }, -} - /// Where the session is within its waves. #[derive(Debug)] pub(crate) enum Phase { Analyze, Complete(usize), Finish(usize), - Await(Awaiting), Done, } @@ -291,19 +280,19 @@ pub struct AnalysisCache { pub(crate) session_digest: ContentDigest, pub(crate) keys: Vec>, pub(crate) hits: Vec, - /// Models whose outcome must not be stored: a logged failure or Python's answer. - pub(crate) uncacheable: Vec, /// The whole-table digest each legacy analysis read; its entry also requires it. pub(crate) legacy_tables: Vec>, pub(crate) stats: AnalysisCacheStats, } -/// One compile's model analysis, advanced phase by phase and resumed with Python's answers. +/// One compile's model analysis, advanced phase by phase. #[derive(Debug)] pub struct AnalysisSession { pub(crate) request: SessionRequest, pub(crate) catalog: SessionCatalog, pub(crate) dependency_ordered: bool, + /// Whether models `ref` each other in a cycle, so Python's completion pass is skipped. + pub(crate) cyclic: bool, pub(crate) waves: Vec>, pub(crate) next_wave: usize, pub(crate) available_types: ShapeTable, @@ -316,6 +305,57 @@ pub struct AnalysisSession { pub(crate) cache: Option, } +/// Which of Python's column analyses one query outside the session takes. +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum QueryColumnsMode { + /// The precomputed compact batch: a failed analysis has no columns. + Batch, + /// Compact re-analysis over the input types, then the parsed tree where it declines. + Reanalysis, + /// `infer_columns_with_sql_analysis`: the parsed tree only. + Parse, + /// `analyze_columns_and_lineage_with_polyglot` with compact analysis off: the parsed tree. + Legacy, +} + +/// One query outside the session whose columns Python inferred. +#[derive(Debug, Clone)] +pub struct QueryColumnsInput { + /// The model SQL; in `Parse` and `Legacy` modes, already through Python's normalization. + pub sql: String, + pub placeholders: Pairs, + /// Every reference's analysis name, in reference order. + pub analysis_names: Vec, + /// Python's `lineage_reference_map` items. + pub lineage_references: Vec<(String, String, String)>, + pub recover_cte_facts: bool, + pub mode: QueryColumnsMode, +} + +/// The queries, with the profile settings and relation facts their analysis reads. +#[derive(Debug, Clone, Default)] +pub struct QueryColumnsRequest { + pub dialect: String, + /// The unaliased `profile.sql_analysis_dialect or "generic"` normalization reads. + pub normalization_dialect: String, + pub function_return_types: Pairs, + /// Adapter nullability rules as `(function name, rule id)`. + pub nullability_rules: Option, + /// Runs the adapter's own rules, those with the `python` rule id. + pub nullability_callback: Option, + pub types: Shapes, + pub nullability: Shapes, + pub queries: Vec, +} + +/// One query's analysis: whether it succeeded, its columns and whether it projects a star. +#[derive(Debug, Clone, Default, PartialEq, Eq)] +pub struct QueryColumns { + pub succeeded: bool, + pub columns: Option>, + pub has_star: bool, +} + /// One query's CTE fact recovery, as Python's compact enrichment runs it. #[derive(Debug, Clone)] pub struct CteFactRequest { @@ -342,3 +382,85 @@ pub struct CteFacts { /// Sorted outputs a filter proves non-null. pub non_null_outputs: Vec, } + +/// The callback that runs project-local adapter nullability rules, the `python` rule id. +#[derive(Clone)] +pub struct NullabilityCallback(pub Arc); + +impl fmt::Debug for NullabilityCallback { + fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { + formatter.write_str("NullabilityCallback") + } +} + +/// Python's `_simple_projection_facts` of a fixture query; names are casefolded. +#[derive(Debug, Clone, Default, PartialEq, Eq)] +pub struct ProjectionFacts { + /// `(name, type)` in projection order; a later projection of a name wins. + pub types: Vec<(String, String)>, + pub null_literal_names: Vec, + pub quoted_names: Vec, +} + +/// One model's analysis results, which `model_columns` applies in `_assemble_model`'s order. +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub struct ModelColumnsInput<'a> { + /// The model's analysis is enabled (`sql_analysis_enabled` for this model). + pub analysis_enabled: bool, + /// The finished session's result for the model. + pub session: SessionModelAnalysis<'a>, + /// The `Parse` mode `query_columns` result, required when enabled and the session failed. + pub fallback: Option<&'a QueryColumns>, + /// A standalone pivot proof, for a model with families the session did not analyse. + pub standalone_proof: Option<&'a ContractProof>, + /// Output columns type recovery poisoned for this model (`TypeRecoveryPlan::poisoned`). + pub poisoned: &'a [String], +} + +/// A model's final output columns, as `CompiledModel` carries them after type recovery. +#[derive(Debug, Clone, Default, PartialEq, Eq)] +pub struct ModelColumns { + /// `inferred_columns`; a poisoned column has no type. + pub columns: Option>, + /// A proven pivot forces `fast_lineage_has_star`. + pub proven_star: bool, + /// `unchecked_output_columns`: every poisoned name, in plan order. + pub unchecked: Vec, +} + +impl ModelColumnsInput<'_> { + /// `_assemble_model`'s columns, then `_recovered_model`'s; Err where the fallback is missing. + pub fn model_columns(&self) -> Result { + let analysed: Option> = if !self.analysis_enabled { + None + } else if self.session.succeeded { + self.session.columns.map(<[ColumnFact]>::to_vec) + } else { + self.fallback + .ok_or("a failed session analysis without its parse fallback")? + .columns + .clone() + }; + let proven: Option<&ContractProof> = self + .session + .dynamic_proof + .or(self.standalone_proof) + .filter(|proof| proof.output_proven); + let columns: Option> = proven + .map(|proof| proof.fixed_columns.clone()) + .or(analysed) + .map(|mut columns| { + for column in &mut columns { + if self.poisoned.contains(&column.name) { + column.data_type = None; + } + } + columns + }); + Ok(ModelColumns { + columns, + proven_star: proven.is_some(), + unchecked: self.poisoned.to_vec(), + }) + } +} diff --git a/crates/sqlbuild-analysis/src/assembly/analysis_session/tests.rs b/crates/sqlbuild-analysis/src/assembly/analysis_session/tests.rs index a3cfec2ac5..f9737f30b6 100644 --- a/crates/sqlbuild-analysis/src/assembly/analysis_session/tests.rs +++ b/crates/sqlbuild-analysis/src/assembly/analysis_session/tests.rs @@ -8,5 +8,7 @@ mod expression_shapes; mod helpers; #[path = "tests/test_mappings.rs"] mod mappings; +#[path = "tests/test_model_columns.rs"] +mod model_columns; #[path = "tests/test_types.rs"] mod test_types; diff --git a/crates/sqlbuild-analysis/src/assembly/analysis_session/tests/helpers.rs b/crates/sqlbuild-analysis/src/assembly/analysis_session/tests/helpers.rs index 137ae96f67..16b5f60f76 100644 --- a/crates/sqlbuild-analysis/src/assembly/analysis_session/tests/helpers.rs +++ b/crates/sqlbuild-analysis/src/assembly/analysis_session/tests/helpers.rs @@ -12,17 +12,18 @@ use crate::assembly::analysis_session::main::attach_analysis_cache::attach_analy use crate::assembly::analysis_session::main::finish_analysis_session::finish_analysis_session; use crate::assembly::analysis_session::main::finished_fact_models::finished_fact_models; use crate::assembly::analysis_session::main::finished_model_facts::finished_model_facts; -use crate::assembly::analysis_session::main::provide_deferred_analyses::provide_deferred_analyses; use crate::assembly::analysis_session::main::run_analysis_session::run_analysis_session; use crate::assembly::analysis_session::main::start_analysis_session::start_analysis_session; use crate::assembly::analysis_session::main::take_analysis_cache::take_analysis_cache; use crate::assembly::analysis_session::models::{ - AnalysisCacheStats, AnalysisSession, ColumnFact, ContractProof, Deferral, DeferredAnalysis, - DynamicFamily, FinishedSession, LineageRow, ModelOutcome, ModelReference, ModelRequest, - PivotBatchRequest, PivotModel, PivotOutcome, PivotTables, SessionModelFacts, SessionOutcome, + AnalysisCacheStats, AnalysisSession, ColumnFact, ContractProof, DynamicFamily, FinishedSession, + LineageRow, ModelColumns, ModelOutcome, ModelReference, ModelRequest, PivotBatchRequest, + PivotModel, PivotOutcome, PivotTables, SessionModelAnalysis, SessionModelFacts, SessionOutcome, SessionRequest, SessionStep, }; -use crate::assembly::analysis_session::tests::test_types::{CachedRun, ModelSpec, RecoveredFacts}; +use crate::assembly::analysis_session::tests::test_types::{ + CachedRun, ColumnView, ModelSpec, RecoveredFacts, +}; use crate::assembly::analysis_session::types::{Pairs, Shapes}; use crate::semantic_validation::models::{CatalogInput, ProjectCatalog}; @@ -120,6 +121,7 @@ pub(crate) fn orders_request(models: Vec) -> SessionRequest { case_sensitive_shapes: false, function_return_types: Vec::new(), nullability_rules: Some(Vec::new()), + nullability_callback: None, rich_type_inference: true, column_types: raw_orders.clone(), column_nullability: shapes(&[( @@ -135,37 +137,24 @@ pub(crate) fn orders_request(models: Vec) -> SessionRequest { pub(crate) fn started(request: SessionRequest) -> AnalysisSession { let catalog: ProjectCatalog = catalog(&request.dialect, &request.catalog_schemas); - start_analysis_session(request, &catalog).expect("the models form no cycle") + start_analysis_session(request, &catalog).expect("the session starts") } -/// Run to completion, answering every deferral with `answer`: the steps, outcomes and session. +/// Run to completion: the step, outcomes and session. pub(crate) fn completed( session: AnalysisSession, - answer: fn(&Deferral) -> DeferredAnalysis, ) -> (Vec, Vec, FinishedSession) { - let (steps, outcome, finished, ()) = completed_with(session, answer, |_| ()); + let (steps, outcome, finished, ()) = completed_with(session, |_| ()); (steps, outcome.models, finished) } /// [`completed`], reading the session with `before_finish` once every wave has run. pub(crate) fn completed_with( mut session: AnalysisSession, - answer: fn(&Deferral) -> DeferredAnalysis, before_finish: impl FnOnce(&mut AnalysisSession) -> T, ) -> (Vec, SessionOutcome, FinishedSession, T) { - let mut done: bool = false; - let steps: Vec = std::iter::from_fn(|| { - (!done).then(|| { - let step: SessionStep = run_analysis_session(&mut session).expect("the session runs"); - let answers: Vec = step.deferrals.iter().map(answer).collect(); - done = answers.is_empty(); - (!done).then(|| { - provide_deferred_analyses(&mut session, answers).expect("the answers match") - }); - step - }) - }) - .collect(); + let steps: Vec = + vec![run_analysis_session(&mut session).expect("the session runs")]; let read: T = before_finish(&mut session); let (outcome, finished) = finish_analysis_session(session).expect("the session finished"); (steps, outcome, finished, read) @@ -176,7 +165,7 @@ pub(crate) fn cached_run(request: SessionRequest, store: NativeStore) -> CachedR let mut session: AnalysisSession = started(request); attach_analysis_cache(&mut session, store); let (steps, outcome, finished, (keys, hits, (store, stats))) = - completed_with(session, empty_answer, |session| { + completed_with(session, |session| { let (keys, hits) = session .cache .as_ref() @@ -200,7 +189,7 @@ pub(crate) fn cached_run(request: SessionRequest, store: NativeStore) -> CachedR /// The catalog changes and fact models of `request` run without a cache. pub(crate) fn uncached_catalog(request: SessionRequest) -> (Shapes, Vec, Vec) { - let (_, outcome, finished, ()) = completed_with(started(request), empty_answer, |_| ()); + let (_, outcome, finished, ()) = completed_with(started(request), |_| ()); catalog_changes(outcome, &finished) } @@ -244,20 +233,7 @@ pub(crate) fn described(outcome: &ModelOutcome) -> Vec { lines } -/// A successful Python answer with no columns and no star. -pub(crate) fn empty_answer(deferral: &Deferral) -> DeferredAnalysis { - DeferredAnalysis { - model: deferral.model(), - analysis_succeeded: true, - columns: None, - has_star: false, - star_resolved: false, - binding_diagnostics: Vec::new(), - binding_validated: true, - } -} - -/// `publish name col:TYPE ...` per publication, then `defer kind model` per deferral. +/// `publish name col:TYPE ...` per publication. pub(crate) fn step_lines(step: &SessionStep) -> Vec { let mut lines: Vec = Vec::new(); for (name, shape) in &step.publications { @@ -267,11 +243,6 @@ pub(crate) fn step_lines(step: &SessionStep) -> Vec { .collect(); lines.push(format!("publish {name} {}", columns.join(" "))); } - lines.extend( - step.deferrals - .iter() - .map(|deferral| format!("defer {} {}", deferral.kind(), deferral.model())), - ); lines } @@ -284,10 +255,7 @@ pub(crate) fn model_requests(models: &[ModelSpec]) -> Vec { /// Run `models` over the orders request: each step's lines and each model's description. pub(crate) fn session_lines(models: &[ModelSpec]) -> (Vec>, Vec>) { - let (steps, outcomes, _) = completed( - started(orders_request(model_requests(models))), - empty_answer, - ); + let (steps, outcomes, _) = completed(started(orders_request(model_requests(models)))); ( steps.iter().map(step_lines).collect(), outcomes.iter().map(described).collect(), @@ -296,10 +264,7 @@ pub(crate) fn session_lines(models: &[ModelSpec]) -> (Vec>, Vec Vec { - let (_, _, finished) = completed( - started(orders_request(model_requests(models))), - empty_answer, - ); + let (_, _, finished) = completed(started(orders_request(model_requests(models)))); models .iter() .map(|(name, ..)| { @@ -314,7 +279,56 @@ fn fact_line(facts: &SessionModelFacts) -> String { .iter() .map(|(output, sources)| format!("{output}<-{sources:?}")) .collect(); - format!("{:?} {}", facts.columns, lineage.join(" ")) + let columns: Option> = facts + .columns + .as_ref() + .map(|columns| columns.iter().map(column_line).collect()); + format!("{columns:?} {}", lineage.join(" ")) +} + +/// The proof and published columns a finished session keeps for `pivot_request`'s models. +pub(crate) fn kept_model_analyses( + dialect: &str, + sql: &str, + family: Option<(&str, &str, &str)>, +) -> Vec<(PivotOutcome, Option>)> { + let pivots: PivotBatchRequest = pivot_request(dialect, sql, family); + let names: [&str; 2] = ["customer_amounts", "plain"]; + let models: Vec = names + .iter() + .zip(pivots.models) + .map(|(name, pivot)| ModelRequest { + pivot_sql: pivot.sql.clone(), + dynamic_families: pivot.families, + ..model(name, &pivot.sql, &["raw_orders"], &[]) + }) + .collect(); + let tables: PivotTables = pivots.tables; + let request = SessionRequest { + dialect: tables.dialect, + column_types: tables.column_types.clone(), + column_nullability: tables.column_nullability, + complete_schemas: tables.authoritative_types, + catalog_schemas: tables.column_types, + dynamic_families_by_table: tables.families_by_table, + ..orders_request(models) + }; + let (_, _, finished) = completed(started(request)); + names + .iter() + .map(|name| kept_line(finished.model_analysis(name))) + .collect() +} + +fn kept_line(analysis: SessionModelAnalysis<'_>) -> (PivotOutcome, Option>) { + let proof: PivotOutcome = analysis + .dynamic_proof + .cloned() + .map_or(PivotOutcome::Absent, PivotOutcome::Proof); + let columns: Option> = analysis + .columns + .map(|columns| columns.iter().map(column_line).collect()); + (proof, columns) } /// Proofs over typed `raw_orders` and pivot `status_amounts`: the model, then a family-less one. @@ -369,6 +383,7 @@ pub(crate) fn finished_session(tables: PivotTables) -> FinishedSession { tables, pool: catalog("duckdb", &Vec::new()).analysis_pool(), models: HashMap::new(), + dynamic_proofs: HashMap::new(), } } @@ -439,6 +454,7 @@ pub(crate) fn recovered_facts(sql: &str) -> Option<(Pairs, Pairs, Vec, V dialect: "duckdb", function_return_types: &Vec::new(), rules: Some(&rules), + callback: None, }, }) .ok()?; @@ -510,12 +526,14 @@ pub(crate) fn legacy_lines(sql: &str) -> Option> { cleaned_sql: sql, lineage_references: &references, recover: true, + full_nullability: false, types: &types, nullability: &nullability, profile: RecoveryProfile { dialect: "duckdb", function_return_types: &Vec::new(), rules: Some(&rules), + callback: None, }, }) .ok()?; @@ -594,3 +612,45 @@ pub(crate) fn current_model_key(session: &AnalysisSession, name: &str) -> Conten .collect(); session.model_key(&ContentDigest::default(), model, &Vec::new(), &relations) } + +/// Owned copies of expected lines. +pub(crate) fn lines(expected: &[&str]) -> Vec { + expected.iter().map(|line| (*line).to_owned()).collect() +} + +/// `(name, type)` pairs as typed columns of unknown nullability. +pub(crate) fn fact_columns(pairs: &[(&str, &str)]) -> Vec { + pairs + .iter() + .map(|(name, data_type)| ColumnFact { + name: (*name).to_owned(), + data_type: Some((*data_type).to_owned()), + nullability: "unknown".to_owned(), + }) + .collect() +} + +/// A pivot proof with these fixed columns. +pub(crate) fn contract_proof((output_proven, fixed): (bool, &[(&str, &str)])) -> ContractProof { + ContractProof { + output_proven, + fixed_columns: fact_columns(fixed), + families: Vec::new(), + input_relations: Vec::new(), + failure_reason: None, + bare_dynamic_pivot: false, + } +} + +/// Final columns as `(name, type)` pairs and the forced star, for comparison with expectations. +pub(crate) fn column_view(finished: &ModelColumns) -> ColumnView<'_> { + ( + finished.columns.as_ref().map(|columns| { + columns + .iter() + .map(|column| (column.name.as_str(), column.data_type.as_deref())) + .collect() + }), + finished.proven_star, + ) +} diff --git a/crates/sqlbuild-analysis/src/assembly/analysis_session/tests/test_analysis_cache.rs b/crates/sqlbuild-analysis/src/assembly/analysis_session/tests/test_analysis_cache.rs index b531a45915..24c55a4b51 100644 --- a/crates/sqlbuild-analysis/src/assembly/analysis_session/tests/test_analysis_cache.rs +++ b/crates/sqlbuild-analysis/src/assembly/analysis_session/tests/test_analysis_cache.rs @@ -87,7 +87,7 @@ fn given_a_filled_cache_when_rerunning_then_hits_match_the_uncached_session() { expected_stats: [(0, 2, 2), (2, 0, 0)], }, CacheReuseTestCase { - description: "a model Python analyses is never stored", + description: "non-ASCII models analysed natively are stored", models: &[ ( "events", @@ -103,7 +103,7 @@ fn given_a_filled_cache_when_rerunning_then_hits_match_the_uncached_session() { &["events"], ), ], - expected_stats: [(0, 2, 1), (1, 1, 0)], + expected_stats: [(0, 2, 2), (2, 0, 0)], }, CacheReuseTestCase { description: "a natively answered legacy fallback and a failed analysis are stored", @@ -354,7 +354,7 @@ fn given_any_analysis_input_changed_when_keying_then_the_key_changes() { }, CacheKeyTestCase { description: "dialect", - change: |request| request.dialect = "postgres".to_owned(), + change: |request| request.dialect = "postgresql".to_owned(), expected_key_changed: true, }, CacheKeyTestCase { diff --git a/crates/sqlbuild-analysis/src/assembly/analysis_session/tests/test_analysis_session.rs b/crates/sqlbuild-analysis/src/assembly/analysis_session/tests/test_analysis_session.rs index 50f4d2dab9..03e6f7d0fc 100644 --- a/crates/sqlbuild-analysis/src/assembly/analysis_session/tests/test_analysis_session.rs +++ b/crates/sqlbuild-analysis/src/assembly/analysis_session/tests/test_analysis_session.rs @@ -1,18 +1,28 @@ use crate::assembly::analysis_session::main::prove_dynamic_contracts::prove_dynamic_contracts; use crate::assembly::analysis_session::main::prove_finished_dynamic_contracts::prove_finished_dynamic_contracts; +use crate::assembly::analysis_session::main::run_analysis_session::run_analysis_session; use crate::assembly::analysis_session::main::start_analysis_session::start_analysis_session; use crate::assembly::analysis_session::models::PivotOutcome; use crate::assembly::analysis_session::tests::helpers::{ - catalog, expected_facts, fact_lines, failed, finished_session, legacy_lines, model_requests, - orders_request, pivot_request, proven, recovered_facts, session_lines, + catalog, expected_facts, fact_lines, failed, finished_session, kept_model_analyses, + legacy_lines, lines, model_requests, orders_request, pivot_request, proven, recovered_facts, + session_lines, }; use crate::assembly::analysis_session::tests::test_types::{ - CteRecoveryTestCase, LegacyAnalysisTestCase, PivotTestCase, SessionFactsTestCase, - SessionTestCase, UnscheduledTestCase, + CteRecoveryTestCase, KeptAnalysisTestCase, LegacyAnalysisTestCase, ModelSpec, PivotTestCase, + SessionFactsTestCase, SessionFailureTestCase, SessionTestCase, UnscheduledTestCase, }; +/// A model whose missing column stays untyped over a known input, so completion re-analyses it. +const UNTYPED_ORDERS: ModelSpec = ( + "orders_untyped", + "SELECT order_id, missing_column FROM __source(\"raw_orders\")", + &["raw_orders"], + &[], +); + #[test] -fn given_models_when_running_the_session_then_defers_and_publishes_as_python_does() { +fn given_models_when_running_the_session_then_publishes_as_python_does() { let test_cases = [ SessionTestCase { description: "typed producers publish closed shapes their consumers bind", @@ -106,7 +116,7 @@ fn given_models_when_running_the_session_then_defers_and_publishes_as_python_doe ], }, SessionTestCase { - description: "a non-ASCII filter column Python casefolds still defers to Python", + description: "a non-ASCII filter column is analysed natively", models: &[ ( "events", @@ -122,16 +132,19 @@ fn given_models_when_running_the_session_then_defers_and_publishes_as_python_doe &["events"], ), ], - expected_steps: &[ - &["publish events gr\u{f6}\u{df}e:UNKNOWN", "defer analysis 1"], - &[], - ], + expected_steps: &[&[ + "publish events gr\u{f6}\u{df}e:UNKNOWN", + "publish events_mart gr\u{f6}\u{df}e:UNKNOWN", + ]], expected_outcomes: &[ &[ "gr\u{f6}\u{df}e - unknown", "succeeded=true star=false/false diagnostics=[]", ], - &["succeeded=true star=false/false diagnostics=[]"], + &[ + "gr\u{f6}\u{df}e - non_null", + "succeeded=true star=false/false diagnostics=[]", + ], ], }, SessionTestCase { @@ -165,7 +178,7 @@ fn given_models_when_running_the_session_then_defers_and_publishes_as_python_doe fn given_finished_sessions_when_reading_model_facts_then_keeps_only_native_successes() { let test_cases = [ SessionFactsTestCase { - description: "native lineage keeps output names and sources", + description: "native lineage keeps typed output columns and sources", models: &[ ( "stg_orders", @@ -181,14 +194,14 @@ fn given_finished_sessions_when_reading_model_facts_then_keeps_only_native_succe ), ], expected_facts: &[ - "Some([\"order_id\", \"doubled\"]) \ + "Some([\"order_id INTEGER non_null\", \"doubled DOUBLE unknown\"]) \ order_id<-[(\"raw_orders\", \"order_id\")] \ doubled<-[(\"raw_orders\", \"amount\")]", - "Some([\"missing_column\"]) missing_column<-[(\"raw_orders\", \"missing_column\")]", + "Some([\"missing_column - unknown\"]) missing_column<-[(\"raw_orders\", \"missing_column\")]", ], }, SessionFactsTestCase { - description: "a native legacy analysis keeps its output names and sources", + description: "a native legacy analysis keeps its typed output columns and sources", models: &[ ( "events", @@ -204,12 +217,12 @@ fn given_finished_sessions_when_reading_model_facts_then_keeps_only_native_succe ), ], expected_facts: &[ - "Some([\"event_id\"]) event_id<-[(\"raw_events\", \"event_id\")]", - "Some([\"event_id\", \"one\"]) event_id<-[(\"events\", \"event_id\")] one<-[]", + "Some([\"event_id - unknown\"]) event_id<-[(\"raw_events\", \"event_id\")]", + "Some([\"event_id - unknown\", \"one INT non_null\"]) event_id<-[(\"events\", \"event_id\")] one<-[]", ], }, SessionFactsTestCase { - description: "a model Python analysed keeps no session facts", + description: "a non-ASCII model analysed natively keeps its session facts", models: &[ ( "events", @@ -226,8 +239,8 @@ fn given_finished_sessions_when_reading_model_facts_then_keeps_only_native_succe ), ], expected_facts: &[ - "Some([\"gr\u{f6}\u{df}e\"]) gr\u{f6}\u{df}e<-[(\"raw_events\", \"event_id\")]", - "none", + "Some([\"gr\u{f6}\u{df}e - unknown\"]) gr\u{f6}\u{df}e<-[(\"raw_events\", \"event_id\")]", + "Some([\"gr\u{f6}\u{df}e - non_null\"]) gr\u{f6}\u{df}e<-[(\"events\", \"gr\u{f6}\u{df}e\")]", ], }, ]; @@ -242,10 +255,10 @@ fn given_finished_sessions_when_reading_model_facts_then_keeps_only_native_succe } #[test] -fn given_unschedulable_models_when_starting_then_python_analyses() { +fn given_models_when_starting_then_only_duplicate_names_fail_as_an_internal_error() { let test_cases = [ UnscheduledTestCase { - description: "models that reference each other", + description: "models that reference each other analyse in one unordered wave", models: &[ ( "orders", @@ -260,7 +273,7 @@ fn given_unschedulable_models_when_starting_then_python_analyses() { &["orders"], ), ], - expected_started: false, + expected_error: None, }, UnscheduledTestCase { description: "two models with one name", @@ -268,7 +281,9 @@ fn given_unschedulable_models_when_starting_then_python_analyses() { ("orders", "SELECT 1 AS order_id", &[], &[]), ("orders", "SELECT 2 AS order_id", &[], &[]), ], - expected_started: false, + expected_error: Some( + "NativeCompilerError: native model analysis: two analysed models share a name", + ), }, ]; for test_case in test_cases { @@ -276,8 +291,46 @@ fn given_unschedulable_models_when_starting_then_python_analyses() { let catalog = catalog(&request.dialect, &request.catalog_schemas); assert_eq!( - start_analysis_session(request, &catalog).is_some(), - test_case.expected_started, + start_analysis_session(request, &catalog).err().as_deref(), + test_case.expected_error, + "{}", + test_case.description + ); + } +} + +#[test] +fn given_enrichment_dialect_when_running_then_answers_natively_or_fails_internally() { + let test_cases = [ + SessionFailureTestCase { + description: "the dialect compile passes for the postgres adapter", + dialect: "postgresql", + models: &[UNTYPED_ORDERS], + expected_error: None, + }, + SessionFailureTestCase { + description: "an adapter alias compile maps before analysis never reaches the session", + dialect: "postgres", + models: &[UNTYPED_ORDERS], + expected_error: Some( + "NativeCompilerError: native model analysis of model 'orders_untyped' enrichment: \ + query analysis options: unknown variant `postgres`", + ), + }, + ]; + for test_case in test_cases { + let mut request = orders_request(model_requests(test_case.models)); + request.dialect = test_case.dialect.to_owned(); + let catalog = catalog(&request.dialect, &request.catalog_schemas); + let mut session = start_analysis_session(request, &catalog).expect("the session starts"); + + let error: Option = run_analysis_session(&mut session).err(); + + assert_eq!( + error + .as_deref() + .map(|error| error.split(',').next().unwrap_or(error)), + test_case.expected_error, "{}", test_case.description ); @@ -378,14 +431,20 @@ fn given_dynamic_pivots_when_proving_then_matches_python_or_defers() { dialect: "duckdb", sql: "PIVOT FROM WHERE", family: Some(("status", "amount", "MAX")), - expected_outcome: PivotOutcome::Deferred, + expected_outcome: failed( + "dynamic pivot SQL could not be parsed: Parse error at line 1, column 11: \ + Unexpected token: From", + ), }, PivotTestCase { - description: "non-ASCII names Python casefolds differently", + description: "non-ASCII names fold as Python casefolds them", dialect: "duckdb", sql: "SELECT * FROM __ref(\"stra\u{df}e\")", family: Some(("status", "amount", "MAX")), - expected_outcome: PivotOutcome::Deferred, + expected_outcome: failed( + "dynamic-family passthrough from 'stra\u{df}e' must redeclare the upstream \ + families exactly", + ), }, PivotTestCase { description: "no declared families", @@ -466,9 +525,9 @@ fn given_cte_reads_when_recovering_facts_then_matches_python_or_defers() { expected_facts: Some((&[], &[], &[], &["order_id"])), }, CteRecoveryTestCase { - description: "non-ASCII names Python casefolds differently", + description: "non-ASCII names fold as Python casefolds them", sql: "WITH b\u{e4}se AS (SELECT order_id FROM orders) SELECT order_id FROM b\u{e4}se", - expected_facts: None, + expected_facts: Some((&[("order_id", "INTEGER")], &[], &["order_id"], &[])), }, ]; for test_case in test_cases { @@ -559,9 +618,13 @@ fn given_handed_back_models_when_analysing_legacy_then_matches_python_or_defers( ]), }, LegacyAnalysisTestCase { - description: "non-ASCII names Python casefolds differently", + description: "non-ASCII names fold as Python casefolds them", sql: "SELECT \"gr\u{f6}\u{df}e\" FROM orders WHERE \"gr\u{f6}\u{df}e\" IS NOT NULL", - expected_lines: None, + expected_lines: Some(&[ + "succeeded=true star=false", + "gr\u{f6}\u{df}e - unknown", + "gr\u{f6}\u{df}e direct medium [model:orders:gr\u{f6}\u{df}e]", + ]), }, ]; for test_case in test_cases { @@ -577,3 +640,39 @@ fn given_handed_back_models_when_analysing_legacy_then_matches_python_or_defers( ); } } + +#[test] +fn given_a_finished_session_when_reading_model_analyses_then_keeps_typed_columns_and_proofs() { + let test_cases = [KeptAnalysisTestCase { + description: "a proven pivot publishes its fixed columns; a plain model its analysis", + dialect: "duckdb", + sql: "PIVOT __source(\"raw_orders\") ON status USING MAX(amount) GROUP BY customer_id", + family: Some(("status", "amount", "MAX")), + expected_outcome: proven( + &[("customer_id", "INTEGER", "non_null")], + Some("DOUBLE"), + "raw_orders", + true, + ), + expected_columns: [&["customer_id INTEGER non_null"], &["1 - non_null"]], + }]; + for test_case in test_cases { + let kept = kept_model_analyses(test_case.dialect, test_case.sql, test_case.family); + + assert_eq!( + kept, + vec![ + ( + test_case.expected_outcome, + Some(lines(test_case.expected_columns[0])) + ), + ( + PivotOutcome::Absent, + Some(lines(test_case.expected_columns[1])) + ), + ], + "{}", + test_case.description + ); + } +} diff --git a/crates/sqlbuild-analysis/src/assembly/analysis_session/tests/test_expression_shapes.rs b/crates/sqlbuild-analysis/src/assembly/analysis_session/tests/test_expression_shapes.rs index 6811ffd806..cf037ef39a 100644 --- a/crates/sqlbuild-analysis/src/assembly/analysis_session/tests/test_expression_shapes.rs +++ b/crates/sqlbuild-analysis/src/assembly/analysis_session/tests/test_expression_shapes.rs @@ -48,12 +48,21 @@ fn given_source_expressions_when_inferring_shapes_then_matches_python_shapes() { expression: "SELECT 1 AS \"Mixed_Case\", CAST(2 AS BIGINT) AS total", expected_shape: r#"Inferred([("\"Mixed_Case\"", "INT"), ("total", "BIGINT")])"#, }, + ExpressionShapeTestCase { + description: "untyped projections take Python's legacy analysis natively", + dialect: "duckdb", + case_sensitive_shapes: false, + expression: "SELECT mystery_fn(1) AS event_id, NULL AS note", + expected_shape: r#"Inferred([("event_id", "UNKNOWN"), ("note", "UNKNOWN")])"#, + }, ]; for test_case in test_cases { let request = ExpressionShapeRequest { dialect: test_case.dialect.to_owned(), case_sensitive_shapes: test_case.case_sensitive_shapes, function_return_types: Vec::new(), + nullability_rules: Some(Vec::new()), + nullability_callback: None, expressions: vec![test_case.expression.to_owned()], }; diff --git a/crates/sqlbuild-analysis/src/assembly/analysis_session/tests/test_model_columns.rs b/crates/sqlbuild-analysis/src/assembly/analysis_session/tests/test_model_columns.rs new file mode 100644 index 0000000000..1f8f081497 --- /dev/null +++ b/crates/sqlbuild-analysis/src/assembly/analysis_session/tests/test_model_columns.rs @@ -0,0 +1,162 @@ +use crate::assembly::analysis_session::models::{ + ColumnFact, ContractProof, ModelColumns, ModelColumnsInput, QueryColumns, SessionModelAnalysis, +}; +use crate::assembly::analysis_session::tests::helpers::{ + column_view, contract_proof, fact_columns, +}; +use crate::assembly::analysis_session::tests::test_types::ModelColumnsTestCase; + +const ORDERS: &[(&str, &str)] = &[("id", "INTEGER"), ("amount", "DECIMAL")]; +const PARSED: &[(&str, &str)] = &[("id", "BIGINT")]; +const PIVOT: &[(&str, &str)] = &[("region", "VARCHAR"), ("north", "DECIMAL")]; + +#[test] +fn given_model_results_when_finalizing_columns_then_applies_python_order() { + let test_cases = [ + ModelColumnsTestCase { + description: "analysis disabled keeps no columns but still reports poisoned names", + analysis_enabled: false, + succeeded: false, + session_columns: None, + session_proof: None, + fallback: None, + standalone_proof: None, + poisoned: &["id"], + expected_columns: Ok((None, false)), + }, + ModelColumnsTestCase { + description: "a successful session keeps its columns and type recovery unsets poisoned types", + analysis_enabled: true, + succeeded: true, + session_columns: Some(ORDERS), + session_proof: None, + fallback: None, + standalone_proof: None, + poisoned: &["amount"], + expected_columns: Ok((Some(vec![("id", Some("INTEGER")), ("amount", None)]), false)), + }, + ModelColumnsTestCase { + description: "a failed session takes the parse fallback's columns", + analysis_enabled: true, + succeeded: false, + session_columns: None, + session_proof: None, + fallback: Some(Some(PARSED)), + standalone_proof: None, + poisoned: &[], + expected_columns: Ok((Some(vec![("id", Some("BIGINT"))]), false)), + }, + ModelColumnsTestCase { + description: "a failed session whose parse fallback infers nothing has no columns", + analysis_enabled: true, + succeeded: false, + session_columns: None, + session_proof: None, + fallback: Some(None), + standalone_proof: None, + poisoned: &[], + expected_columns: Ok((None, false)), + }, + ModelColumnsTestCase { + description: "a failed session without its parse fallback is an internal failure", + analysis_enabled: true, + succeeded: false, + session_columns: None, + session_proof: None, + fallback: None, + standalone_proof: None, + poisoned: &[], + expected_columns: Err("a failed session analysis without its parse fallback"), + }, + ModelColumnsTestCase { + description: "a proven session pivot replaces the parse fallback and forces a star", + analysis_enabled: true, + succeeded: false, + session_columns: None, + session_proof: Some((true, PIVOT)), + fallback: Some(Some(PARSED)), + standalone_proof: None, + poisoned: &[], + expected_columns: Ok(( + Some(vec![ + ("region", Some("VARCHAR")), + ("north", Some("DECIMAL")), + ]), + true, + )), + }, + ModelColumnsTestCase { + description: "an unproven session pivot keeps the analysed columns", + analysis_enabled: true, + succeeded: true, + session_columns: Some(ORDERS), + session_proof: Some((false, PIVOT)), + fallback: None, + standalone_proof: Some((true, PIVOT)), + poisoned: &[], + expected_columns: Ok(( + Some(vec![("id", Some("INTEGER")), ("amount", Some("DECIMAL"))]), + false, + )), + }, + ModelColumnsTestCase { + description: "a proven standalone pivot of an unanalysed model sets columns, then poisoning", + analysis_enabled: false, + succeeded: false, + session_columns: None, + session_proof: None, + fallback: None, + standalone_proof: Some((true, PIVOT)), + poisoned: &["north"], + expected_columns: Ok(( + Some(vec![("region", Some("VARCHAR")), ("north", None)]), + true, + )), + }, + ]; + for test_case in test_cases { + let session_columns: Option> = test_case.session_columns.map(fact_columns); + let session_proof: Option = test_case.session_proof.map(contract_proof); + let fallback: Option = test_case.fallback.map(|parsed| QueryColumns { + succeeded: parsed.is_some(), + columns: parsed.map(fact_columns), + has_star: false, + }); + let standalone_proof: Option = + test_case.standalone_proof.map(contract_proof); + let poisoned: Vec = test_case + .poisoned + .iter() + .map(|name| (*name).to_owned()) + .collect(); + let input = ModelColumnsInput { + analysis_enabled: test_case.analysis_enabled, + session: SessionModelAnalysis { + succeeded: test_case.succeeded, + columns: session_proof + .as_ref() + .filter(|proof| proof.output_proven) + .map(|proof| proof.fixed_columns.as_slice()) + .or(session_columns.as_deref()), + dynamic_proof: session_proof.as_ref(), + }, + fallback: fallback.as_ref(), + standalone_proof: standalone_proof.as_ref(), + poisoned: &poisoned, + }; + + let finished: Result = input.model_columns(); + + assert_eq!( + finished.as_ref().map(column_view).map_err(String::as_str), + test_case.expected_columns, + "{}", + test_case.description + ); + assert!( + finished.map_or(true, |finished| finished.unchecked == poisoned), + "{}", + test_case.description + ); + } +} diff --git a/crates/sqlbuild-analysis/src/assembly/analysis_session/tests/test_types.rs b/crates/sqlbuild-analysis/src/assembly/analysis_session/tests/test_types.rs index e55e9e91fc..cf81b59c4f 100644 --- a/crates/sqlbuild-analysis/src/assembly/analysis_session/tests/test_types.rs +++ b/crates/sqlbuild-analysis/src/assembly/analysis_session/tests/test_types.rs @@ -27,7 +27,14 @@ pub(crate) struct SessionFactsTestCase { pub(crate) struct UnscheduledTestCase { pub(crate) description: &'static str, pub(crate) models: &'static [ModelSpec], - pub(crate) expected_started: bool, + pub(crate) expected_error: Option<&'static str>, +} + +pub(crate) struct SessionFailureTestCase { + pub(crate) description: &'static str, + pub(crate) dialect: &'static str, + pub(crate) models: &'static [ModelSpec], + pub(crate) expected_error: Option<&'static str>, } pub(crate) struct ExpressionShapeTestCase { @@ -135,3 +142,31 @@ pub(crate) struct CachedRun { Vec, ), } + +pub(crate) struct KeptAnalysisTestCase { + pub(crate) description: &'static str, + pub(crate) dialect: &'static str, + pub(crate) sql: &'static str, + pub(crate) family: Option<(&'static str, &'static str, &'static str)>, + pub(crate) expected_outcome: PivotOutcome, + /// `name type nullability` of each model's published columns: the pivot, then a plain one. + pub(crate) expected_columns: [&'static [&'static str]; 2], +} + +/// Final `(name, type)` columns and the forced star. +pub(crate) type ColumnView<'a> = (Option)>>, bool); + +/// The expected column view, or the internal failure. +pub(crate) type ExpectedModelColumns = Result, &'static str>; + +pub(crate) struct ModelColumnsTestCase { + pub(crate) description: &'static str, + pub(crate) analysis_enabled: bool, + pub(crate) succeeded: bool, + pub(crate) session_columns: Option<&'static [(&'static str, &'static str)]>, + pub(crate) session_proof: Option<(bool, &'static [(&'static str, &'static str)])>, + pub(crate) fallback: Option>, + pub(crate) standalone_proof: Option<(bool, &'static [(&'static str, &'static str)])>, + pub(crate) poisoned: &'static [&'static str], + pub(crate) expected_columns: ExpectedModelColumns, +} diff --git a/crates/sqlbuild-analysis/src/assembly/analysis_session/types.rs b/crates/sqlbuild-analysis/src/assembly/analysis_session/types.rs index 0dbac8f6a5..913e016439 100644 --- a/crates/sqlbuild-analysis/src/assembly/analysis_session/types.rs +++ b/crates/sqlbuild-analysis/src/assembly/analysis_session/types.rs @@ -1,5 +1,9 @@ //! Ordered mappings shared with Python's dicts. +/// An adapter's Python nullability rule: `(function name, argument nullabilities)` to a result. +pub type NullabilityRuleFn = + dyn Fn(&str, &[&'static str]) -> Result<&'static str, String> + Send + Sync; + /// An ordered `name -> value` mapping in Python dict order. pub type Pairs = Vec<(String, String)>; /// Ordered relation shapes in Python dict order. diff --git a/crates/sqlbuild-analysis/src/assembly/project/_helpers/deps.rs b/crates/sqlbuild-analysis/src/assembly/project/_helpers/deps.rs index da8005a6de..de5150607b 100644 --- a/crates/sqlbuild-analysis/src/assembly/project/_helpers/deps.rs +++ b/crates/sqlbuild-analysis/src/assembly/project/_helpers/deps.rs @@ -2,9 +2,12 @@ use std::collections::HashSet; +use sqlbuild_core::text::main::python_str_repr::python_str_repr; + use crate::assembly::project::constants::{ - ATTACHED_AUDIT_KINDS, AUDIT_TARGET_DEFERRAL, DBT_REF_KIND, KIND_RESOURCES, MODEL_RESOURCE, + ATTACHED_AUDIT_KINDS, AUDIT_TARGET_KIND_ENUM, DBT_REF_KIND, KIND_RESOURCES, MODEL_RESOURCE, }; +use crate::assembly::project::errors::AssemblyError; use crate::assembly::project::models::{AuditFacts, Reference}; use crate::assembly::project::types::Fact; use crate::assembly::project::types::ObjectKey; @@ -19,7 +22,14 @@ pub(crate) fn audit_deps(audit: &AuditFacts) -> Fact> { let mut keys: Vec = reference_deps(&audit.references); if let Some((kind, name)) = &audit.attached { if !ATTACHED_AUDIT_KINDS.contains(&kind.as_str()) { - return Err(AUDIT_TARGET_DEFERRAL.to_owned()); + return Err(match python_str_repr(kind) { + Some(repr) => { + AssemblyError::Value(format!("{repr} is not a valid {AUDIT_TARGET_KIND_ENUM}")) + } + None => AssemblyError::Internal(format!( + "a non-ASCII attached audit target kind is not a valid {AUDIT_TARGET_KIND_ENUM}" + )), + }); } keys.push((kind.clone(), name.clone())); } diff --git a/crates/sqlbuild-analysis/src/assembly/project/_helpers/mod.rs b/crates/sqlbuild-analysis/src/assembly/project/_helpers/mod.rs index 000b88358d..b16c7ba17f 100644 --- a/crates/sqlbuild-analysis/src/assembly/project/_helpers/mod.rs +++ b/crates/sqlbuild-analysis/src/assembly/project/_helpers/mod.rs @@ -1,4 +1,5 @@ pub(crate) mod deps; +pub(crate) mod resources; pub(crate) mod syntax; pub(crate) mod targets; pub(crate) mod templates; diff --git a/crates/sqlbuild-analysis/src/assembly/project/_helpers/resources.rs b/crates/sqlbuild-analysis/src/assembly/project/_helpers/resources.rs new file mode 100644 index 0000000000..2cf2a12302 --- /dev/null +++ b/crates/sqlbuild-analysis/src/assembly/project/_helpers/resources.rs @@ -0,0 +1,99 @@ +//! Python's resource assembly loop over one project's sources, seeds and audits. + +use std::cell::RefCell; + +use crate::assembly::project::_helpers::deps::{audit_deps, reference_deps}; +use crate::assembly::project::_helpers::syntax::syntax_valid; +use crate::assembly::project::_helpers::targets::{managed_source, seed_target}; +use crate::assembly::project::_helpers::templates::TemplateInputs; +use crate::assembly::project::models::{ + ModelFacts, ProjectRequest, ProjectResources, ResourceFailure, ResourceSlot, +}; + +/// Each resource's facts in Python's assembly order (sources, seeds, audits) up to its failure. +pub(crate) fn project_resources(request: &ProjectRequest) -> ProjectResources { + let target = request.target.as_ref(); + let inputs = TemplateInputs { + variables: &request.variables, + environment: &request.environment, + reads: RefCell::new(Vec::new()), + }; + let mut resources = ProjectResources { + model_syntax_valid: request + .models + .iter() + .map(|model| valid_syntax(model, &request.dialect)) + .collect(), + model_deps: request + .models + .iter() + .map(|model| reference_deps(&model.references)) + .collect(), + function_deps: request + .functions + .iter() + .map(|function| reference_deps(&function.references)) + .collect(), + ..ProjectResources::default() + }; + for (index, source) in request.sources.iter().enumerate() { + match managed_source(source, target, &inputs) { + Ok(namespace) => resources.sources.push(namespace), + Err(error) => { + let failure = ResourceFailure { + slot: ResourceSlot::Source, + index, + error, + }; + return failed(resources, &inputs, failure); + } + } + } + for (index, seed) in request.seeds.iter().enumerate() { + match seed_target(seed, &request.defaults, target, &inputs) { + Ok(namespace) => resources.seeds.push(namespace), + Err(error) => { + let failure = ResourceFailure { + slot: ResourceSlot::Seed, + index, + error, + }; + return failed(resources, &inputs, failure); + } + } + } + for (index, audit) in request.audits.iter().enumerate() { + match audit_deps(audit) { + Ok(keys) => resources.audit_deps.push(keys), + Err(error) => { + let failure = ResourceFailure { + slot: ResourceSlot::Audit, + index, + error, + }; + return failed(resources, &inputs, failure); + } + } + } + resources.reads = inputs.reads.into_inner(); + resources +} + +/// The resources assembled so far, the reads made and the resource Python raises at. +fn failed( + mut resources: ProjectResources, + inputs: &TemplateInputs<'_>, + failure: ResourceFailure, +) -> ProjectResources { + resources.reads = inputs.reads.borrow().clone(); + resources.failure = Some(failure); + resources +} + +/// Whether Python's model and hook syntax validation passes; Python reports every failure. +fn valid_syntax(model: &ModelFacts, dialect: &str) -> bool { + model + .syntax_checks + .iter() + .all(|check| syntax_valid(check, dialect) == Ok(true)) +} diff --git a/crates/sqlbuild-analysis/src/assembly/project/_helpers/syntax.rs b/crates/sqlbuild-analysis/src/assembly/project/_helpers/syntax.rs index 59d20a7422..b9706b03d1 100644 --- a/crates/sqlbuild-analysis/src/assembly/project/_helpers/syntax.rs +++ b/crates/sqlbuild-analysis/src/assembly/project/_helpers/syntax.rs @@ -1,89 +1,74 @@ -//! Python's `validate_sql_syntax` and `validate_hook_sql_syntax` outcome, without the message. +//! Python's syntax validation: Polyglot's `validate` or `parse_one` of the cleaned SQL. use std::collections::HashMap; use polyglot_sql::{ - ComplexityGuardOptions, Dialect, DialectType, ValidationOptions, validate_with_dialect, + ComplexityGuardOptions, Dialect, DialectType, ParseOptions, ValidationOptions, + validate_with_dialect, }; -use serde_json::json; -use crate::assembly::project::constants::{ - DIALECT_DEFERRAL, MAX_FUNCTION_CALL_DEPTH, NORMALIZATION_DEFERRAL, PLACEHOLDER_DEFERRAL, - PLACEHOLDER_PREFIX, UNSUPPORTED_DIALECT_DEFERRAL, -}; -use crate::assembly::project::models::SyntaxCheck; -use crate::assembly::project::types::Fact; +use crate::assembly::project::constants::{INVALID_SQL, MAX_FUNCTION_CALL_DEPTH}; +use sqlbuild_sqltext::compiler::main::placeholder_defaults::placeholder_defaults; + +use crate::assembly::project::models::{SyntaxCheck, SyntaxFailure, SyntaxMode}; use crate::lineage::main::parser_dialect::parser_dialect; use crate::semantic_validation::main::normalize::normalize_analysis_sql; use crate::semantic_validation::models::NormalizationInput; -/// Whether Polyglot's `validate` accepts the cleaned SQL; Python raises where it does not. -pub(crate) fn syntax_valid(check: &SyntaxCheck, dialect: &str) -> Fact { +/// Whether Polyglot's `validate` accepts the cleaned SQL; Err is the `ValueError` Python raises. +pub(crate) fn syntax_valid(check: &SyntaxCheck, dialect: &str) -> Result { + syntax_error(check, dialect, SyntaxMode::Validate).map(|error| error.is_none()) +} + +/// Python's syntax error message for one SQL string, None where Polyglot accepts it. +pub(crate) fn syntax_error( + check: &SyntaxCheck, + dialect: &str, + mode: SyntaxMode, +) -> Result, SyntaxFailure> { let cleaned: String = normalize_analysis_sql(NormalizationInput { sql: check.sql.clone(), dialect: dialect.to_owned(), stubs: HashMap::new(), placeholders: HashMap::new(), }) - .map_err(|_| NORMALIZATION_DEFERRAL.to_owned())?; + .map_err(SyntaxFailure::Normalization)?; let cleaned: String = if check.placeholders.is_empty() { cleaned } else { - placeholder_defaults(&cleaned, &check.placeholders)? + placeholder_defaults(&cleaned, &check.placeholders) }; - let dialect: DialectType = - parser_dialect(Some(dialect)).ok_or_else(|| UNSUPPORTED_DIALECT_DEFERRAL.to_owned())?; - let complexity_guard: ComplexityGuardOptions = - serde_json::from_value(json!({"maxFunctionCallDepth": MAX_FUNCTION_CALL_DEPTH})) - .map_err(|_| DIALECT_DEFERRAL.to_owned())?; - let options = ValidationOptions { - complexity_guard: Some(complexity_guard), - strict_syntax: false, - semantic: false, + let dialect_type: DialectType = parser_dialect(Some(dialect)) + .map_err(|unknown| SyntaxFailure::UnknownDialect(unknown.to_owned()))?; + let complexity_guard = ComplexityGuardOptions { + max_function_call_depth: Some(MAX_FUNCTION_CALL_DEPTH), + ..Default::default() }; - Ok(validate_with_dialect(&cleaned, &Dialect::get(dialect), &options).valid) -} - -/// `substitute_placeholder_defaults`: `@@@name` becomes its default; unknown names stay. -fn placeholder_defaults(sql: &str, placeholders: &[(String, String)]) -> Fact { - let mut result: String = String::with_capacity(sql.len()); - let mut rest: &str = sql; - while let Some(start) = rest.find(PLACEHOLDER_PREFIX) { - result.push_str(&rest[..start]); - let after: &str = &rest[start + PLACEHOLDER_PREFIX.len()..]; - let length: usize = after - .find(|character: char| !is_word(character)) - .unwrap_or(after.len()); - if after[length..] - .chars() - .next() - .is_some_and(|next| !next.is_ascii()) - { - return Err(PLACEHOLDER_DEFERRAL.to_owned()); - } - if length == 0 { - result.push_str(&rest[start..=start]); - rest = &rest[start + 1..]; - continue; + let polyglot: Dialect = Dialect::get(dialect_type); + Ok(match mode { + SyntaxMode::Validate => { + let options = ValidationOptions { + complexity_guard: Some(complexity_guard), + strict_syntax: false, + semantic: false, + }; + let result = validate_with_dialect(&cleaned, &polyglot, &options); + (!result.valid).then(|| { + result + .errors + .first() + .map_or_else(|| INVALID_SQL.to_owned(), |error| error.message.clone()) + }) } - let name: &str = &after[..length]; - match placeholders - .iter() - .find(|(placeholder, _)| placeholder == name) - { - Some((_, default)) => result.push_str(default), - None => { - result.push_str(PLACEHOLDER_PREFIX); - result.push_str(name); + SyntaxMode::Parse => { + let options = ParseOptions { + complexity_guard: Some(complexity_guard), + }; + match polyglot.parse_with_options(&cleaned, &options) { + Ok(statements) if statements.len() == 1 => None, + Ok(statements) => Some(format!("Expected 1 statement, found {}", statements.len())), + Err(error) => Some(error.to_string()), } } - rest = &after[length..]; - } - result.push_str(rest); - Ok(result) -} - -/// An ASCII character Python's `\w` matches. -fn is_word(character: char) -> bool { - character.is_ascii_alphanumeric() || character == '_' + }) } diff --git a/crates/sqlbuild-analysis/src/assembly/project/_helpers/targets.rs b/crates/sqlbuild-analysis/src/assembly/project/_helpers/targets.rs index 5a8cdeeaca..ff59b71794 100644 --- a/crates/sqlbuild-analysis/src/assembly/project/_helpers/targets.rs +++ b/crates/sqlbuild-analysis/src/assembly/project/_helpers/targets.rs @@ -1,11 +1,16 @@ //! Python's managed source and seed targets (`assembly/project.py`, `assembly/targets.py`). use crate::assembly::project::_helpers::templates::{Context, TemplateInputs, expanded_text}; +use crate::assembly::project::constants::{ + DATABASE_DIMENSION, DEFAULT_SEED_DATABASE_LABEL, DEFAULT_SEED_SCHEMA_LABEL, + MANAGED_SOURCE_TARGET_LABEL, SCHEMA_DIMENSION, TARGET_DATABASE_LABEL, TARGET_SCHEMA_LABEL, +}; use crate::assembly::project::constants::{ DESTINATION_DATABASE_CONTEXT, DESTINATION_QUALIFIED_CONTEXT, DESTINATION_SCHEMA_CONTEXT, DESTINATION_TABLE_CONTEXT, MODEL_ALIAS_CONTEXT, MODEL_DATABASE_CONTEXT, MODEL_NAME_CONTEXT, - MODEL_SCHEMA_CONTEXT, PRESERVE_TARGET_VALUE, PRESERVED_NAMESPACE_DEFERRAL, + MODEL_SCHEMA_CONTEXT, PRESERVE_TARGET_VALUE, }; +use crate::assembly::project::errors::AssemblyError; use crate::assembly::project::models::{ Namespace, SeedDefaults, SeedFacts, SourceFacts, TargetNamespace, }; @@ -31,6 +36,7 @@ pub(crate) fn managed_source( loader_schema: target.loader_schema.clone(), }; preserved_namespace( + &format!("Managed source '{}'", source.name), Some(&loader_target), source.database.as_ref(), source.schema.as_ref(), @@ -59,25 +65,44 @@ pub(crate) fn seed_target( .as_ref() .or(defaults.database.as_ref()), inputs, + DEFAULT_SEED_DATABASE_LABEL, )?; let mut logical_schema: Option = environment_text( defaults.seed_schema.as_ref().or(defaults.schema.as_ref()), inputs, + DEFAULT_SEED_SCHEMA_LABEL, )?; if let Some(raw) = &seed.database { let context = seed_context(&seed.name, logical_database.clone(), logical_schema.clone()); - logical_database = seed_text(raw, inputs, &context)?; + let label: String = format!("seed '{}' database", seed.name); + logical_database = seed_text(raw, inputs, &context, &label)?; } if let Some(raw) = &seed.schema { let context = seed_context(&seed.name, logical_database.clone(), logical_schema.clone()); - logical_schema = seed_text(raw, inputs, &context)?; + let label: String = format!("seed '{}' schema", seed.name); + logical_schema = seed_text(raw, inputs, &context, &label)?; } - preserved_namespace(target, logical_database.as_ref(), logical_schema.as_ref())?; + preserved_namespace( + &format!("Seed '{}'", seed.name), + target, + logical_database.as_ref(), + logical_schema.as_ref(), + )?; let (database, schema) = match target { None => (logical_database.clone(), logical_schema.clone()), Some(target) => ( - target_override(target.database.as_ref(), logical_database.clone(), inputs)?, - target_override(target.schema.as_ref(), logical_schema.clone(), inputs)?, + target_override( + target.database.as_ref(), + logical_database.clone(), + inputs, + TARGET_DATABASE_LABEL, + )?, + target_override( + target.schema.as_ref(), + logical_schema.clone(), + inputs, + TARGET_SCHEMA_LABEL, + )?, ), }; Ok(Namespace { @@ -88,8 +113,9 @@ pub(crate) fn seed_target( }) } -/// `validate_preserved_logical_namespace`; Python raises where Err. +/// `validate_preserved_logical_namespace` for the resource Python names `resource_label`. fn preserved_namespace( + resource_label: &str, target: Option<&TargetNamespace>, logical_database: Option<&String>, logical_schema: Option<&String>, @@ -99,27 +125,46 @@ fn preserved_namespace( }; let preserved = |value: Option<&String>| value.is_some_and(|value| value == PRESERVE_TARGET_VALUE); - if (preserved(target.database.as_ref()) && logical_database.is_none()) - || (preserved(target.schema.as_ref()) && logical_schema.is_none()) - { - return Err(PRESERVED_NAMESPACE_DEFERRAL.to_owned()); + let mut missing: Vec<&str> = Vec::new(); + if preserved(target.database.as_ref()) && logical_database.is_none() { + missing.push(DATABASE_DIMENSION); + } + if preserved(target.schema.as_ref()) && logical_schema.is_none() { + missing.push(SCHEMA_DIMENSION); + } + if missing.is_empty() { + return Ok(()); } - Ok(()) + let dimensions: String = missing.join(" and "); + Err(AssemblyError::CompileInput { + message: format!( + "{resource_label} has no logical {dimensions}, but the selected target sets \ + {dimensions} to '{PRESERVE_TARGET_VALUE}'" + ), + help: Some(format!( + "Set {dimensions} on the resource or its defaults, or configure a literal target \ + {dimensions}." + )), + }) } /// `_expand_target_value`. fn optional_text(value: Option<&str>, inputs: &TemplateInputs<'_>) -> Fact> { value - .map(|value| expanded_text(value, inputs, None)) + .map(|value| expanded_text(value, inputs, None, MANAGED_SOURCE_TARGET_LABEL)) .transpose() } /// `_expand_seed_default_value` and `_expand_seed_environment_value`. -fn environment_text(raw: Option<&String>, inputs: &TemplateInputs<'_>) -> Fact> { +fn environment_text( + raw: Option<&String>, + inputs: &TemplateInputs<'_>, + label: &str, +) -> Fact> { match raw { None => Ok(None), Some(raw) if raw == PRESERVE_TARGET_VALUE => Ok(None), - Some(raw) => expanded_text(raw, inputs, None).map(Some), + Some(raw) => expanded_text(raw, inputs, None, label).map(Some), } } @@ -128,11 +173,12 @@ fn seed_text( raw: &str, inputs: &TemplateInputs<'_>, context: &Context<'_>, + label: &str, ) -> Fact> { if raw == PRESERVE_TARGET_VALUE { return Ok(None); } - expanded_text(raw, inputs, Some(context)).map(Some) + expanded_text(raw, inputs, Some(context), label).map(Some) } /// `_apply_seed_target_overrides` for one dimension. @@ -140,9 +186,10 @@ fn target_override( raw: Option<&String>, logical: Option, inputs: &TemplateInputs<'_>, + label: &str, ) -> Fact> { match raw { - Some(raw) if raw != PRESERVE_TARGET_VALUE => environment_text(Some(raw), inputs), + Some(raw) if raw != PRESERVE_TARGET_VALUE => environment_text(Some(raw), inputs, label), _ => Ok(logical), } } diff --git a/crates/sqlbuild-analysis/src/assembly/project/_helpers/templates.rs b/crates/sqlbuild-analysis/src/assembly/project/_helpers/templates.rs index f97b281c3a..2356aea56e 100644 --- a/crates/sqlbuild-analysis/src/assembly/project/_helpers/templates.rs +++ b/crates/sqlbuild-analysis/src/assembly/project/_helpers/templates.rs @@ -1,18 +1,21 @@ -//! Python's `str(expand_template_data(...))` over scalar variables, the environment and context. +//! Python's `str(expand_template_data(...))` over project variables, the environment and context. -use std::cell::RefCell; +use std::cell::{Cell, RefCell}; +use sqlbuild_model_config::templates::errors::TemplateError; use sqlbuild_model_config::templates::main::expand_template_string::expand_template_string; +use sqlbuild_model_config::templates::main::template_error_message::template_error_message; use sqlbuild_model_config::templates::models::{ ContextValue, Scalar, StringExpansion, TemplateFailure, TemplateOptions, }; use sqlbuild_model_config::templates::types::TemplateHost; use crate::assembly::project::constants::{ - PROJECT_VAR_FALSE, PROJECT_VAR_TRUE, PYTHON_FALSE, PYTHON_NONE, PYTHON_TRUE, TEMPLATE_DEFERRAL, - TEMPLATE_LABEL, TEMPLATE_OPEN_TOKEN, + PROJECT_VAR_FALSE, PROJECT_VAR_TRUE, PYTHON_FALSE, PYTHON_NONE, PYTHON_TRUE, + TEMPLATE_OPEN_TOKEN, UNLISTED_ENVIRONMENT, }; -use crate::assembly::project::models::{InputRead, Variable}; +use crate::assembly::project::errors::AssemblyError; +use crate::assembly::project::models::{InputRead, OpaqueRender, OpaqueVariable, Variable}; use crate::assembly::project::types::Fact; /// Context values by name; None is a known key whose value Python holds as None. @@ -26,26 +29,42 @@ pub(crate) struct TemplateInputs<'a> { pub(crate) reads: RefCell>, } -/// One expansion's inputs and context values. -struct ScalarHost<'a> { +/// One evaluated value: a scalar, or a variable value only Python renders. +#[derive(Clone)] +enum TargetValue { + Scalar(Scalar), + Opaque(OpaqueVariable), +} + +/// One expansion's inputs, context values and the label its errors name. +struct TargetHost<'a> { inputs: &'a TemplateInputs<'a>, context: &'a Context<'a>, + label: &'a str, + /// Why the host stopped evaluation: the exception Python raises, or an internal failure. + stopped: Cell>, } -impl TemplateHost for ScalarHost<'_> { - type Value = Scalar; +impl TargetHost<'_> { + fn stop(&self, error: AssemblyError) -> TemplateFailure { + self.stopped.set(Some(error)); + TemplateFailure::Host + } +} + +impl TemplateHost for TargetHost<'_> { + type Value = TargetValue; fn variable(&self, name: &str) -> Result, TemplateFailure> { - match self + Ok(self .inputs .variables .iter() .find(|(variable, _)| variable == name) - { - None => Ok(None), - Some((_, Variable::Scalar(value))) => Ok(Some(value.clone())), - Some((_, Variable::Unsupported)) => Err(TemplateFailure::Host), - } + .map(|(_, value)| match value { + Variable::Scalar(value) => TargetValue::Scalar(value.clone()), + Variable::Opaque(value) => TargetValue::Opaque(value.clone()), + })) } fn environment(&self, name: &str) -> Result, TemplateFailure> { @@ -59,8 +78,12 @@ impl TemplateHost for ScalarHost<'_> { .iter() .find(|(variable, _)| variable == name) { - None => Err(TemplateFailure::Host), - Some((_, value)) => Ok(value.clone().map(Scalar::Text)), + None => Err(self.stop(AssemblyError::Internal(format!( + "{UNLISTED_ENVIRONMENT} '{name}'" + )))), + Some((_, value)) => Ok(value + .clone() + .map(|text| TargetValue::Scalar(Scalar::Text(text)))), } } @@ -72,45 +95,58 @@ impl TemplateHost for ScalarHost<'_> { Ok(match self.context.iter().find(|(key, _)| *key == name) { None => ContextValue::Unknown, Some((_, None)) => ContextValue::Unavailable, - Some((_, Some(value))) => ContextValue::Value(Scalar::Text(value.clone())), + Some((_, Some(value))) => { + ContextValue::Value(TargetValue::Scalar(Scalar::Text(value.clone()))) + } }) } fn text(&self, text: &str) -> Result { - Ok(Scalar::Text(text.to_owned())) + Ok(TargetValue::Scalar(Scalar::Text(text.to_owned()))) } fn boolean(&self, flag: bool) -> Result { - Ok(Scalar::Bool(flag)) + Ok(TargetValue::Scalar(Scalar::Bool(flag))) } fn null(&self) -> Self::Value { - Scalar::Null + TargetValue::Scalar(Scalar::Null) } fn scalar(&self, value: &Self::Value) -> Result { - Ok(value.clone()) - } - - fn render(&self, value: &Self::Value, _label: &str) -> Result { Ok(match value { - Scalar::Null => String::new(), - Scalar::Bool(true) => PROJECT_VAR_TRUE.to_owned(), - Scalar::Bool(false) => PROJECT_VAR_FALSE.to_owned(), - Scalar::Text(text) => text.clone(), + TargetValue::Scalar(value) => value.clone(), + TargetValue::Opaque(value) => Scalar::Text(value.text.clone()), }) } + fn render(&self, value: &Self::Value, label: &str) -> Result { + match value { + TargetValue::Scalar(Scalar::Null) => Ok(String::new()), + TargetValue::Scalar(Scalar::Bool(true)) => Ok(PROJECT_VAR_TRUE.to_owned()), + TargetValue::Scalar(Scalar::Bool(false)) => Ok(PROJECT_VAR_FALSE.to_owned()), + TargetValue::Scalar(Scalar::Text(text)) => Ok(text.clone()), + TargetValue::Opaque(value) => match &value.render { + OpaqueRender::Text(text) => Ok(text.clone()), + OpaqueRender::Rejected(rest) => Err(TemplateFailure::Invalid( + TemplateError::Message(format!("{label}{rest}")), + )), + OpaqueRender::Raises(index) => Err(self.stop(AssemblyError::Raise(*index))), + }, + } + } + fn label(&self) -> &str { - TEMPLATE_LABEL + self.label } } -/// `str(expand_template_data(value=text, ...))`; context is allowed only where Some. +/// `str(expand_template_data(value=text, context_label=label, ...))`; context only where Some. pub(crate) fn expanded_text( text: &str, inputs: &TemplateInputs<'_>, context: Option<&Context<'_>>, + label: &str, ) -> Fact { if !text.contains(TEMPLATE_OPEN_TOKEN) { return Ok(text.to_owned()); @@ -120,24 +156,35 @@ pub(crate) fn expanded_text( preserve_context_tokens: false, preserve_unknown_context: false, }; - let host = ScalarHost { + let host = TargetHost { inputs, context: context.unwrap_or_default(), + label, + stopped: Cell::new(None), }; match expand_template_string(&host, text, options) { Ok(StringExpansion::Unchanged) => Ok(text.to_owned()), Ok(StringExpansion::Value(value)) => Ok(python_str(value)), Ok(StringExpansion::Text(expanded)) => Ok(expanded), - Err(_) => Err(TEMPLATE_DEFERRAL.to_owned()), + Err(TemplateFailure::Missing(error) | TemplateFailure::Invalid(error)) => { + Err(AssemblyError::CompileInput { + message: template_error_message(&error, label), + help: None, + }) + } + Err(TemplateFailure::Host) => Err(host.stopped.take().unwrap_or_else(|| { + AssemblyError::Internal("template expansion stopped without an error".to_owned()) + })), } } -/// Python's `str()` of a scalar. -fn python_str(value: Scalar) -> String { +/// Python's `str()` of a value. +fn python_str(value: TargetValue) -> String { match value { - Scalar::Null => PYTHON_NONE.to_owned(), - Scalar::Bool(true) => PYTHON_TRUE.to_owned(), - Scalar::Bool(false) => PYTHON_FALSE.to_owned(), - Scalar::Text(text) => text, + TargetValue::Scalar(Scalar::Null) => PYTHON_NONE.to_owned(), + TargetValue::Scalar(Scalar::Bool(true)) => PYTHON_TRUE.to_owned(), + TargetValue::Scalar(Scalar::Bool(false)) => PYTHON_FALSE.to_owned(), + TargetValue::Scalar(Scalar::Text(text)) => text, + TargetValue::Opaque(value) => value.text, } } diff --git a/crates/sqlbuild-analysis/src/assembly/project/constants.rs b/crates/sqlbuild-analysis/src/assembly/project/constants.rs index dc6f8f874f..0eedde351b 100644 --- a/crates/sqlbuild-analysis/src/assembly/project/constants.rs +++ b/crates/sqlbuild-analysis/src/assembly/project/constants.rs @@ -16,7 +16,6 @@ pub(crate) const TEMPLATE_OPEN_TOKEN: &str = "${"; pub(crate) const PYTHON_NONE: &str = "None"; pub(crate) const PYTHON_TRUE: &str = "True"; pub(crate) const PYTHON_FALSE: &str = "False"; -pub(crate) const PLACEHOLDER_PREFIX: &str = "@@@"; pub(crate) const MAX_FUNCTION_CALL_DEPTH: usize = 512; pub(crate) const MODEL_NAME_CONTEXT: &str = "model.name"; pub(crate) const MODEL_DATABASE_CONTEXT: &str = "model.database"; @@ -26,17 +25,21 @@ pub(crate) const DESTINATION_DATABASE_CONTEXT: &str = "destination.database"; pub(crate) const DESTINATION_SCHEMA_CONTEXT: &str = "destination.schema"; pub(crate) const DESTINATION_TABLE_CONTEXT: &str = "destination.table"; pub(crate) const DESTINATION_QUALIFIED_CONTEXT: &str = "destination.qualified"; -pub(crate) const AUDIT_TARGET_DEFERRAL: &str = "audit_target_kind"; -pub(crate) const TEMPLATE_DEFERRAL: &str = "target_template"; /// `render_project_var_text` of booleans inside a larger template string. pub(crate) const PROJECT_VAR_TRUE: &str = "true"; pub(crate) const PROJECT_VAR_FALSE: &str = "false"; -/// The label template errors would name; assembly defers every template error. -pub(crate) const TEMPLATE_LABEL: &str = "project assembly template"; -pub(crate) const PRESERVED_NAMESPACE_DEFERRAL: &str = "preserved_namespace"; -pub(crate) const SYNTAX_DEFERRAL: &str = "syntax_error"; -pub(crate) const PLACEHOLDER_DEFERRAL: &str = "placeholder_word"; -pub(crate) const NORMALIZATION_DEFERRAL: &str = "normalization"; -pub(crate) const DIALECT_DEFERRAL: &str = "dialect"; -pub(crate) const UNSUPPORTED_DIALECT_DEFERRAL: &str = "unsupported_dialect"; -pub(crate) const PANIC_DEFERRAL: &str = "panic"; +/// Python's message when `validate` rejects SQL without naming an error. +pub(crate) const INVALID_SQL: &str = "invalid SQL"; +/// The `context_label`s Python's target expansions name in their errors. +pub(crate) const MANAGED_SOURCE_TARGET_LABEL: &str = "managed source target"; +pub(crate) const DEFAULT_SEED_DATABASE_LABEL: &str = "default seed database"; +pub(crate) const DEFAULT_SEED_SCHEMA_LABEL: &str = "default seed schema"; +pub(crate) const TARGET_DATABASE_LABEL: &str = "target database"; +pub(crate) const TARGET_SCHEMA_LABEL: &str = "target schema"; +pub(crate) const DATABASE_DIMENSION: &str = "database"; +pub(crate) const SCHEMA_DIMENSION: &str = "schema"; +/// An `ENV:` name the request did not look up, which the request builder's scan always finds. +pub(crate) const UNLISTED_ENVIRONMENT: &str = + "a target template read an environment variable the request did not list"; +/// `AttachedAuditTargetKind`'s name in the `ValueError` its constructor raises. +pub(crate) const AUDIT_TARGET_KIND_ENUM: &str = "AttachedAuditTargetKind"; diff --git a/crates/sqlbuild-analysis/src/assembly/project/errors.rs b/crates/sqlbuild-analysis/src/assembly/project/errors.rs new file mode 100644 index 0000000000..69d4586459 --- /dev/null +++ b/crates/sqlbuild-analysis/src/assembly/project/errors.rs @@ -0,0 +1,17 @@ +//! The errors Python's resource assembly raises. + +/// The error Python's resource assembly raises. +#[derive(Debug, Clone, PartialEq, Eq)] +pub enum AssemblyError { + /// `CompileInputError(message, help=help)`. + CompileInput { + message: String, + help: Option, + }, + /// `ValueError(message)`. + Value(String), + /// The exception the request holds at this index, raised as is. + Raise(usize), + /// An internal native failure. + Internal(String), +} diff --git a/crates/sqlbuild-analysis/src/assembly/project/main/assemble_project_resources.rs b/crates/sqlbuild-analysis/src/assembly/project/main/assemble_project_resources.rs index add612c439..4b04fed11d 100644 --- a/crates/sqlbuild-analysis/src/assembly/project/main/assemble_project_resources.rs +++ b/crates/sqlbuild-analysis/src/assembly/project/main/assemble_project_resources.rs @@ -1,73 +1,11 @@ -//! Python's resource assembly facts for one project, or why Python must assemble it. +//! Python's resource assembly facts for one project, up to the resource Python raises at. -use std::cell::RefCell; - -use sqlbuild_core::constants::PANIC_MESSAGE; use sqlbuild_core::panics::main::catch_compiler_panic::catch_compiler_panic; -use crate::assembly::project::_helpers::deps::{audit_deps, reference_deps}; -use crate::assembly::project::_helpers::syntax::syntax_valid; -use crate::assembly::project::_helpers::targets::{managed_source, seed_target}; -use crate::assembly::project::_helpers::templates::TemplateInputs; -use crate::assembly::project::constants::{PANIC_DEFERRAL, SYNTAX_DEFERRAL}; -use crate::assembly::project::models::{ModelFacts, ProjectRequest, ProjectResources}; -use crate::assembly::project::types::Fact; +use crate::assembly::project::_helpers::resources::project_resources; +use crate::assembly::project::models::{ProjectRequest, ProjectResources}; -/// Each resource's dependencies and namespace, or the kind of work Python must do instead. +/// Each resource's facts up to the first resource Python raises at; Err is a native failure. pub fn assemble_project_resources(request: &ProjectRequest) -> Result { - catch_compiler_panic(|| resources(request)).map_err(|kind| { - if kind == PANIC_MESSAGE { - PANIC_DEFERRAL.to_owned() - } else { - kind - } - }) -} - -fn resources(request: &ProjectRequest) -> Fact { - for model in &request.models { - valid_syntax(model, &request.dialect)?; - } - let target = request.target.as_ref(); - let inputs = TemplateInputs { - variables: &request.variables, - environment: &request.environment, - reads: RefCell::new(Vec::new()), - }; - let sources = request - .sources - .iter() - .map(|source| managed_source(source, target, &inputs)) - .collect::>()?; - let seeds = request - .seeds - .iter() - .map(|seed| seed_target(seed, &request.defaults, target, &inputs)) - .collect::>()?; - Ok(ProjectResources { - model_deps: request - .models - .iter() - .map(|model| reference_deps(&model.references)) - .collect(), - sources, - seeds, - function_deps: request - .functions - .iter() - .map(|references| reference_deps(references)) - .collect(), - audit_deps: request.audits.iter().map(audit_deps).collect::>()?, - reads: inputs.reads.into_inner(), - }) -} - -/// Python's model and hook syntax validation, which raises for the first SQL it rejects. -fn valid_syntax(model: &ModelFacts, dialect: &str) -> Fact<()> { - for check in &model.syntax_checks { - if !syntax_valid(check, dialect)? { - return Err(SYNTAX_DEFERRAL.to_owned()); - } - } - Ok(()) + catch_compiler_panic(|| Ok(project_resources(request))) } diff --git a/crates/sqlbuild-analysis/src/assembly/project/main/check_sql_syntax.rs b/crates/sqlbuild-analysis/src/assembly/project/main/check_sql_syntax.rs index a2604be080..2e9c2203a8 100644 --- a/crates/sqlbuild-analysis/src/assembly/project/main/check_sql_syntax.rs +++ b/crates/sqlbuild-analysis/src/assembly/project/main/check_sql_syntax.rs @@ -1,24 +1,19 @@ //! Whether Python's syntax validation accepts every SQL string, stopping at the first it rejects. -use sqlbuild_core::constants::PANIC_MESSAGE; use sqlbuild_core::panics::main::catch_compiler_panic::catch_compiler_panic; use crate::assembly::project::_helpers::syntax::syntax_valid; -use crate::assembly::project::constants::PANIC_DEFERRAL; -use crate::assembly::project::models::SyntaxCheck; +use crate::assembly::project::models::{SyntaxCheck, SyntaxFailure}; -/// True when every check parses, false at the first Python rejects, Err to let Python decide. -pub fn check_sql_syntax(dialect: &str, checks: &[SyntaxCheck]) -> Result { - catch_compiler_panic(|| all_valid(dialect, checks)).map_err(|kind| { - if kind == PANIC_MESSAGE { - PANIC_DEFERRAL.to_owned() - } else { - kind - } - }) +/// Whether every check parses, stopping at the first rejection or `ValueError`; Err is a panic. +pub fn check_sql_syntax( + dialect: &str, + checks: &[SyntaxCheck], +) -> Result, String> { + catch_compiler_panic(|| Ok(all_valid(dialect, checks))) } -fn all_valid(dialect: &str, checks: &[SyntaxCheck]) -> Result { +fn all_valid(dialect: &str, checks: &[SyntaxCheck]) -> Result { for check in checks { if !syntax_valid(check, dialect)? { return Ok(false); diff --git a/crates/sqlbuild-analysis/src/assembly/project/main/mod.rs b/crates/sqlbuild-analysis/src/assembly/project/main/mod.rs index d35ca0b269..dccf961e02 100644 --- a/crates/sqlbuild-analysis/src/assembly/project/main/mod.rs +++ b/crates/sqlbuild-analysis/src/assembly/project/main/mod.rs @@ -1,2 +1,3 @@ pub mod assemble_project_resources; pub mod check_sql_syntax; +pub mod sql_syntax_error; diff --git a/crates/sqlbuild-analysis/src/assembly/project/main/sql_syntax_error.rs b/crates/sqlbuild-analysis/src/assembly/project/main/sql_syntax_error.rs new file mode 100644 index 0000000000..14449abeeb --- /dev/null +++ b/crates/sqlbuild-analysis/src/assembly/project/main/sql_syntax_error.rs @@ -0,0 +1,13 @@ +//! Python's syntax validation message for one SQL string. + +use crate::assembly::project::_helpers::syntax::syntax_error; +use crate::assembly::project::models::{SyntaxCheck, SyntaxFailure, SyntaxMode}; + +/// The message Python's validation raises with, None where Polyglot accepts the SQL. +pub fn sql_syntax_error( + check: &SyntaxCheck, + dialect: &str, + mode: SyntaxMode, +) -> Result, SyntaxFailure> { + syntax_error(check, dialect, mode) +} diff --git a/crates/sqlbuild-analysis/src/assembly/project/mod.rs b/crates/sqlbuild-analysis/src/assembly/project/mod.rs index 4439eb2731..9363ac4cab 100644 --- a/crates/sqlbuild-analysis/src/assembly/project/mod.rs +++ b/crates/sqlbuild-analysis/src/assembly/project/mod.rs @@ -2,6 +2,7 @@ pub(crate) mod _helpers; pub(crate) mod constants; +pub mod errors; pub mod main; pub mod models; pub mod types; diff --git a/crates/sqlbuild-analysis/src/assembly/project/models.rs b/crates/sqlbuild-analysis/src/assembly/project/models.rs index 92d0f34a3c..4dea56fc1f 100644 --- a/crates/sqlbuild-analysis/src/assembly/project/models.rs +++ b/crates/sqlbuild-analysis/src/assembly/project/models.rs @@ -3,6 +3,7 @@ use sqlbuild_model_config::templates::models::Scalar; use crate::assembly::analysis_session::types::Pairs; +use crate::assembly::project::errors::AssemblyError; use crate::assembly::project::types::ObjectKey; /// One SQL reference a resource makes: Python's `CompileSqlReference`. @@ -14,11 +15,45 @@ pub struct Reference { pub package: Option, } -/// One project variable, as a scalar Python renders with `str()`, or a value only Python renders. +/// One project variable: a scalar, or another Python value described by its Python renderings. #[derive(Debug, Clone, PartialEq, Eq)] pub enum Variable { Scalar(Scalar), - Unsupported, + Opaque(OpaqueVariable), +} + +/// A variable value only Python renders: its `str()` and `render_project_var_text` outcome. +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct OpaqueVariable { + /// `str(value)`: a whole-template result and the text the resolver compares. + pub text: String, + pub render: OpaqueRender, +} + +/// `render_project_var_text(value=value, label=label)` for any label. +#[derive(Debug, Clone, PartialEq, Eq)] +pub enum OpaqueRender { + Text(String), + /// The `ValueError` message after the label. + Rejected(String), + /// Another exception, which Python raises; the index of the exception the request holds. + Raises(usize), +} + +/// Which resource list a failure belongs to. +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum ResourceSlot { + Source, + Seed, + Audit, +} + +/// The first resource whose assembly raises, in Python's assembly order. +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct ResourceFailure { + pub slot: ResourceSlot, + pub index: usize, + pub error: AssemblyError, } /// One environment or context lookup a template made, which Python records for compile reuse. @@ -52,9 +87,33 @@ pub struct SyntaxCheck { pub placeholders: Pairs, } -/// One model's references and the SQL strings its assembly validates. +/// Which Polyglot entry point Python's validation calls. +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum SyntaxMode { + /// `validate`, for model queries and hooks. + Validate, + /// `parse_one`, for function bodies and source expressions. + Parse, +} + +/// Where Python's syntax validation raises instead of reporting a message. +#[derive(Debug, Clone, PartialEq, Eq)] +pub enum SyntaxFailure { + /// The analysis normalization's `ValueError` message. + Normalization(String), + /// Polyglot does not know the dialect name. + UnknownDialect(String), +} + +/// One model's identity, graph facts, references and the SQL strings its assembly validates. #[derive(Debug, Clone, PartialEq, Eq)] pub struct ModelFacts { + /// The model's name: its file stem, the name of its `("model", name)` key. + pub name: String, + /// `str(model_file.relative_path.parent)`, the folder project selectors match. + pub directory: String, + /// `config.values["tags"]` items as `str()` where a list or tuple, else empty. + pub tags: Vec, pub references: Vec, pub syntax_checks: Vec, } @@ -68,14 +127,26 @@ pub struct SourceFacts { pub schema: Option, } -/// One seed's name and authored namespace. +/// One seed's name, tags and authored namespace. #[derive(Debug, Clone, PartialEq, Eq)] pub struct SeedFacts { pub name: String, + /// `schema_entry.tags`. + pub tags: Vec, pub database: Option, pub schema: Option, } +/// One SQL function's key, tags and references. +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct FunctionFacts { + /// `function_node_type(return_columns)`: `udf` or `table_fn`, its key's resource type. + pub kind: String, + pub name: String, + pub tags: Vec, + pub references: Vec, +} + /// One audit's references and the resource it is attached to. #[derive(Debug, Clone, PartialEq, Eq)] pub struct AuditFacts { @@ -97,7 +168,7 @@ pub struct ProjectRequest { pub models: Vec, pub sources: Vec, pub seeds: Vec, - pub functions: Vec>, + pub functions: Vec, pub audits: Vec, } @@ -114,10 +185,14 @@ pub struct Namespace { #[derive(Debug, Clone, Default, PartialEq, Eq)] pub struct ProjectResources { pub model_deps: Vec>, + /// Whether every SQL string a model's assembly validates parses; Python reports failures. + pub model_syntax_valid: Vec, /// A managed source's `(database, schema)`; None where the entry stays as authored. pub sources: Vec, Option)>>, pub seeds: Vec, pub function_deps: Vec>, pub audit_deps: Vec>, pub reads: Vec, + /// The resource Python raises at; the lists stop before it and later resources are absent. + pub failure: Option, } diff --git a/crates/sqlbuild-analysis/src/assembly/project/tests/helpers.rs b/crates/sqlbuild-analysis/src/assembly/project/tests/helpers.rs index e983316a09..d876b617ae 100644 --- a/crates/sqlbuild-analysis/src/assembly/project/tests/helpers.rs +++ b/crates/sqlbuild-analysis/src/assembly/project/tests/helpers.rs @@ -8,8 +8,8 @@ use crate::assembly::project::_helpers::targets::{managed_source, seed_target}; use crate::assembly::project::_helpers::templates::TemplateInputs; use crate::assembly::project::main::check_sql_syntax::check_sql_syntax; use crate::assembly::project::models::{ - AuditFacts, InputRead, Namespace, Reference, SeedDefaults, SeedFacts, SourceFacts, SyntaxCheck, - TargetNamespace, Variable, + AuditFacts, InputRead, Namespace, OpaqueRender, OpaqueVariable, Reference, SeedDefaults, + SeedFacts, SourceFacts, SyntaxCheck, TargetNamespace, Variable, }; use crate::assembly::project::tests::test_types::{ExpectedNamespace, SeedSpec}; use crate::assembly::project::types::ObjectKey; @@ -42,6 +42,7 @@ pub(crate) fn seed( seed_target( &SeedFacts { name: name.to_owned(), + tags: Vec::new(), database: database.map(str::to_owned), schema: schema.map(str::to_owned), }, @@ -72,6 +73,7 @@ pub(crate) fn seed_reads( let resolved = seed_target( &SeedFacts { name: name.to_owned(), + tags: Vec::new(), database: database.map(str::to_owned), schema: schema.map(str::to_owned), }, @@ -123,7 +125,7 @@ pub(crate) fn all_valid(sqls: &[&str]) -> Option { placeholders: vec![("x".to_owned(), "1".to_owned())], }) .collect(); - check_sql_syntax("generic", &checks).ok() + check_sql_syntax("generic", &checks).ok()?.ok() } pub(crate) fn namespace(expected: ExpectedNamespace) -> Namespace { @@ -173,6 +175,16 @@ fn variables() -> Vec<(String, Variable)> { Variable::Scalar(Scalar::Text("3".to_owned())), ), ("flag".to_owned(), Variable::Scalar(Scalar::Bool(true))), - ("tags".to_owned(), Variable::Unsupported), + ( + "tags".to_owned(), + Variable::Opaque(OpaqueVariable { + text: "['daily']".to_owned(), + render: OpaqueRender::Rejected( + " is an array and cannot be interpolated as text: [\"daily\"]. Use a macro \ + to consume structured vars." + .to_owned(), + ), + }), + ), ] } diff --git a/crates/sqlbuild-analysis/src/assembly/project/tests/test_project_assembly.rs b/crates/sqlbuild-analysis/src/assembly/project/tests/test_project_assembly.rs index 184a8b3ff3..d9549857eb 100644 --- a/crates/sqlbuild-analysis/src/assembly/project/tests/test_project_assembly.rs +++ b/crates/sqlbuild-analysis/src/assembly/project/tests/test_project_assembly.rs @@ -59,7 +59,7 @@ fn given_references_when_deriving_deps_then_matches_python_keys() { } #[test] -fn given_seeds_when_resolving_targets_then_matches_python_or_defers() { +fn given_seeds_when_resolving_targets_then_matches_python_or_raises() { let test_cases = [ SeedTestCase { description: "defaults and the seed's templates read variables and updated context", @@ -116,17 +116,24 @@ fn given_seeds_when_resolving_targets_then_matches_python_or_defers() { expected_namespace: None, }, SeedTestCase { - description: "environment reads stay with Python", + description: "an environment name the request did not list is an internal failure", seed: ("countries", None, Some("${ENV:SEED_SCHEMA}")), defaults: (None, None, None, None), target: None, expected_namespace: None, }, SeedTestCase { - description: "a variable only Python renders", + description: "a whole-template list variable is Python's str of the list", seed: ("countries", None, Some("${tags}")), defaults: (None, None, None, None), target: None, + expected_namespace: Some((None, Some("['daily']"), None, Some("['daily']"))), + }, + SeedTestCase { + description: "a list variable inside text raises Python's interpolation error", + seed: ("countries", None, Some("s_${tags}")), + defaults: (None, None, None, None), + target: None, expected_namespace: None, }, ]; @@ -181,7 +188,7 @@ fn given_sources_when_resolving_managed_targets_then_matches_python() { } #[test] -fn given_model_sql_when_validating_syntax_then_matches_python_or_defers() { +fn given_model_sql_when_validating_syntax_then_matches_python_or_raises() { let test_cases = [ SyntaxTestCase { dialect: "duckdb", @@ -206,17 +213,17 @@ fn given_model_sql_when_validating_syntax_then_matches_python_or_defers() { }, SyntaxTestCase { dialect: "duckdb", - description: "a placeholder followed by text Python's \\w may extend", + description: "a placeholder name Python's \\w extends past ASCII stays authored", sql: "SELECT @@@x\u{e9} AS a", placeholders: &[("x", "1")], - expected_valid: None, + expected_valid: Some(true), }, SyntaxTestCase { dialect: "trino", - description: "a dialect this parser build does not carry", + description: "a dialect outside the old parser build reads as the wheel does", sql: "SELECT 1 AS a FROM t QUALIFY a = 1", placeholders: &[], - expected_valid: None, + expected_valid: Some(false), }, ]; for test_case in test_cases { @@ -261,7 +268,7 @@ fn given_environment_templates_when_resolving_seeds_then_matches_python_values_a expected_reads: vec![InputRead::Environment("SQB_UNSET_SCHEMA".to_owned())], }, EnvironmentTestCase { - description: "a name Python did not resolve stays with Python", + description: "a name the request did not list is an internal failure", seed: ( "countries", None, @@ -292,7 +299,7 @@ fn given_environment_templates_when_resolving_seeds_then_matches_python_values_a } #[test] -fn given_sql_batches_when_checking_syntax_then_stops_at_python_first_rejection_or_defers() { +fn given_sql_batches_when_checking_syntax_then_stops_at_python_first_rejection_or_raise() { let test_cases = [ SyntaxBatchTestCase { description: "every statement parses", @@ -310,9 +317,9 @@ fn given_sql_batches_when_checking_syntax_then_stops_at_python_first_rejection_o expected_valid: Some(false), }, SyntaxBatchTestCase { - description: "a statement native defers before any rejection", + description: "a non-ASCII placeholder name before a rejection", sqls: &["SELECT @@@x\u{e9}", "SELECT FROM WHERE ("], - expected_valid: None, + expected_valid: Some(false), }, ]; for test_case in test_cases { diff --git a/crates/sqlbuild-analysis/src/assembly/project/tests/test_types.rs b/crates/sqlbuild-analysis/src/assembly/project/tests/test_types.rs index ca67d431c2..adfbe725ba 100644 --- a/crates/sqlbuild-analysis/src/assembly/project/tests/test_types.rs +++ b/crates/sqlbuild-analysis/src/assembly/project/tests/test_types.rs @@ -53,7 +53,7 @@ pub(crate) struct SyntaxTestCase { pub(crate) dialect: &'static str, pub(crate) sql: &'static str, pub(crate) placeholders: &'static [(&'static str, &'static str)], - /// None where native defers to Python. + /// None where Python raises. pub(crate) expected_valid: Option, } @@ -77,6 +77,6 @@ pub(crate) struct EnvironmentTestCase { pub(crate) struct SyntaxBatchTestCase { pub(crate) description: &'static str, pub(crate) sqls: &'static [&'static str], - /// None where native defers to Python. + /// None where Python raises. pub(crate) expected_valid: Option, } diff --git a/crates/sqlbuild-analysis/src/assembly/project/types.rs b/crates/sqlbuild-analysis/src/assembly/project/types.rs index 8d39093007..981e162728 100644 --- a/crates/sqlbuild-analysis/src/assembly/project/types.rs +++ b/crates/sqlbuild-analysis/src/assembly/project/types.rs @@ -1,7 +1,9 @@ //! Project assembly key and result aliases. -/// One step's result, or the deferral kind Python must assemble the project for. -pub(crate) type Fact = Result; +use crate::assembly::project::errors::AssemblyError; + +/// One step's result, or the error Python's assembly raises there. +pub(crate) type Fact = Result; /// A `CompiledObjectKey`: `(resource type, name)`. pub type ObjectKey = (String, String); diff --git a/crates/sqlbuild-analysis/src/compiler/_helpers/sql_tests/assembly.rs b/crates/sqlbuild-analysis/src/compiler/_helpers/sql_tests/assembly.rs index 6836d3cf0f..a768faf024 100644 --- a/crates/sqlbuild-analysis/src/compiler/_helpers/sql_tests/assembly.rs +++ b/crates/sqlbuild-analysis/src/compiler/_helpers/sql_tests/assembly.rs @@ -3,13 +3,13 @@ use rayon::prelude::{IntoParallelRefIterator, ParallelIterator}; use sqlbuild_sqltext::sql_scan::models::LexicalSyntax; -use crate::compiler::_helpers::sql_tests::case_identity::case_fingerprint; +use crate::compiler::_helpers::sql_tests::case_identity::{FingerprintFailure, case_fingerprint}; use crate::compiler::_helpers::sql_tests::macro_call_names::macro_call_names; use crate::compiler::_helpers::sql_tests::mock_reads::{ MockReadsRequest, mock_reading_helper_diagnostics, }; use crate::compiler::models::{ - AssembledSqlTestFacts, SqlTestAssemblyBatch, SqlTestAssemblyDeferral, SqlTestAssemblyModel, + AssembledSqlTestFacts, SqlTestAssemblyBatch, SqlTestAssemblyFailure, SqlTestAssemblyModel, SqlTestAssemblyOutcome, SqlTestAssemblyPayload, SqlTestAssemblyTest, SqlTestHelperDiagnostic, }; @@ -19,7 +19,7 @@ const MACRO_MODE: &str = "macro"; const UDF_MODE: &str = "udf"; const UDF_REFERENCE_KIND: &str = "udf"; -/// Each test's facts in request order, or the reason Python assembles it. +/// Each test's facts in request order, or why its assembly raises. pub(crate) fn assemble_batch(batch: &SqlTestAssemblyBatch) -> Vec { let tests_macros = batch.tests.iter().any(|test| { matches!(&test.payload, SqlTestAssemblyPayload::Direct { mode, .. } if mode == MACRO_MODE) @@ -42,14 +42,14 @@ pub(crate) fn assemble_batch(batch: &SqlTestAssemblyBatch) -> Vec SqlTestAssemblyOutcome::Assembled(facts), - Err(deferral) => SqlTestAssemblyOutcome::Deferred(deferral), + Ok(outcome) => outcome, + Err(failure) => SqlTestAssemblyOutcome::Failed(failure), }) .collect() } /// A model's macro dependencies, or Python's scan of its pre-macro SQL when none were recorded. -type MacroNames = Result, SqlTestAssemblyDeferral>; +type MacroNames = Result, String>; struct Project<'a> { models: &'a [SqlTestAssemblyModel], @@ -60,7 +60,7 @@ struct Project<'a> { fn assemble( test: &SqlTestAssemblyTest, project: &Project<'_>, -) -> Result { +) -> Result { let models = project.models; let syntax = project.syntax; let mut target_model_names: Vec = Vec::new(); @@ -78,9 +78,6 @@ fn assemble( direct_scope_deps(mode, tested_resource_names, project)? } SqlTestAssemblyPayload::Model(payload) => { - if payload.has_macro_mocks { - return Err(SqlTestAssemblyDeferral::MacroMocks); - } for name in payload .expected_model_names .iter() @@ -104,16 +101,23 @@ fn assemble( .collect() } }; + let mut overflow = false; let case_fingerprint = match &test.case_name { - Some(case_name) => Some(case_fingerprint( - test, - case_name, - &scope_deps, - &tested_resources, - )?), + Some(case_name) => { + match case_fingerprint(test, case_name, &scope_deps, &tested_resources) { + Ok(fingerprint) => Some(fingerprint), + Err(FingerprintFailure::DecimalOverflow) => { + overflow = true; + None + } + Err(FingerprintFailure::Internal(reason)) => { + return Err(SqlTestAssemblyFailure::Internal(reason)); + } + } + } None => None, }; - Ok(AssembledSqlTestFacts { + let facts = AssembledSqlTestFacts { name: test_name(test), scope_deps, target_model_names, @@ -122,6 +126,11 @@ fn assemble( .unwrap_or(&test.relative_stem) .to_owned(), diagnostics, + }; + Ok(if overflow { + SqlTestAssemblyOutcome::FingerprintOverflow(facts) + } else { + SqlTestAssemblyOutcome::Assembled(facts) }) } @@ -143,12 +152,14 @@ fn direct_scope_deps( mode: &str, tested_names: &[String], project: &Project<'_>, -) -> Result, SqlTestAssemblyDeferral> { +) -> Result, SqlTestAssemblyFailure> { let mut scope_deps: Vec<(&'static str, String)> = Vec::new(); match mode { MACRO_MODE => { for (model, names) in project.models.iter().zip(project.macro_names) { - let names = names.as_ref().map_err(|deferral| *deferral)?; + let names = names + .as_ref() + .map_err(|message| SqlTestAssemblyFailure::Input(message.clone()))?; if names.iter().any(|name| tested_names.contains(name)) { scope_deps.push((MODEL_RESOURCE, model.name.clone())); } diff --git a/crates/sqlbuild-analysis/src/compiler/_helpers/sql_tests/case_identity.rs b/crates/sqlbuild-analysis/src/compiler/_helpers/sql_tests/case_identity.rs index 4bbc98f63f..801e993b33 100644 --- a/crates/sqlbuild-analysis/src/compiler/_helpers/sql_tests/case_identity.rs +++ b/crates/sqlbuild-analysis/src/compiler/_helpers/sql_tests/case_identity.rs @@ -4,14 +4,25 @@ use sha2::{Digest, Sha256}; use sqlbuild_core::json::main::dumps::dumps; use sqlbuild_core::json::models::{JsonDialect, JsonInteger, JsonValue, StdlibJsonOptions}; -use crate::compiler::models::{ - SqlTestAssemblyDeferral, SqlTestAssemblyTest, SqlTestParameterValue, -}; +use crate::compiler::models::{SqlTestAssemblyTest, SqlTestParameterValue}; + +/// Why Python's fingerprint of a case raises. +#[derive(Debug, PartialEq, Eq)] +pub(crate) enum FingerprintFailure { + /// `Decimal.normalize()` overflows the default context: Python raises `decimal.Overflow`. + DecimalOverflow, + /// An internal native failure. + Internal(String), +} /// Python's default decimal context: precision and exponent limits `normalize()` applies. const DECIMAL_PRECISION: usize = 28; +/// The largest decimal digit, which carries when rounded up. +const MAX_DIGIT: u8 = 9; const DECIMAL_EMAX: i64 = 999_999; const DECIMAL_EMIN: i64 = -999_999; +/// The smallest exponent of a subnormal result: `Emin - prec + 1`. +const DECIMAL_ETINY: i64 = DECIMAL_EMIN - 27; /// The SHA-256 of Python's compact, ASCII, key-sorted JSON of the case's compile inputs. pub(crate) fn case_fingerprint( @@ -19,7 +30,7 @@ pub(crate) fn case_fingerprint( case_name: &str, scope_deps: &[(&'static str, String)], tested_resources: &[(String, String)], -) -> Result { +) -> Result { let mut sorted_deps: Vec<(&str, &str)> = scope_deps .iter() .map(|(kind, name)| (*kind, name.as_str())) @@ -34,7 +45,7 @@ pub(crate) fn case_fingerprint( .parameter_values .iter() .map(|(name, value)| Ok(JsonValue::Array(vec![string(name), identity(value)?]))) - .collect::>()?; + .collect::>()?; let payload = JsonValue::Object(vec![ ("source_path".to_owned(), string(&test.relative_path)), ("block_index".to_owned(), integer(test.block_index)), @@ -70,8 +81,11 @@ pub(crate) fn case_fingerprint( sort_keys: true, allow_nan: true, }); - let encoded = - dumps(&payload, &dialect).map_err(|_| SqlTestAssemblyDeferral::UnencodableValue)?; + let encoded = dumps(&payload, &dialect).map_err(|error| { + FingerprintFailure::Internal(format!( + "the case fingerprint payload does not encode: {error:?}" + )) + })?; Ok(Sha256::digest(encoded.as_bytes()) .iter() .map(|byte| format!("{byte:02x}")) @@ -96,7 +110,7 @@ fn pairs(entries: &[(&str, &str)]) -> JsonValue { } /// Python's `sql_value_identity`: `(kind, payload)` with decimals as normalized tuples. -fn identity(value: &SqlTestParameterValue) -> Result { +fn identity(value: &SqlTestParameterValue) -> Result { let (kind, payload) = match value { SqlTestParameterValue::String(text) => ("string", string(text)), SqlTestParameterValue::Integer(number) => ("integer", integer(*number)), @@ -116,53 +130,111 @@ fn identity(value: &SqlTestParameterValue) -> Result>()?, + .collect::>()?, ), ), }; Ok(JsonValue::Array(vec![string(kind), payload])) } -fn identities(items: &[SqlTestParameterValue]) -> Result { +fn identities(items: &[SqlTestParameterValue]) -> Result { Ok(JsonValue::Array( items.iter().map(identity).collect::>()?, )) } -/// `Decimal.normalize().as_tuple()` where the default context neither rounds nor clamps. +/// `Decimal.normalize().as_tuple()` under Python's default context. fn normalized_decimal( negative: bool, digits: &[u8], exponent: i64, -) -> Result { +) -> Result { let sign = integer(i64::from(negative)); - let first = digits.iter().position(|digit| *digit != 0); - let Some(first) = first else { - return Ok(JsonValue::Array(vec![ - sign, + let zero = || { + JsonValue::Array(vec![ + integer(i64::from(negative)), JsonValue::Array(vec![integer(0)]), integer(0), - ])); + ]) + }; + let Some(first) = digits.iter().position(|digit| *digit != 0) else { + return Ok(zero()); }; - let significant = &digits[first..]; - let adjusted = exponent + i64::try_from(significant.len()).unwrap_or(i64::MAX) - 1; - if significant.len() > DECIMAL_PRECISION || !(DECIMAL_EMIN..=DECIMAL_EMAX).contains(&adjusted) { - return Err(SqlTestAssemblyDeferral::DecimalContext); + let mut coefficient: Vec = digits[first..].to_vec(); + let mut exponent: i64 = exponent; + let length = |coefficient: &[u8]| i64::try_from(coefficient.len()).unwrap_or(i64::MAX); + let adjusted: i64 = exponent.saturating_add(length(&coefficient) - 1); + let dropped: i64 = if adjusted < DECIMAL_EMIN { + DECIMAL_ETINY.saturating_sub(exponent).max(0) + } else { + (length(&coefficient) - i64::try_from(DECIMAL_PRECISION).unwrap_or(i64::MAX)).max(0) + }; + if dropped > 0 { + coefficient = + rounded_half_even(&coefficient, usize::try_from(dropped).unwrap_or(usize::MAX)); + exponent = exponent.saturating_add(dropped); + if coefficient.len() > DECIMAL_PRECISION { + let _ = coefficient.pop(); + exponent = exponent.saturating_add(1); + } + if coefficient.iter().all(|digit| *digit == 0) { + return Ok(zero()); + } + } + if exponent.saturating_add(length(&coefficient) - 1) > DECIMAL_EMAX { + return Err(FingerprintFailure::DecimalOverflow); } - let mut end = significant.len(); - let mut normalized_exponent = exponent; - while significant[end - 1] == 0 && normalized_exponent < DECIMAL_EMAX { + let mut end = coefficient.len(); + while coefficient[end - 1] == 0 && exponent < DECIMAL_EMAX { end -= 1; - normalized_exponent += 1; + exponent += 1; } Ok(JsonValue::Array(vec![ sign, JsonValue::Array( - significant[..end] + coefficient[..end] .iter() .map(|digit| integer(i64::from(*digit))) .collect(), ), - integer(normalized_exponent), + integer(exponent), ])) } + +/// The coefficient without its last `dropped` digits, rounded half-even; a carry adds a digit. +fn rounded_half_even(coefficient: &[u8], dropped: usize) -> Vec { + if dropped > coefficient.len() { + return vec![0]; + } + let (kept, removed) = coefficient.split_at(coefficient.len() - dropped); + let mut kept: Vec = if kept.is_empty() { + vec![0] + } else { + kept.to_vec() + }; + let round_up: bool = match removed.first() { + Some(6..=9) => true, + Some(5) => { + removed[1..].iter().any(|digit| *digit != 0) + || kept.last().is_some_and(|digit| digit % 2 == 1) + } + _ => false, + }; + if round_up { + let mut index = kept.len(); + loop { + if index == 0 { + kept.insert(0, 1); + break; + } + index -= 1; + if kept[index] == MAX_DIGIT { + kept[index] = 0; + } else { + kept[index] += 1; + break; + } + } + } + kept +} diff --git a/crates/sqlbuild-analysis/src/compiler/_helpers/sql_tests/macro_call_names.rs b/crates/sqlbuild-analysis/src/compiler/_helpers/sql_tests/macro_call_names.rs index 38c0421c61..e0c42597d8 100644 --- a/crates/sqlbuild-analysis/src/compiler/_helpers/sql_tests/macro_call_names.rs +++ b/crates/sqlbuild-analysis/src/compiler/_helpers/sql_tests/macro_call_names.rs @@ -1,105 +1,15 @@ -//! Python's `find_macro_call_names`: unique top-level macro call names in encounter order. +//! Python's `find_macro_call_names` over a model's pre-macro SQL. -use sqlbuild_sqltext::sql_scan::main::matching_paren::matching_paren; -use sqlbuild_sqltext::sql_scan::main::non_code_end::non_code_end; -use sqlbuild_sqltext::sql_scan::models::QuotePolicy; +use sqlbuild_core::text::main::active_python_text::active_python_text; +use sqlbuild_render::macro_calls::main::macro_call_names::macro_call_names as scanned_names; -use crate::compiler::models::SqlTestAssemblyDeferral; - -/// Declaration calls that expansion substitutes rather than running as macros. +/// Declaration calls expansion substitutes rather than running as macros. const DECLARATION_CALLS: [&str; 2] = ["enum", "const"]; -type Scan = Result; - -/// The names Python's scan returns; text it raises on, or classifies by Unicode, is Python's. -pub(crate) fn macro_call_names(sql: &str) -> Scan> { - let bytes = sql.as_bytes(); - let mut names: Vec = Vec::new(); - let mut index = 0; - while index < bytes.len() { - match non_code_end(bytes, index, QuotePolicy::COMPILER) { - Ok(Some(end)) => { - index = end; - continue; - } - Ok(None) => {} - Err(_) => return Err(SqlTestAssemblyDeferral::MacroCallScan), - } - if bytes[index] != b'@' || !macro_call_at(bytes, index)? { - index += 1; - continue; - } - let name_end = identifier_end(bytes, index + 1)?; - let name = &sql[index + 1..name_end]; - if !names.iter().any(|known| known == name) { - names.push(name.to_owned()); - } - let open = space_end(bytes, name_end)?; - if bytes.get(open) != Some(&b'(') { - return Err(SqlTestAssemblyDeferral::MacroCallScan); - } - index = matching_paren(bytes, open, QuotePolicy::COMPILER) - .map_err(|_| SqlTestAssemblyDeferral::MacroCallScan)? - + 1; - } +/// The names Python's scan returns, or the message of the `CompileInputError` it raises. +pub(crate) fn macro_call_names(sql: &str) -> Result, String> { + let mut names: Vec = scanned_names(active_python_text(), sql, false) + .map_err(|error| error.message().to_owned())?; names.retain(|name| !DECLARATION_CALLS.contains(&name.as_str())); Ok(names) } - -/// Python's `_is_macro_call_start`, which skips whitespace after each name character. -fn macro_call_at(bytes: &[u8], at: usize) -> Scan { - let Some(&first) = bytes.get(at + 1) else { - return Ok(false); - }; - if !ascii(first)? || !(first == b'_' || first.is_ascii_alphabetic()) { - return Ok(false); - } - let mut cursor = at + 2; - while let Some(&byte) = bytes.get(cursor) { - if !ascii(byte)? || !is_identifier_continue(byte) { - break; - } - cursor = space_end(bytes, cursor + 1)?; - } - Ok(bytes.get(cursor) == Some(&b'(')) -} - -fn identifier_end(bytes: &[u8], start: usize) -> Scan { - let mut cursor = start; - while let Some(&byte) = bytes.get(cursor) { - if !ascii(byte)? || !is_identifier_continue(byte) { - break; - } - cursor += 1; - } - Ok(cursor) -} - -/// Python's `str.isspace` skip; a non-ASCII character there is classified by Python. -fn space_end(bytes: &[u8], start: usize) -> Scan { - let mut cursor = start; - while let Some(&byte) = bytes.get(cursor) { - if !ascii(byte)? - || !matches!( - byte, - b' ' | b'\t' | b'\n' | b'\r' | 0x0b | 0x0c | 0x1c..=0x1f - ) - { - break; - } - cursor += 1; - } - Ok(cursor) -} - -fn is_identifier_continue(byte: u8) -> bool { - byte == b'_' || byte.is_ascii_alphanumeric() -} - -fn ascii(byte: u8) -> Scan { - if byte.is_ascii() { - Ok(true) - } else { - Err(SqlTestAssemblyDeferral::MacroCallScan) - } -} diff --git a/crates/sqlbuild-analysis/src/compiler/_helpers/sql_tests/mock_reads.rs b/crates/sqlbuild-analysis/src/compiler/_helpers/sql_tests/mock_reads.rs index 5e9793b5e8..60f90b333b 100644 --- a/crates/sqlbuild-analysis/src/compiler/_helpers/sql_tests/mock_reads.rs +++ b/crates/sqlbuild-analysis/src/compiler/_helpers/sql_tests/mock_reads.rs @@ -2,17 +2,23 @@ use std::collections::HashSet; +use polyglot_sql::expressions::With; use polyglot_sql::{ ComplexityGuardOptions, Dialect, DialectType, Expression, ExpressionWalk, ParseOptions, }; -use serde_json::Value; +use sqlbuild_core::text::main::active_python_text::active_python_text; +use sqlbuild_core::text::main::is_python_space::is_python_space; +use sqlbuild_core::text::main::is_python_word::is_python_word; +use sqlbuild_core::text::main::python_casefold::python_casefold; +use sqlbuild_core::text::main::python_ignorecase_key::python_ignorecase_key; +use sqlbuild_core::text::models::PythonText; use sqlbuild_sqltext::sql_references::main::extract_sql_references::extract_sql_references; use sqlbuild_sqltext::sql_references::models::{ReferenceExtraction, SqlReference}; use sqlbuild_sqltext::sql_scan::models::LexicalSyntax; use crate::compiler::_helpers::sql_tests::planning::MOCK_CTE_PREFIXES; use crate::compiler::models::{ - SqlTestAssemblyDeferral, SqlTestAssemblyModel, SqlTestAssemblyModelPayload, + SqlTestAssemblyFailure, SqlTestAssemblyModel, SqlTestAssemblyModelPayload, SqlTestAssemblyReference, SqlTestAssemblyTest, SqlTestCte, SqlTestHelperDiagnostic, }; @@ -26,12 +32,10 @@ const RELATION_KINDS: [&str; 5] = [ DBT_REF_KIND, TABLE_FUNCTION_KIND, ]; -/// Payload nesting past which the parsed tree is left to Python's `to_dict` walk. -const MAX_TREE_DEPTH: usize = 400; /// The function call depth SQLBuild's Polyglot proxy allows `parse_one`. const MAX_FUNCTION_CALL_DEPTH: usize = 512; -type Deferrable = Result; +type Deferrable = Result; /// A reference as compile carries it: the scanner's or a model input's. #[derive(Clone)] @@ -152,13 +156,12 @@ pub(crate) fn mock_reading_helper_diagnostics( .into_iter() .find(|reference| RELATION_KINDS.contains(&reference.kind.as_str())); if let Some(reference) = first { - referencing.assign(ascii_fold(&cte.name)?, reference); + referencing.assign(fold(&cte.name), reference); } } if referencing.entries.is_empty() { return Ok(Vec::new()); } - require_ascii(request.test, payload)?; let readers: Vec<&SqlTestCte> = payload .expected_ctes .iter() @@ -218,42 +221,18 @@ fn is_mock_name(name: &str) -> bool { .any(|prefix| name.starts_with(prefix)) } -/// Python's `str.casefold`, exact only on ASCII text. -fn ascii_fold(text: &str) -> Deferrable { - if text.is_ascii() { - Ok(text.to_ascii_lowercase()) - } else { - Err(SqlTestAssemblyDeferral::NonAsciiText) - } +/// Python's `str.casefold`. +fn fold(text: &str) -> String { + python_casefold(active_python_text(), text) } -/// Python's folding, token and header patterns read only ASCII text exactly. -fn require_ascii( - test: &SqlTestAssemblyTest, - payload: &SqlTestAssemblyModelPayload, -) -> Deferrable<()> { - let ascii = test.contents.is_ascii() - && test.block_sql.is_ascii() - && payload - .authored_ctes - .iter() - .chain(&payload.expected_ctes) - .chain(&payload.assertion_ctes) - .all(|cte| cte.name.is_ascii() && cte.sql_body.is_ascii()); - if ascii { - Ok(()) - } else { - Err(SqlTestAssemblyDeferral::NonAsciiText) - } -} - -/// Python's `scan_sql_reference_calls(...).references`; a failing scan is Python's to raise. +/// Python's `scan_sql_reference_calls(...).references`; a failing scan raises unlocated. fn references(sql: &str, syntax: &LexicalSyntax) -> Deferrable> { match extract_sql_references(sql, syntax) { ReferenceExtraction::Extracted(scan) => { Ok(scan.references.into_iter().map(scanned).collect()) } - ReferenceExtraction::Failed(_) => Err(SqlTestAssemblyDeferral::ReferenceScan), + ReferenceExtraction::Failed(failure) => Err(SqlTestAssemblyFailure::Input(failure.message)), } } @@ -277,7 +256,7 @@ fn model_reference(reference: &SqlTestAssemblyReference) -> Reference { fn cte_graph<'a>(authored: &'a [SqlTestCte], readers: &[&SqlTestCte]) -> Deferrable> { let mut ctes: OrderedEntries<&'a SqlTestCte> = OrderedEntries::new(); for cte in authored { - ctes.assign(ascii_fold(&cte.name)?, cte); + ctes.assign(fold(&cte.name), cte); } let keys: Vec = ctes.keys(); let mut reads: OrderedEntries> = OrderedEntries::new(); @@ -310,7 +289,7 @@ fn cte_graph<'a>(authored: &'a [SqlTestCte], readers: &[&SqlTestCte]) -> Deferra /// Python's `_parsed_reads`: unqualified reads of `keys` no nested CTE shadows, or None unparsed. fn parsed_reads(sql: &str, keys: &[String]) -> Deferrable>> { - let folded = ascii_fold(sql)?; + let folded = fold(sql); if !keys.iter().any(|key| folded.contains(key.as_str())) { return Ok(Some(Vec::new())); } @@ -323,7 +302,7 @@ fn parsed_reads(sql: &str, keys: &[String]) -> Deferrable>> { return Ok(None); } let parsed: Expression = statements.remove(0); - let nested = defined_cte_keys(&parsed)?; + let nested = defined_cte_keys(&parsed); let mut reads: Vec = Vec::new(); for node in parsed.dfs() { let Expression::Table(table) = node else { @@ -332,7 +311,7 @@ fn parsed_reads(sql: &str, keys: &[String]) -> Deferrable>> { if table.schema.is_some() || table.catalog.is_some() { continue; } - let key = ascii_fold(&table.name.name)?; + let key = fold(&table.name.name); if keys.contains(&key) && !nested.contains(&key) && !reads.contains(&key) { reads.push(key); } @@ -345,61 +324,54 @@ fn proxy_parse_options() -> Deferrable { let guard: ComplexityGuardOptions = serde_json::from_value(serde_json::json!({ "maxFunctionCallDepth": MAX_FUNCTION_CALL_DEPTH, })) - .map_err(|_| SqlTestAssemblyDeferral::UnreadableTree)?; + .map_err(|error| SqlTestAssemblyFailure::Internal(error.to_string()))?; Ok(ParseOptions { complexity_guard: Some(guard), }) } -/// Python's `_defined_cte_keys` over the serialized tree Python's `to_dict` returns. -fn defined_cte_keys(parsed: &Expression) -> Deferrable> { - let tree = serde_json::to_value(parsed).map_err(|_| SqlTestAssemblyDeferral::UnreadableTree)?; +/// Python's `_defined_cte_keys` over `to_dict()`. +fn defined_cte_keys(parsed: &Expression) -> HashSet { let mut keys: HashSet = HashSet::new(); - let mut pending: Vec<(&Value, usize)> = vec![(&tree, 0)]; - while let Some((value, depth)) = pending.pop() { - if depth > MAX_TREE_DEPTH { - return Err(SqlTestAssemblyDeferral::UnreadableTree); - } - match value { - Value::Array(items) => pending.extend(items.iter().map(|item| (item, depth + 1))), - Value::Object(entries) => { - if let Some(Value::Array(ctes)) = entries.get("ctes") { - for cte in ctes { - if let Some(Value::String(name)) = cte - .get("alias") - .filter(|alias| alias.is_object()) - .and_then(|alias| alias.get("name")) - { - let _ = keys.insert(ascii_fold(name)?); - } - } - } - pending.extend(entries.values().map(|item| (item, depth + 1))); - } - _ => {} + for node in parsed.dfs() { + let with: Option<&With> = match node { + Expression::Select(select) => select.with.as_ref(), + Expression::Union(union) => union.with.as_ref(), + Expression::Intersect(intersect) => intersect.with.as_ref(), + Expression::Except(except) => except.with.as_ref(), + Expression::Pivot(pivot) => pivot.with.as_ref(), + Expression::Insert(insert) => insert.with.as_ref(), + Expression::Update(update) => update.with.as_ref(), + Expression::Delete(delete) => delete.with.as_ref(), + Expression::CreateTable(create) => create.with_cte.as_ref(), + Expression::With(with) => Some(with), + _ => None, + }; + for cte in with.map_or(&[][..], |with| with.ctes.as_slice()) { + let _ = keys.insert(fold(&cte.alias.name)); } } - Ok(keys) + keys } -/// Python's `_token_reads` over `[A-Za-z_][\w$]*` tokens of ASCII text. +/// Python's `_token_reads` over `[A-Za-z_][\w$]*` tokens. fn token_reads(sql: &str, keys: &[String]) -> Vec { - let bytes = sql.as_bytes(); + let python: PythonText = active_python_text(); + let chars: Vec<(usize, char)> = sql.char_indices().collect(); let mut tokens: Vec = Vec::new(); let mut index = 0; - while index < bytes.len() { - if !(bytes[index].is_ascii_alphabetic() || bytes[index] == b'_') { + while index < chars.len() { + if !(chars[index].1.is_ascii_alphabetic() || chars[index].1 == '_') { index += 1; continue; } - let start = index; + let start = chars[index].0; index += 1; - while index < bytes.len() - && (bytes[index].is_ascii_alphanumeric() || matches!(bytes[index], b'_' | b'$')) - { + while index < chars.len() && is_word_or_dollar(python, chars[index].1) { index += 1; } - let token = sql[start..index].to_ascii_lowercase(); + let end = chars.get(index).map_or(sql.len(), |(offset, _)| *offset); + let token = fold(&sql[start..end]); if !tokens.contains(&token) { tokens.push(token); } @@ -433,7 +405,7 @@ fn mock_keys(reference: &Reference) -> Deferrable> { } names .iter() - .map(|name| ascii_fold(&format!("{prefix}{name}"))) + .map(|name| Ok(fold(&format!("{prefix}{name}")))) .collect() } @@ -526,17 +498,25 @@ fn mock_reference_help(mock_name: &str, call: &str, reference: &Reference) -> St format!("Write the rows of '{mock_name}' directly, for example {mock_name} AS (SELECT ...).") } -/// Python's `sql_test_cte_location` and `reference_call_location` on ASCII contents. +/// Python's `sql_test_cte_location` and `reference_call_location`, in code points. fn located(test: &SqlTestAssemblyTest, cte_name: &str, call: &str) -> Span { - let contents = test.contents.as_str(); - let block_offset = contents.find(test.block_sql.as_str()).unwrap_or(0); - let (start, length) = match cte_header(contents, cte_name, block_offset) { - Some((header_start, header_end)) => find_ignoring_case(contents, call, header_end) - .map_or((header_start, cte_name.len()), |found| (found, call.len())), + let python: PythonText = active_python_text(); + let contents: Vec = test.contents.chars().collect(); + let block_offset: usize = test + .contents + .find(test.block_sql.as_str()) + .map_or(0, |byte| test.contents[..byte].chars().count()); + let name: Vec = cte_name.chars().collect(); + let call: Vec = call.chars().collect(); + let (start, length) = match cte_header(python, &contents, &name, block_offset) { + Some((header_start, header_end)) => { + find_ignoring_case(python, &contents, &call, header_end) + .map_or((header_start, name.len()), |found| (found, call.len())) + } None => (block_offset, 0), }; - let (line, column) = line_and_column(contents, start); - let (end_line, end_column) = line_and_column(contents, start + length); + let (line, column) = line_and_column(&contents, start); + let (end_line, end_column) = line_and_column(&contents, start + length); Span { line, column, @@ -545,75 +525,95 @@ fn located(test: &SqlTestAssemblyTest, cte_name: &str, call: &str) -> Span { } } -/// Python's `(? Option<(usize, usize)> { - let bytes = contents.as_bytes(); +/// Python's `(? Option<(usize, usize)> { + let space = |index: usize| contents.get(index).is_some_and(|c| is_python_space(*c)); let mut start = from; - while let Some(found) = find_ignoring_case(contents, name, start) { + while let Some(found) = find_ignoring_case(python, contents, name, start) { start = found + 1; - if found > 0 && is_word_or_dollar(bytes[found - 1]) { + if found > 0 && is_word_or_dollar(python, contents[found - 1]) { continue; } let mut cursor = found + name.len(); - if matches!(bytes.get(cursor), Some(b'"' | b'`')) { + if matches!(contents.get(cursor), Some('"' | '`')) { cursor += 1; } let spaces = cursor; - while bytes - .get(cursor) - .is_some_and(|byte| is_python_ascii_space(*byte)) - { + while space(cursor) { cursor += 1; } - if cursor == spaces - || !bytes - .get(cursor..cursor + 2) - .is_some_and(|keyword| keyword.eq_ignore_ascii_case(b"AS")) - { + if cursor == spaces || !matches_ignoring_case(python, contents, &['a', 's'], cursor) { continue; } cursor += 2; - while bytes - .get(cursor) - .is_some_and(|byte| is_python_ascii_space(*byte)) - { + while space(cursor) { cursor += 1; } - if bytes.get(cursor) == Some(&b'(') { + if contents.get(cursor) == Some(&'(') { return Some((found, cursor + 1)); } } None } -fn find_ignoring_case(contents: &str, needle: &str, from: usize) -> Option { - let haystack = contents.as_bytes(); - let needle = needle.as_bytes(); - if needle.is_empty() { - return (from <= haystack.len()).then_some(from); - } - (from..=haystack.len().checked_sub(needle.len())?) - .find(|&index| haystack[index..index + needle.len()].eq_ignore_ascii_case(needle)) +/// Python's `re.compile(re.escape(needle), re.IGNORECASE).search(contents, from)`. +fn find_ignoring_case( + python: PythonText, + contents: &[char], + needle: &[char], + from: usize, +) -> Option { + let needle: Vec = needle + .iter() + .map(|character| python_ignorecase_key(python, *character)) + .collect(); + (from..=contents.len().checked_sub(needle.len())?) + .find(|&index| keys_at(python, contents, &needle, index)) +} + +/// Whether `needle` matches at `at` under `re.IGNORECASE`. +fn matches_ignoring_case( + python: PythonText, + contents: &[char], + needle: &[char], + at: usize, +) -> bool { + let keys: Vec = needle + .iter() + .map(|character| python_ignorecase_key(python, *character)) + .collect(); + keys_at(python, contents, &keys, at) } -fn is_word_or_dollar(byte: u8) -> bool { - byte.is_ascii_alphanumeric() || matches!(byte, b'_' | b'$') +fn keys_at(python: PythonText, contents: &[char], keys: &[char], at: usize) -> bool { + contents.get(at..at + keys.len()).is_some_and(|window| { + window + .iter() + .zip(keys) + .all(|(character, key)| python_ignorecase_key(python, *character) == *key) + }) } -/// Python's `\s` on ASCII text, which includes the information separators. -fn is_python_ascii_space(byte: u8) -> bool { - matches!( - byte, - b' ' | b'\t' | b'\n' | b'\r' | 0x0b | 0x0c | 0x1c..=0x1f - ) +/// Python's `[\w$]`. +fn is_word_or_dollar(python: PythonText, character: char) -> bool { + character == '$' || is_python_word(python, character) } -fn line_and_column(contents: &str, offset: usize) -> (usize, usize) { - let before = &contents.as_bytes()[..offset]; - let line = before.iter().filter(|byte| **byte == b'\n').count() + 1; +fn line_and_column(contents: &[char], offset: usize) -> (usize, usize) { + let before = &contents[..offset]; + let line = before + .iter() + .filter(|character| **character == '\n') + .count() + + 1; let line_start = before .iter() - .rposition(|byte| *byte == b'\n') + .rposition(|character| *character == '\n') .map_or(0, |index| index + 1); (line, offset - line_start + 1) } diff --git a/crates/sqlbuild-analysis/src/compiler/_helpers/sql_tests/planning.rs b/crates/sqlbuild-analysis/src/compiler/_helpers/sql_tests/planning.rs index e879c9da90..dd807f1445 100644 --- a/crates/sqlbuild-analysis/src/compiler/_helpers/sql_tests/planning.rs +++ b/crates/sqlbuild-analysis/src/compiler/_helpers/sql_tests/planning.rs @@ -7,6 +7,7 @@ use std::time::Instant; use polyglot_sql::{Dialect, Expression}; use rayon::iter::{IntoParallelIterator, ParallelIterator}; use regex::Regex; +#[cfg(test)] use serde::Serialize; use crate::compiler::_helpers::sql_tests::cte_rename::defined_cte_keys; @@ -65,6 +66,7 @@ pub(crate) const DBT_REF_FUNCTION: &str = "__dbt_ref"; const UDF_FUNCTION: &str = "__udf"; const TABLE_FUNCTION: &str = "__table_fn"; +#[cfg(test)] #[derive(Debug, Serialize)] #[serde(rename_all = "camelCase")] struct ChainBatchResponse { @@ -426,6 +428,7 @@ impl GeneratedCteState { } /// Return each test's topologically ordered unmocked model chain without planning SQL. +#[cfg(test)] pub(crate) fn resolve_chains_json(request_json: &str) -> Result { let request: SqlTestChainBatch = serde_json::from_str(request_json).map_err(|error| error.to_string())?; @@ -496,6 +499,7 @@ fn chain_root_names( dedupe(expected_names) } +#[cfg(test)] pub(crate) fn plan_and_render_json(request_json: &str) -> Result { let request: SqlTestPlanBatch = serde_json::from_str(request_json).map_err(|error| error.to_string())?; diff --git a/crates/sqlbuild-analysis/src/compiler/main/mod.rs b/crates/sqlbuild-analysis/src/compiler/main/mod.rs index bb4c16b14f..8f17d7b413 100644 --- a/crates/sqlbuild-analysis/src/compiler/main/mod.rs +++ b/crates/sqlbuild-analysis/src/compiler/main/mod.rs @@ -1,12 +1,10 @@ pub mod function_type_validation; pub mod sql_scenario_extraction; pub mod sql_test_assembly; -pub mod sql_test_chain_resolution; pub mod sql_test_chains; pub mod sql_test_difference_sampling; pub mod sql_test_extraction; pub mod sql_test_fixture_facts; pub mod sql_test_glue; pub mod sql_test_plan_errors; -pub mod sql_test_planning; pub mod sql_test_rendering; diff --git a/crates/sqlbuild-analysis/src/compiler/main/sql_test_chain_resolution.rs b/crates/sqlbuild-analysis/src/compiler/main/sql_test_chain_resolution.rs deleted file mode 100644 index 74ae93cc0d..0000000000 --- a/crates/sqlbuild-analysis/src/compiler/main/sql_test_chain_resolution.rs +++ /dev/null @@ -1,5 +0,0 @@ -use crate::compiler::_helpers; - -pub fn resolve_chains_json(request_json: &str) -> Result { - _helpers::sql_tests::planning::resolve_chains_json(request_json) -} diff --git a/crates/sqlbuild-analysis/src/compiler/main/sql_test_planning.rs b/crates/sqlbuild-analysis/src/compiler/main/sql_test_planning.rs deleted file mode 100644 index d5057b8241..0000000000 --- a/crates/sqlbuild-analysis/src/compiler/main/sql_test_planning.rs +++ /dev/null @@ -1,5 +0,0 @@ -use crate::compiler::_helpers; - -pub fn plan_and_render_json(request_json: &str) -> Result { - _helpers::sql_tests::planning::plan_and_render_json(request_json) -} diff --git a/crates/sqlbuild-analysis/src/compiler/models.rs b/crates/sqlbuild-analysis/src/compiler/models.rs index ca6719b481..457dd969a1 100644 --- a/crates/sqlbuild-analysis/src/compiler/models.rs +++ b/crates/sqlbuild-analysis/src/compiler/models.rs @@ -265,14 +265,15 @@ pub struct SqlTestAssemblyModelPayload { pub assertion_target_model_names: Vec, pub reference_target_model_names: Vec, pub mock_model_names: Vec, - pub has_macro_mocks: bool, } -/// One test's assembled facts, or why Python assembles it. +/// One test's assembled facts, or why its assembly raises. #[derive(Debug, PartialEq)] pub enum SqlTestAssemblyOutcome { Assembled(AssembledSqlTestFacts), - Deferred(SqlTestAssemblyDeferral), + /// Python's decimal context overflows normalizing a case parameter. + FingerprintOverflow(AssembledSqlTestFacts), + Failed(SqlTestAssemblyFailure), } /// The facts Python's `_assemble_compiled_sql_test` computes for one test. @@ -299,36 +300,11 @@ pub struct SqlTestHelperDiagnostic { pub help: String, } -/// Why one test is assembled by Python instead. -#[derive(Clone, Copy, Debug, PartialEq, Eq)] -pub enum SqlTestAssemblyDeferral { - /// Macro mocks re-expand every model, which only Python's macro expansion does. - MacroMocks, - /// A model's macro call scan raises in Python or meets text Python classifies by Unicode. - MacroCallScan, - /// The reference scan fails or cannot classify the text as Python does. - ReferenceScan, - /// Non-ASCII text where Python's case folding or Unicode classes would apply. - NonAsciiText, - /// A decimal parameter Python's decimal context would round or clamp. - DecimalContext, - /// A parameter value the JSON encoder cannot encode as Python's does. - UnencodableValue, - /// A parsed CTE tree too deep, or otherwise unfit, to read as Python's `to_dict` walk does. - UnreadableTree, -} - -impl SqlTestAssemblyDeferral { - /// The kind recorded for the deferral. - pub fn as_str(self) -> &'static str { - match self { - Self::MacroMocks => "macro_mocks", - Self::MacroCallScan => "macro_call_scan", - Self::ReferenceScan => "reference_scan", - Self::NonAsciiText => "non_ascii_text", - Self::DecimalContext => "decimal_context", - Self::UnencodableValue => "unencodable_value", - Self::UnreadableTree => "unreadable_tree", - } - } +/// Why one test's assembly raises, as Python's assembly would. +#[derive(Clone, Debug, PartialEq, Eq)] +pub enum SqlTestAssemblyFailure { + /// The message of the `CompileInputError` Python raises before the test's macro-mock queries. + Input(String), + /// An internal native failure. + Internal(String), } diff --git a/crates/sqlbuild-analysis/src/compiler/tests/helpers.rs b/crates/sqlbuild-analysis/src/compiler/tests/helpers.rs index b53085d4bd..99ffa40a63 100644 --- a/crates/sqlbuild-analysis/src/compiler/tests/helpers.rs +++ b/crates/sqlbuild-analysis/src/compiler/tests/helpers.rs @@ -1864,7 +1864,7 @@ pub(crate) fn plan_helper_reference_response( case: &HelperReferenceTestCase, sends_compiler_reads: bool, ) -> Result { - crate::compiler::main::sql_test_planning::plan_and_render_json( + crate::compiler::_helpers::sql_tests::planning::plan_and_render_json( &json!({ "lexicalSyntax": generic_lexical_syntax(), "models": helper_reference_models(), @@ -1889,7 +1889,7 @@ pub(crate) fn plan_helper_reference_case(case: &HelperReferenceTestCase) -> Valu /// Resolve one helper-reference case's model chain without planning SQL. pub(crate) fn chain_helper_reference_case(case: &HelperReferenceTestCase) -> Value { let response: Value = serde_json::from_str( - &crate::compiler::main::sql_test_chain_resolution::resolve_chains_json( + &crate::compiler::_helpers::sql_tests::planning::resolve_chains_json( &json!({ "lexicalSyntax": generic_lexical_syntax(), "models": helper_reference_models(), @@ -1910,16 +1910,16 @@ pub(crate) fn defined_before(sql: &str, first: &str, second: &str) -> bool { /// Plan a request whose model tests predate the compiler's reads, sending empty reads for them. pub(crate) fn plan_json(request_json: &str) -> Result { - crate::compiler::main::sql_test_planning::plan_and_render_json(&with_empty_compiler_reads( - request_json, - )) + crate::compiler::_helpers::sql_tests::planning::plan_and_render_json( + &with_empty_compiler_reads(request_json), + ) } /// Resolve chains for a request whose model tests predate the compiler's reads. pub(crate) fn chain_json(request_json: &str) -> Result { - crate::compiler::main::sql_test_chain_resolution::resolve_chains_json( - &with_empty_compiler_reads(request_json), - ) + crate::compiler::_helpers::sql_tests::planning::resolve_chains_json(&with_empty_compiler_reads( + request_json, + )) } fn with_empty_compiler_reads(request_json: &str) -> String { diff --git a/crates/sqlbuild-analysis/src/compiler/tests/test_sql_test_helper_references.rs b/crates/sqlbuild-analysis/src/compiler/tests/test_sql_test_helper_references.rs index 05d1594a41..e2d0a816ce 100644 --- a/crates/sqlbuild-analysis/src/compiler/tests/test_sql_test_helper_references.rs +++ b/crates/sqlbuild-analysis/src/compiler/tests/test_sql_test_helper_references.rs @@ -3,10 +3,9 @@ use serde_json::{Value, json}; use crate::compiler::_helpers::sql_tests::extraction::generic_syntax; use crate::compiler::main::sql_test_assembly::assemble_sql_test_batch; use crate::compiler::models::{ - AssembledSqlTestFacts, SqlTestAssemblyBatch, SqlTestAssemblyDeferral, SqlTestAssemblyModel, - SqlTestAssemblyModelPayload, SqlTestAssemblyOutcome, SqlTestAssemblyPayload, - SqlTestAssemblyReference, SqlTestAssemblyTest, SqlTestCte, SqlTestHelperDiagnostic, - SqlTestParameterValue, + AssembledSqlTestFacts, SqlTestAssemblyBatch, SqlTestAssemblyModel, SqlTestAssemblyModelPayload, + SqlTestAssemblyOutcome, SqlTestAssemblyPayload, SqlTestAssemblyReference, SqlTestAssemblyTest, + SqlTestCte, SqlTestHelperDiagnostic, SqlTestParameterValue, }; use crate::compiler::tests::helpers::{ chain_helper_reference_case, defined_before, plan_helper_reference_case, @@ -45,6 +44,12 @@ __expected__customer_totals AS (SELECT 1 AS customer_id)\nSELECT 1\n"; /// Python's `build_sql_test_case_fingerprint` of the parameterized case below. const PYTHON_CASE_FINGERPRINT: &str = "8f2adcab557ba4476fcb70de1fc11014acda9f1b597a3ca5c3245afb632e5d0f"; +/// Python's fingerprint of the case with 29 ones, which its decimal context rounds to 28 digits. +const PYTHON_ROUNDED_CASE_FINGERPRINT: &str = + "58f918fcd3fa8df50c2b10a9e8671c1f3b49eb80af3d48b7eb609392e255ccb4"; +/// Python's fingerprint of the case with 29 nines, whose rounding carries into a new digit. +const PYTHON_CARRIED_CASE_FINGERPRINT: &str = + "6da8c843ce65781616436ca7665394b9495efc3881955fbe3b58be610e3faa7a"; #[test] fn given_helper_cte_references_when_planning_then_references_resolve_in_dependency_order() { @@ -509,14 +514,14 @@ fn given_unresolvable_reader_references_when_planning_directly_then_planner_reje } #[test] -fn given_compiled_sql_test_inputs_when_assembling_then_facts_match_python_or_defer() { +fn given_compiled_sql_test_inputs_when_assembling_then_facts_match_python() { let cte = |name: &str, sql_body: &str| SqlTestCte { name: name.to_owned(), sql_body: sql_body.to_owned(), }; let strings = |names: &[&str]| -> Vec { names.iter().map(|n| (*n).to_owned()).collect() }; - let model_test = |contents: &str, has_macro_mocks: bool| SqlTestAssemblyTest { + let model_test = |contents: &str| SqlTestAssemblyTest { block_name: Some("mock_reads_helper".to_owned()), file_stem: "test_customer_totals".to_owned(), relative_path: "tests/unit/test_customer_totals.sql".to_owned(), @@ -545,7 +550,6 @@ fn given_compiled_sql_test_inputs_when_assembling_then_facts_match_python_or_def assertion_target_model_names: Vec::new(), reference_target_model_names: Vec::new(), mock_model_names: strings(&["stg_orders"]), - has_macro_mocks, }), }; let model = |name: &str, macro_deps: &[&str], source: Option<&str>, refs: &[(&str, &str)]| { @@ -592,7 +596,7 @@ fn given_compiled_sql_test_inputs_when_assembling_then_facts_match_python_or_def mode: "macro".to_owned(), tested_resource_names: strings(&["dollars"]), }, - ..model_test(MOCK_READS_HELPER_TEST, false) + ..model_test(MOCK_READS_HELPER_TEST) }; let case_test = |decimal_digits: Vec| SqlTestAssemblyTest { relative_path: "tests/unit/test_cases.sql".to_owned(), @@ -624,14 +628,26 @@ fn given_compiled_sql_test_inputs_when_assembling_then_facts_match_python_or_def assertion_target_model_names: strings(&["orders"]), reference_target_model_names: Vec::new(), mock_model_names: Vec::new(), - has_macro_mocks: false, }), - ..model_test(MOCK_READS_HELPER_TEST, false) + ..model_test(MOCK_READS_HELPER_TEST) + }; + let rounded_case = |fingerprint: &str| { + SqlTestAssemblyOutcome::Assembled(AssembledSqlTestFacts { + name: "mock_reads_helper [first]".to_owned(), + scope_deps: vec![ + ("model", "orders".to_owned()), + ("model", "customers".to_owned()), + ], + target_model_names: strings(&["orders", "customers"]), + case_fingerprint: Some(fingerprint.to_owned()), + diagnostic_resource_name: "mock_reads_helper".to_owned(), + diagnostics: Vec::new(), + }) }; let test_cases = [ SqlTestAssemblyTestCase { description: "a mock reading a helper that calls a source reports P013 at the call", - batch: batch(vec![model_test(MOCK_READS_HELPER_TEST, false)]), + batch: batch(vec![model_test(MOCK_READS_HELPER_TEST)]), expected_outcomes: vec![SqlTestAssemblyOutcome::Assembled(AssembledSqlTestFacts { name: "mock_reads_helper".to_owned(), scope_deps: vec![("model", "customer_totals".to_owned())], @@ -657,16 +673,38 @@ fn given_compiled_sql_test_inputs_when_assembling_then_facts_match_python_or_def })], }, SqlTestAssemblyTestCase { - description: "macro mocks, non-ASCII text and out-of-context decimals defer", + description: "non-ASCII contents and decimals Python's context rounds assemble as Python", batch: batch(vec![ - model_test(MOCK_READS_HELPER_TEST, true), - model_test(&format!("-- caf\u{e9}\n{MOCK_READS_HELPER_TEST}"), false), + model_test(&format!("-- caf\u{e9}\n{MOCK_READS_HELPER_TEST}")), case_test(vec![1; 29]), + case_test(vec![9; 29]), ]), expected_outcomes: vec![ - SqlTestAssemblyOutcome::Deferred(SqlTestAssemblyDeferral::MacroMocks), - SqlTestAssemblyOutcome::Deferred(SqlTestAssemblyDeferral::NonAsciiText), - SqlTestAssemblyOutcome::Deferred(SqlTestAssemblyDeferral::DecimalContext), + SqlTestAssemblyOutcome::Assembled(AssembledSqlTestFacts { + name: "mock_reads_helper".to_owned(), + scope_deps: vec![("model", "customer_totals".to_owned())], + target_model_names: strings(&["customer_totals"]), + case_fingerprint: None, + diagnostic_resource_name: "mock_reads_helper".to_owned(), + diagnostics: vec![SqlTestHelperDiagnostic { + line: 5, + column: 31, + end_line: 5, + end_column: 53, + message: "SQL test mock '__ref__stg_orders' reads helper CTE \ + 'orders_feed', which calls __source(\"raw_orders\"); mocks \ + and fixtures are defined before the models the test runs, so \ + the helper cannot be resolved for them" + .to_owned(), + help: "Read a mock by its CTE name instead, for example FROM \ + __source__raw_orders rather than FROM __source(\"raw_orders\"), \ + defining __source__raw_orders AS (SELECT ...) if the test does \ + not mock it, or write the rows of '__ref__stg_orders' directly." + .to_owned(), + }], + }), + rounded_case(PYTHON_ROUNDED_CASE_FINGERPRINT), + rounded_case(PYTHON_CARRIED_CASE_FINGERPRINT), ], }, SqlTestAssemblyTestCase { diff --git a/crates/sqlbuild-analysis/src/compiler/tests/test_sql_test_planning.rs b/crates/sqlbuild-analysis/src/compiler/tests/test_sql_test_planning.rs index a54b22b9de..f7e25c954a 100644 --- a/crates/sqlbuild-analysis/src/compiler/tests/test_sql_test_planning.rs +++ b/crates/sqlbuild-analysis/src/compiler/tests/test_sql_test_planning.rs @@ -1,10 +1,10 @@ use serde_json::{Value, json}; -use crate::compiler::main::sql_test_chain_resolution::resolve_chains_json; +use crate::compiler::_helpers::sql_tests::planning::plan_and_render_json; +use crate::compiler::_helpers::sql_tests::planning::resolve_chains_json; use crate::compiler::main::sql_test_chains::resolve_sql_test_chains; use crate::compiler::main::sql_test_glue::plan_sql_test_batch; use crate::compiler::main::sql_test_plan_errors::sql_test_plan_error_messages; -use crate::compiler::main::sql_test_planning::plan_and_render_json; use crate::compiler::models::{SqlTestPlan, SqlTestPlanWarning}; use crate::compiler::tests::helpers::{ chain_resolution_orders_unmocked_models, concurrent_requests_initialize_shared_template_once, diff --git a/crates/sqlbuild-analysis/src/contracts/_helpers/columns.rs b/crates/sqlbuild-analysis/src/contracts/_helpers/columns.rs index 20922fe52b..eacc966c75 100644 --- a/crates/sqlbuild-analysis/src/contracts/_helpers/columns.rs +++ b/crates/sqlbuild-analysis/src/contracts/_helpers/columns.rs @@ -13,9 +13,10 @@ use crate::contracts::constants::{ UNPROVEN_TYPE_OUTPUT_MESSAGE, }; use crate::contracts::models::{ - ContractDeferral, ContractDiagnostic, ContractLocation, ContractModel, ContractSchema, - ContractSeverity, DeclaredColumn, InferredOutputColumn, RelatedOutput, + ContractDiagnostic, ContractLocation, ContractModel, ContractSchema, ContractSeverity, + DeclaredColumn, InferredOutputColumn, RelatedOutput, }; +use crate::type_system::errors::TypeNormalizationError; /// Python's `_requires_contract_evaluation`. pub(crate) fn requires_contract_evaluation(model: &ContractModel, implicit: bool) -> bool { @@ -46,7 +47,7 @@ pub(crate) fn model_contract_diagnostics( model: &ContractModel, validate_declared_shape: bool, types: &TypeComparer<'_>, -) -> Result, ContractDeferral> { +) -> Result, TypeNormalizationError> { let contract_enforced: bool = model.contract.as_deref() == Some(CONTRACT_ENFORCED); let Some(schema) = model .schema @@ -249,7 +250,7 @@ fn missing_column( fn column_type( column: &TypedColumn<'_>, check: &TypeCheck<'_>, -) -> Result, ContractDeferral> { +) -> Result, TypeNormalizationError> { let name: &str = &column.declared.name; let declared_type: &str = column.declared_type; let Some(inferred_type) = column.inferred.inferred_type.as_deref() else { diff --git a/crates/sqlbuild-analysis/src/contracts/_helpers/dynamic.rs b/crates/sqlbuild-analysis/src/contracts/_helpers/dynamic.rs index 058b485381..9c98d44453 100644 --- a/crates/sqlbuild-analysis/src/contracts/_helpers/dynamic.rs +++ b/crates/sqlbuild-analysis/src/contracts/_helpers/dynamic.rs @@ -2,6 +2,9 @@ use std::collections::HashMap; +use sqlbuild_core::text::main::active_python_text::active_python_text; +use sqlbuild_core::text::main::python_casefold::python_casefold; + use crate::contracts::_helpers::type_comparison::{TypeComparer, TypeComparison}; use crate::contracts::constants::{ DYNAMIC_FAMILY_TYPE_MISMATCH_HELP, DYNAMIC_FAMILY_UNKNOWN_TYPE_HELP, @@ -9,15 +12,15 @@ use crate::contracts::constants::{ TYPE_MISMATCH_CODE, UNKNOWN_TYPE_CODE, }; use crate::contracts::models::{ - ContractDeferral, ContractDiagnostic, ContractLocation, ContractModel, ContractSeverity, - DynamicContractProof, + ContractDiagnostic, ContractLocation, ContractModel, ContractSeverity, DynamicContractProof, }; +use crate::type_system::errors::TypeNormalizationError; /// The dynamic column contract diagnostics of one model, before its fixed columns. pub(crate) fn dynamic_column_diagnostics( model: &ContractModel, types: &TypeComparer<'_>, -) -> Result, ContractDeferral> { +) -> Result, TypeNormalizationError> { let Some(schema) = model .schema .as_ref() @@ -35,7 +38,7 @@ pub(crate) fn dynamic_column_diagnostics( let proof_by_name: HashMap> = families_by_casefold(proof)?; let mut diagnostics: Vec = Vec::new(); for family in &schema.dynamic_columns { - let key: String = casefold(&family.name)?; + let key: String = casefold(&family.name); let declared: &str = &family.declared_type; let Some(inferred) = proof_by_name.get(&key).copied().flatten() else { diagnostics.push(family_diagnostic( @@ -87,21 +90,17 @@ fn not_proven(model: &ContractModel) -> ContractDiagnostic { fn families_by_casefold( proof: &DynamicContractProof, -) -> Result>, ContractDeferral> { +) -> Result>, TypeNormalizationError> { let mut by_name: HashMap> = HashMap::new(); for (name, inferred_type) in &proof.families { - let _ = by_name.insert(casefold(name)?, inferred_type.as_deref()); + let _ = by_name.insert(casefold(name), inferred_type.as_deref()); } Ok(by_name) } -/// Python's `str.casefold` for ASCII names; other names defer. -fn casefold(name: &str) -> Result { - if name.is_ascii() { - Ok(name.to_ascii_lowercase()) - } else { - Err(ContractDeferral::NonAsciiFamilyName) - } +/// Python's `str.casefold`. +fn casefold(name: &str) -> String { + python_casefold(active_python_text(), name) } fn family_diagnostic( diff --git a/crates/sqlbuild-analysis/src/contracts/_helpers/type_comparison.rs b/crates/sqlbuild-analysis/src/contracts/_helpers/type_comparison.rs index 13bb94ae69..a922a1dc2a 100644 --- a/crates/sqlbuild-analysis/src/contracts/_helpers/type_comparison.rs +++ b/crates/sqlbuild-analysis/src/contracts/_helpers/type_comparison.rs @@ -1,9 +1,9 @@ -//! Python's `types_equal` over the native type system, deferring where it cannot answer. +//! Python's `types_equal` over the native type system. use std::cell::RefCell; use std::collections::HashMap; -use crate::contracts::models::ContractDeferral; +use crate::type_system::errors::TypeNormalizationError; use crate::type_system::main::normalize_type::normalize_type; use crate::type_system::models::{NormalizedType, TypeNormalization}; @@ -17,7 +17,7 @@ pub(crate) enum TypeComparison { /// One request's type comparisons, normalizing each type string once as Python's cache does. pub(crate) struct TypeComparer<'a> { dialect: &'a str, - normalized: RefCell>>, + normalized: RefCell>>, } impl<'a> TypeComparer<'a> { @@ -28,12 +28,12 @@ impl<'a> TypeComparer<'a> { } } - /// Compare two types as Python's `types_equal`, or defer when either has no native answer. + /// Compare two types as Python's `types_equal`, or Python's normalization error. pub(crate) fn types_equal( &self, left: &str, right: &str, - ) -> Result { + ) -> Result { let left: NormalizedType = self.normalized(left)?; let right: NormalizedType = self.normalized(right)?; Ok(if left == right { @@ -43,15 +43,16 @@ impl<'a> TypeComparer<'a> { }) } - fn normalized(&self, type_sql: &str) -> Result { + fn normalized(&self, type_sql: &str) -> Result { if let Some(known) = self.normalized.borrow().get(type_sql) { - return known.clone().ok_or(ContractDeferral::TypeNormalization); + return known.clone(); } - let normalized: Option = normalize_type(type_sql, self.dialect) - .map(|TypeNormalization { normalized, .. }| normalized); + let normalized: Result = + normalize_type(type_sql, self.dialect) + .map(|TypeNormalization { normalized, .. }| normalized); self.normalized .borrow_mut() .insert(type_sql.to_owned(), normalized.clone()); - normalized.ok_or(ContractDeferral::TypeNormalization) + normalized } } diff --git a/crates/sqlbuild-analysis/src/contracts/main/evaluate_model_contracts.rs b/crates/sqlbuild-analysis/src/contracts/main/evaluate_model_contracts.rs index a1fa939fbf..a26e11545a 100644 --- a/crates/sqlbuild-analysis/src/contracts/main/evaluate_model_contracts.rs +++ b/crates/sqlbuild-analysis/src/contracts/main/evaluate_model_contracts.rs @@ -4,11 +4,13 @@ use crate::contracts::_helpers::columns::{ declared_shape_validation_is_active, model_contract_diagnostics, requires_contract_evaluation, }; use crate::contracts::_helpers::type_comparison::TypeComparer; -use crate::contracts::models::{ContractOutcome, ContractRequest}; +use crate::contracts::models::{ContractDiagnostic, ContractRequest}; +use crate::type_system::errors::TypeNormalizationError; -/// One outcome per requested model; models that need no evaluation have no diagnostics. -#[must_use] -pub fn evaluate_model_contracts(request: &ContractRequest) -> Vec { +/// Each requested model's diagnostics; models that need no evaluation have none. +pub fn evaluate_model_contracts( + request: &ContractRequest, +) -> Result>, TypeNormalizationError> { let implicit: bool = request.implicit_column_contracts; let types = TypeComparer::new(&request.dialect); request @@ -16,16 +18,13 @@ pub fn evaluate_model_contracts(request: &ContractRequest) -> Vec ContractOutcome::Diagnostics(diagnostics), - Err(deferral) => ContractOutcome::Deferred(deferral), - } + ) }) .collect() } diff --git a/crates/sqlbuild-analysis/src/contracts/models.rs b/crates/sqlbuild-analysis/src/contracts/models.rs index 131649c921..656f80975a 100644 --- a/crates/sqlbuild-analysis/src/contracts/models.rs +++ b/crates/sqlbuild-analysis/src/contracts/models.rs @@ -130,44 +130,6 @@ pub struct ContractDiagnostic { pub help: String, } -/// Why native contract validation hands one model back to Python. -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -pub enum ContractDeferral { - /// Native type normalization cannot reproduce Python for a compared type. - TypeNormalization, - /// A dynamic family name outside ASCII, whose `casefold` native does not reproduce. - NonAsciiFamilyName, -} - -impl ContractDeferral { - /// The deferral kind recorded for the harness. - #[must_use] - pub fn as_str(self) -> &'static str { - match self { - Self::TypeNormalization => "type_normalization", - Self::NonAsciiFamilyName => "non_ascii_family_name", - } - } -} - -/// One model's contract outcome. -#[derive(Debug, Clone, PartialEq, Eq)] -pub enum ContractOutcome { - Diagnostics(Vec), - Deferred(ContractDeferral), -} - -impl ContractOutcome { - /// `(deferral, diagnostics)`: a deferred model has no diagnostics. - #[must_use] - pub fn into_parts(self) -> (Option, Vec) { - match self { - Self::Diagnostics(diagnostics) => (None, diagnostics), - Self::Deferred(deferral) => (Some(deferral), Vec::new()), - } - } -} - /// The inputs to table promotion conflict detection. #[derive(Debug, Clone, PartialEq, Eq)] pub struct PromotionRequest { diff --git a/crates/sqlbuild-analysis/src/contracts/tests/helpers.rs b/crates/sqlbuild-analysis/src/contracts/tests/helpers.rs index 542f3a7d64..e573e13ec7 100644 --- a/crates/sqlbuild-analysis/src/contracts/tests/helpers.rs +++ b/crates/sqlbuild-analysis/src/contracts/tests/helpers.rs @@ -1,7 +1,6 @@ use crate::contracts::models::{ - ContractDiagnostic, ContractModel, ContractOutcome, ContractSchema, DeclaredColumn, - DeclaredColumnFamily, DynamicContractProof, InferredOutputColumn, PromotionModel, - PromotionRequest, + ContractDiagnostic, ContractModel, ContractSchema, DeclaredColumn, DeclaredColumnFamily, + DynamicContractProof, InferredOutputColumn, PromotionModel, PromotionRequest, }; pub(crate) fn model(contract: Option<&str>, schema: Option) -> ContractModel { @@ -99,12 +98,8 @@ pub(crate) fn promotion_model( } } -pub(crate) fn outcome_lines(outcome: &ContractOutcome) -> Vec { - let (deferral, diagnostics) = outcome.clone().into_parts(); - deferral.map_or_else( - || diagnostics.iter().map(diagnostic_line).collect(), - |deferral| vec![format!("deferred:{}", deferral.as_str())], - ) +pub(crate) fn outcome_lines(diagnostics: &[ContractDiagnostic]) -> Vec { + diagnostics.iter().map(diagnostic_line).collect() } fn diagnostic_line(diagnostic: &ContractDiagnostic) -> String { diff --git a/crates/sqlbuild-analysis/src/contracts/tests/test_evaluate_model_contracts.rs b/crates/sqlbuild-analysis/src/contracts/tests/test_evaluate_model_contracts.rs index 2b3883d3e1..d6eb7f0e35 100644 --- a/crates/sqlbuild-analysis/src/contracts/tests/test_evaluate_model_contracts.rs +++ b/crates/sqlbuild-analysis/src/contracts/tests/test_evaluate_model_contracts.rs @@ -1,9 +1,11 @@ use crate::contracts::main::evaluate_model_contracts::evaluate_model_contracts; -use crate::contracts::models::{ContractModel, ContractOutcome, ContractRequest}; +use crate::contracts::models::{ContractDiagnostic, ContractModel, ContractRequest}; use crate::contracts::tests::helpers::{ declared, dynamic_model, inferred, model, outcome_lines, proof, schema, with_inferred, }; -use crate::contracts::tests::test_types::{ContractTestCase, SharedTypesTestCase}; +use crate::contracts::tests::test_types::{ + ContractTestCase, SharedTypesTestCase, UnknownDialectTestCase, +}; #[test] fn given_model_contracts_when_evaluating_then_diagnostics_follow_python_order() { @@ -132,7 +134,7 @@ fn given_model_contracts_when_evaluating_then_diagnostics_follow_python_order() expected_lines: &[], }, ContractTestCase { - description: "a type native normalization cannot answer defers the model", + description: "a non-ASCII type upper-cases with Python's Unicode mapping", implicit: true, model: with_inferred( model( @@ -141,7 +143,10 @@ fn given_model_contracts_when_evaluating_then_diagnostics_follow_python_order() ), vec![inferred("amount", Some("VARCHAR"), false)], ), - expected_lines: &["deferred:type_normalization"], + expected_lines: &[ + "K002 error declared:0 column 'amount' inferred as VARCHAR but declared type is \ + T\u{c9}XT [amount: inferred VARCHAR]", + ], }, ContractTestCase { description: "an unproven dynamic contract without a reason", @@ -186,13 +191,13 @@ fn given_model_contracts_when_evaluating_then_diagnostics_follow_python_order() ], }, ContractTestCase { - description: "a family name outside ASCII defers the model", + description: "a family name outside ASCII matches under Python's casefold", implicit: true, model: dynamic_model( &[("straße_*", "DOUBLE")], Some(proof(true, None, &[("strasse_*", Some("DOUBLE"))])), ), - expected_lines: &["deferred:non_ascii_family_name"], + expected_lines: &[], }, ]; for test_case in test_cases { @@ -201,9 +206,13 @@ fn given_model_contracts_when_evaluating_then_diagnostics_follow_python_order() implicit_column_contracts: test_case.implicit, models: vec![test_case.model], }; - let outcomes: Vec = evaluate_model_contracts(&request); + let outcomes: Vec> = + evaluate_model_contracts(&request).expect("duckdb types normalize"); assert_eq!( - outcomes.iter().flat_map(outcome_lines).collect::>(), + outcomes + .iter() + .flat_map(|diagnostics| outcome_lines(diagnostics)) + .collect::>(), test_case.expected_lines, "{}", test_case.description @@ -226,7 +235,7 @@ fn given_models_sharing_types_when_evaluating_together_then_each_matches_its_own ) }; let test_cases = [SharedTypesTestCase { - description: "repeated equal, mismatched and unanswerable types", + description: "repeated equal, mismatched and non-ASCII types", models: vec![ enforced("INT", "INTEGER"), enforced("INT", "VARCHAR"), @@ -237,9 +246,9 @@ fn given_models_sharing_types_when_evaluating_together_then_each_matches_its_own ], expected_lines: &[ "K002 error declared:0 column 'amount' inferred as VARCHAR but declared type is INT [amount: inferred VARCHAR]", - "deferred:type_normalization", + "K002 error declared:0 column 'amount' inferred as VARCHAR but declared type is T\u{c9}XT [amount: inferred VARCHAR]", "K002 error declared:0 column 'amount' inferred as VARCHAR but declared type is INT [amount: inferred VARCHAR]", - "deferred:type_normalization", + "K002 error declared:0 column 'amount' inferred as VARCHAR but declared type is T\u{c9}XT [amount: inferred VARCHAR]", ], }]; for test_case in test_cases { @@ -249,14 +258,18 @@ fn given_models_sharing_types_when_evaluating_together_then_each_matches_its_own models, }; let together: Vec = evaluate_model_contracts(&request(test_case.models.clone())) + .expect("duckdb types normalize") .iter() - .flat_map(outcome_lines) + .flat_map(|diagnostics| outcome_lines(diagnostics)) .collect(); let alone: Vec = test_case .models .iter() - .flat_map(|model| evaluate_model_contracts(&request(vec![model.clone()]))) - .flat_map(|outcome| outcome_lines(&outcome)) + .flat_map(|model| { + evaluate_model_contracts(&request(vec![model.clone()])) + .expect("duckdb types normalize") + }) + .flat_map(|diagnostics| outcome_lines(&diagnostics)) .collect(); assert_eq!(together, alone, "{}", test_case.description); @@ -267,3 +280,32 @@ fn given_models_sharing_types_when_evaluating_together_then_each_matches_its_own ); } } + +#[test] +fn given_a_dialect_polyglot_does_not_know_when_comparing_types_then_python_error_is_returned() { + let test_cases = [UnknownDialectTestCase { + description: "an enforced contract compared under an unknown dialect", + dialect: "motherduck", + expected_error: "Unknown dialect: motherduck", + }]; + for test_case in test_cases { + let request = ContractRequest { + dialect: test_case.dialect.to_owned(), + implicit_column_contracts: true, + models: vec![with_inferred( + model( + Some("enforced"), + Some(schema(vec![declared("amount", Some("INT"), false)], false)), + ), + vec![inferred("amount", Some("INTEGER"), false)], + )], + }; + + assert_eq!( + evaluate_model_contracts(&request).map_err(|error| error.message()), + Err(test_case.expected_error.to_owned()), + "{}", + test_case.description + ); + } +} diff --git a/crates/sqlbuild-analysis/src/contracts/tests/test_types.rs b/crates/sqlbuild-analysis/src/contracts/tests/test_types.rs index 43a0260eb6..13d7a49533 100644 --- a/crates/sqlbuild-analysis/src/contracts/tests/test_types.rs +++ b/crates/sqlbuild-analysis/src/contracts/tests/test_types.rs @@ -21,3 +21,9 @@ pub(crate) struct PromotionTestCase { pub(crate) expected_models: &'static [usize], pub(crate) expected_help: Option<&'static str>, } + +pub(crate) struct UnknownDialectTestCase { + pub(crate) description: &'static str, + pub(crate) dialect: &'static str, + pub(crate) expected_error: &'static str, +} diff --git a/crates/sqlbuild-analysis/src/explicit_references/_helpers/audit_gates.rs b/crates/sqlbuild-analysis/src/explicit_references/_helpers/audit_gates.rs new file mode 100644 index 0000000000..d2c4b0a0b0 --- /dev/null +++ b/crates/sqlbuild-analysis/src/explicit_references/_helpers/audit_gates.rs @@ -0,0 +1,188 @@ +//! Python's attached-audit gate edges and the P005 cycles they close. + +use std::collections::{HashMap, HashSet}; + +use crate::explicit_references::_helpers::graph::{Upstream, lineage_upstream, reaches}; +use crate::explicit_references::constants::{ + AUDIT_GATE_CODE, MODEL_TYPE, READABLE_TYPES, SEED_TYPE, SOURCE_TYPE, TABLE_FUNCTION_TYPE, + UDF_TYPE, +}; +use crate::explicit_references::models::{AuditGate, ReferenceDiagnostic, ReferenceRequest}; +use crate::explicit_references::types::ResourceKey; + +/// One ordering edge: `gated` waits for `read`, which an audit on `target` reads. +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub(crate) struct GateEdge { + pub(crate) gated: ResourceKey, + pub(crate) read: ResourceKey, +} + +/// An audit's target and the other resources it reads. +struct Gate<'a> { + target: &'a ResourceKey, + reads: Vec<&'a ResourceKey>, +} + +/// `attached_audit_gate_edges_impl`: edges to a fixed point, as sources gain triggering models. +pub(crate) fn gate_edges(request: &ReferenceRequest) -> Vec { + let mut triggers: HashMap> = HashMap::new(); + for resource in request + .resources + .iter() + .filter(|item| item.key.0 == MODEL_TYPE) + { + for dep in resource.deps.iter().filter(|dep| dep.0 == SOURCE_TYPE) { + triggers + .entry(dep.clone()) + .or_default() + .insert(resource.key.clone()); + } + } + let gates: Vec> = request.audits.iter().filter_map(gate).collect(); + let mut edges: Vec = Vec::new(); + let mut seen: HashSet = HashSet::new(); + let mut changed = true; + while changed { + changed = false; + for gate in &gates { + for edge in edges_of(gate, &triggers) { + if !seen.insert(edge.clone()) { + continue; + } + changed = true; + if edge.read.0 == SOURCE_TYPE && edge.gated.0 == MODEL_TYPE { + triggers + .entry(edge.read.clone()) + .or_default() + .insert(edge.gated.clone()); + } + edges.push(edge); + } + } + } + edges +} + +/// `attached_audit_gate_cycles_impl` as Python's P005 diagnostics, in its order. +pub(crate) fn gate_diagnostics( + request: &ReferenceRequest, + edges: &[GateEdge], +) -> Vec { + let mut upstream: Upstream = lineage_upstream(&request.resources); + for edge in edges { + upstream + .entry(edge.gated.clone()) + .or_default() + .push(edge.read.clone()); + } + let mut audits: Vec<&AuditGate> = request.audits.iter().collect(); + audits.sort_by(|left, right| left.name.cmp(&right.name)); + let mut cycles: Vec<(&AuditGate, &ResourceKey, &ResourceKey)> = Vec::new(); + for audit in audits { + let Some(target) = &audit.target else { + continue; + }; + for read in extra_reads(audit, target) { + let cycle = (audit, target, read); + if reaches(&upstream, read, target) + && !cycles + .iter() + .any(|(other, t, r)| other.name == audit.name && *t == target && *r == read) + { + cycles.push(cycle); + } + } + } + cycles.sort_by(|left, right| { + (&left.0.name, &left.1.1, &left.2.1).cmp(&(&right.0.name, &right.1.1, &right.2.1)) + }); + cycles + .into_iter() + .map(|(audit, target, read)| diagnostic(request, audit, target, read)) + .collect() +} + +fn gate(audit: &AuditGate) -> Option> { + let target = audit.target.as_ref()?; + let reads: Vec<&ResourceKey> = extra_reads(audit, target); + (!reads.is_empty()).then_some(Gate { target, reads }) +} + +fn extra_reads<'a>(audit: &'a AuditGate, target: &ResourceKey) -> Vec<&'a ResourceKey> { + audit + .scope_deps + .iter() + .filter(|read| *read != target && READABLE_TYPES.contains(&read.0.as_str())) + .collect() +} + +/// `_gate_edges`: a source target gates the models it triggers, sorted by name. +fn edges_of( + gate: &Gate<'_>, + triggers: &HashMap>, +) -> Vec { + let gated: Vec = if gate.target.0 == SOURCE_TYPE { + let mut keys: Vec = triggers + .get(gate.target) + .map(|keys| keys.iter().cloned().collect()) + .unwrap_or_default(); + keys.sort_by(|left, right| left.1.cmp(&right.1)); + keys + } else { + vec![gate.target.clone()] + }; + let mut edges: Vec = Vec::new(); + for read in &gate.reads { + for key in &gated { + edges.push(GateEdge { + gated: key.clone(), + read: (*read).clone(), + }); + } + } + edges +} + +fn diagnostic( + request: &ReferenceRequest, + audit: &AuditGate, + target: &ResourceKey, + read: &ResourceKey, +) -> ReferenceDiagnostic { + let path: Option = request + .audits + .iter() + .rev() + .find(|other| other.name == audit.name) + .map(|other| other.path.clone()); + ReferenceDiagnostic { + code: AUDIT_GATE_CODE, + message: format!( + "Audit '{}' on {} reads {}, which depends on '{}'; an attached audit gates its \ + target, so it cannot wait for a resource built from that target", + audit.name, + described(target), + described(read), + target.1 + ), + help: format!( + "write a singular audit under audits/singular/ that references both '{}' and '{}'; \ + it runs once both are built", + target.1, read.1 + ), + path, + owner: None, + line: None, + resource: Some(target.clone()), + } +} + +fn described(key: &ResourceKey) -> String { + let label: &str = match key.0.as_str() { + UDF_TYPE => "function", + TABLE_FUNCTION_TYPE => "table function", + MODEL_TYPE | SOURCE_TYPE | SEED_TYPE => key.0.as_str(), + other => other, + }; + format!("{label} '{}'", key.1) +} diff --git a/crates/sqlbuild-analysis/src/explicit_references/_helpers/graph.rs b/crates/sqlbuild-analysis/src/explicit_references/_helpers/graph.rs new file mode 100644 index 0000000000..337a3f0ade --- /dev/null +++ b/crates/sqlbuild-analysis/src/explicit_references/_helpers/graph.rs @@ -0,0 +1,47 @@ +//! Python's lineage upstream edges and transitive closure over compiled resource keys. + +use std::collections::{HashMap, HashSet, VecDeque}; + +use crate::explicit_references::constants::SQL_TEST_TYPE; +use crate::explicit_references::models::GraphResource; +use crate::explicit_references::types::ResourceKey; + +/// Upstream keys per resource key. +pub(crate) type Upstream = HashMap>; + +/// `build_lineage_upstream_deps_impl`: each resource's dependencies without SQL tests. +pub(crate) fn lineage_upstream(resources: &[GraphResource]) -> Upstream { + let mut upstream: Upstream = HashMap::new(); + for resource in resources { + if resource.key.0 == SQL_TEST_TYPE { + continue; + } + upstream.insert( + resource.key.clone(), + resource + .deps + .iter() + .filter(|dep| dep.0 != SQL_TEST_TYPE) + .cloned() + .collect(), + ); + } + upstream +} + +/// Whether `target` is reachable from `start` over at least one upstream edge. +pub(crate) fn reaches(upstream: &Upstream, start: &ResourceKey, target: &ResourceKey) -> bool { + let mut visited: HashSet<&ResourceKey> = HashSet::new(); + let mut frontier: VecDeque<&ResourceKey> = VecDeque::from([start]); + while let Some(current) = frontier.pop_front() { + for neighbor in upstream.get(current).into_iter().flatten() { + if visited.insert(neighbor) { + if neighbor == target { + return true; + } + frontier.push_back(neighbor); + } + } + } + false +} diff --git a/crates/sqlbuild-analysis/src/explicit_references/_helpers/hook_reads.rs b/crates/sqlbuild-analysis/src/explicit_references/_helpers/hook_reads.rs new file mode 100644 index 0000000000..a81fda7c77 --- /dev/null +++ b/crates/sqlbuild-analysis/src/explicit_references/_helpers/hook_reads.rs @@ -0,0 +1,173 @@ +//! Python's hook-read validation: unknown reads raise, reads of a hook's own dependant are P007. + +use std::collections::HashSet; + +use crate::explicit_references::_helpers::audit_gates::GateEdge; +use crate::explicit_references::_helpers::graph::{Upstream, lineage_upstream, reaches}; +use crate::explicit_references::constants::{ + HOOK_READ_CODE, MODEL_TYPE, PYTHON_DESTINATION, SEED_TYPE, SOURCE_TYPE, SQL_DESTINATION, +}; +use crate::explicit_references::models::{PythonHook, ReferenceDiagnostic, ReferenceRequest}; +use crate::explicit_references::types::ResourceKey; + +/// How diagnostics name a hook. +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +enum HookType { + Python, + Sql, + InlineSql, +} + +/// One ordering edge: model `gated` waits for `read`, which one of its hooks reads. +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +struct HookEdge { + hook_name: String, + gated: ResourceKey, + read: ResourceKey, + hook_type: HookType, + path: Option, +} + +/// The `CompileInputError` message for the first unknown read, hooks taken by name. +pub(crate) fn unknown_read(request: &ReferenceRequest) -> Option { + let mut hooks: Vec<&PythonHook> = request.hooks.iter().collect(); + hooks.sort_by(|left, right| left.name.cmp(&right.name)); + for hook in hooks { + for (kind, name) in &hook.reads { + if !known(request, kind, name) { + return Some(format!( + "Python hook '{}' in '{}' reads unknown {kind} '{name}'", + hook.name, hook.path + )); + } + } + } + None +} + +/// Whether a model, source or seed of that kind and name exists. +fn known(request: &ReferenceRequest, kind: &str, name: &str) -> bool { + [MODEL_TYPE, SOURCE_TYPE, SEED_TYPE].contains(&kind) + && request + .resources + .iter() + .any(|resource| resource.key.0 == kind && resource.key.1 == name) +} + +/// `hook_read_cycles_impl` as Python's P007 diagnostics, in its order. +pub(crate) fn hook_diagnostics( + request: &ReferenceRequest, + gates: &[GateEdge], +) -> Vec { + let mut edges: Vec = hook_edges(request); + if edges.is_empty() { + return Vec::new(); + } + let mut upstream: Upstream = lineage_upstream(&request.resources); + for gate in gates { + upstream + .entry(gate.gated.clone()) + .or_default() + .push(gate.read.clone()); + } + for edge in &edges { + upstream + .entry(edge.gated.clone()) + .or_default() + .push(edge.read.clone()); + } + edges.sort_by(|left, right| { + (&left.gated.1, &left.hook_name, &left.read.1).cmp(&( + &right.gated.1, + &right.hook_name, + &right.read.1, + )) + }); + edges + .iter() + .filter(|edge| reaches(&upstream, &edge.read, &edge.gated)) + .map(diagnostic) + .collect() +} + +/// `hook_read_edges_impl`: Python then SQL hook reads per model, deduplicated, minus self-reads. +fn hook_edges(request: &ReferenceRequest) -> Vec { + let mut candidates: Vec = Vec::new(); + for model in &request.models { + let gated: ResourceKey = (MODEL_TYPE.to_owned(), model.name.clone()); + for hook_name in &model.python_hooks { + let reads: &[ResourceKey] = request + .hooks + .iter() + .rev() + .find(|hook| &hook.name == hook_name && !hook.reads.is_empty()) + .map_or(&[], |hook| hook.reads.as_slice()); + let path: Option = request + .hooks + .iter() + .rev() + .find(|hook| &hook.name == hook_name) + .map(|hook| hook.path.clone()); + candidates.extend(reads.iter().map(|read| HookEdge { + hook_name: hook_name.clone(), + gated: gated.clone(), + read: read.clone(), + hook_type: HookType::Python, + path: path.clone(), + })); + } + for hook in &model.sql_hooks { + let (hook_name, hook_type) = match &hook.name { + Some(name) => (name.clone(), HookType::Sql), + None => ( + format!("{}[{}]", hook.hook_key, hook.index), + HookType::InlineSql, + ), + }; + let path: String = hook.path.clone().unwrap_or_else(|| model.path.clone()); + candidates.extend(hook.reads.iter().map(|read| HookEdge { + hook_name: hook_name.clone(), + gated: gated.clone(), + read: read.clone(), + hook_type, + path: Some(path.clone()), + })); + } + } + let mut seen: HashSet = HashSet::new(); + candidates + .into_iter() + .filter(|edge| edge.read != edge.gated && seen.insert(edge.clone())) + .collect() +} + +fn diagnostic(edge: &HookEdge) -> ReferenceDiagnostic { + let label: String = match edge.hook_type { + HookType::Python => format!("Python hook '{}'", edge.hook_name), + HookType::Sql => format!("SQL hook '{}'", edge.hook_name), + HookType::InlineSql => format!("inline SQL hook {}", edge.hook_name), + }; + let destination: &str = if edge.hook_type == HookType::Python { + PYTHON_DESTINATION + } else { + SQL_DESTINATION + }; + let gated: &str = &edge.gated.1; + ReferenceDiagnostic { + code: HOOK_READ_CODE, + message: format!( + "{label} on {} '{gated}' reads {} '{}', which depends on '{gated}'; a hook runs as \ + part of its model, so it cannot wait for a resource built from that model", + edge.gated.0, edge.read.0, edge.read.1 + ), + help: format!( + "attach the hook to a model built after '{}', or drop the read and use \ + {destination} for '{gated}' itself", + edge.read.1 + ), + path: edge.path.clone(), + owner: None, + line: None, + resource: Some(edge.gated.clone()), + } +} diff --git a/crates/sqlbuild-analysis/src/explicit_references/_helpers/mod.rs b/crates/sqlbuild-analysis/src/explicit_references/_helpers/mod.rs new file mode 100644 index 0000000000..e6c6923006 --- /dev/null +++ b/crates/sqlbuild-analysis/src/explicit_references/_helpers/mod.rs @@ -0,0 +1,5 @@ +pub(crate) mod audit_gates; +pub(crate) mod graph; +pub(crate) mod hook_reads; +pub(crate) mod python_sql; +pub(crate) mod relations; diff --git a/crates/sqlbuild-analysis/src/explicit_references/_helpers/python_sql.rs b/crates/sqlbuild-analysis/src/explicit_references/_helpers/python_sql.rs new file mode 100644 index 0000000000..1932b03970 --- /dev/null +++ b/crates/sqlbuild-analysis/src/explicit_references/_helpers/python_sql.rs @@ -0,0 +1,266 @@ +//! Python's P008 check of project relation names hard-coded in literal SQL in Python code. + +use std::collections::HashSet; + +use sqlbuild_core::text::main::active_python_text::active_python_text; +use sqlbuild_core::text::main::python_casefold::python_casefold; + +use crate::explicit_references::_helpers::relations::{ + ProjectRelation, matched, project_relations, +}; +use crate::explicit_references::constants::{ + HARD_CODED_RELATION_CODE, HOOK_OWNER, LOADER_OWNER, SOURCE_TYPE, +}; +use crate::explicit_references::errors::ReferenceFailure; +use crate::explicit_references::models::{ + LiteralSql, ReferenceDiagnostic, ReferenceReport, ReferenceRequest, Relation, SqlOwner, + UnmatchedRelation, +}; +use crate::explicit_references::types::ResourceKey; +use crate::relation_names::errors::RelationNamesFailure; +use crate::relation_names::main::extract_relation_names::extract_relation_names; +use crate::relation_names::models::ExtractedRelations; + +/// A diagnostic's identity: owner label, line and the matched resource. +type FoundKey = (String, usize, ResourceKey); + +/// What one relation of one literal yields. +enum Finding { + Unmatched(UnmatchedRelation), + Diagnostic(FoundKey, ReferenceDiagnostic), +} + +/// One owner's literal SQL against the project-relation index. +struct OwnerScan<'a> { + request: &'a ReferenceRequest, + index: &'a [ProjectRelation], + owner_index: usize, + owner: &'a SqlOwner, +} + +/// `python_sql_reference_diagnostics`: P008 errors sorted by path, line and owner, and unmatched. +pub(crate) fn python_sql_report( + request: &ReferenceRequest, +) -> Result { + if request.owners.is_empty() { + return Ok(ReferenceReport::default()); + } + let index: Vec = project_relations(request); + let mut findings: Vec = Vec::new(); + for (owner_index, owner) in request.owners.iter().enumerate() { + let scan = OwnerScan { + request, + index: &index, + owner_index, + owner, + }; + findings.extend(scan.findings()?); + } + let mut keys: HashSet = HashSet::new(); + let mut found: Vec<(FoundKey, ReferenceDiagnostic)> = Vec::new(); + let mut unmatched: Vec = Vec::new(); + let mut seen: HashSet = HashSet::new(); + for finding in findings { + match finding { + Finding::Diagnostic(key, diagnostic) => { + if keys.insert(key.clone()) { + found.push((key, diagnostic)); + } + } + Finding::Unmatched(relation) => { + if seen.insert(unmatched_identity(request, &relation)) { + unmatched.push(relation); + } + } + } + } + found.sort_by_cached_key(|(key, diagnostic)| { + let owner: usize = diagnostic.owner.unwrap_or_default(); + ( + request.owners[owner].path_order, + key.1, + key.0.clone(), + key.2.clone(), + ) + }); + Ok(ReferenceReport { + diagnostics: found + .into_iter() + .map(|(_, diagnostic)| diagnostic) + .collect(), + unmatched, + }) +} + +impl OwnerScan<'_> { + /// Each literal in line order, its created temporary tables hiding later unqualified names. + fn findings(&self) -> Result, ReferenceFailure> { + let mut temporary: HashSet = HashSet::new(); + let mut literals: Vec<&LiteralSql> = self.owner.literals.iter().collect(); + literals.sort_by_key(|literal| literal.line); + let mut findings: Vec = Vec::new(); + for literal in literals { + let Some(extracted) = extracted(self.request, literal)? else { + continue; + }; + temporary.extend(extracted.temporary); + for written in extracted.relations { + let relation = Relation { + name: written.name, + schema: written.schema, + database: written.database, + }; + findings.extend(self.finding(literal, &relation, &temporary)); + } + } + Ok(findings) + } + + /// `_hard_coded_relations` for one relation of one literal. + fn finding( + &self, + literal: &LiteralSql, + relation: &Relation, + temporary: &HashSet, + ) -> Option { + if joined(relation, "").contains(&self.request.placeholder) { + return None; + } + if relation.schema.is_none() + && temporary.contains(&python_casefold(active_python_text(), &relation.name)) + { + return None; + } + let Some(found) = matched(self.index, relation) else { + return Some(Finding::Unmatched(UnmatchedRelation { + owner: self.owner_index, + line: literal.line, + method: literal.method.clone(), + relation: relation.clone(), + })); + }; + if found.compatibility_for.is_none() && self.owner.own_refs.contains(&found.target) { + return None; + } + let written: String = joined(relation, "."); + Some(Finding::Diagnostic( + (self.owner.label.clone(), literal.line, found.target.clone()), + ReferenceDiagnostic { + code: HARD_CODED_RELATION_CODE, + message: self.message(literal, &written, found), + help: self.help(relation, &written, found), + path: None, + owner: Some(self.owner_index), + line: Some(literal.line), + resource: None, + }, + )) + } + + fn message(&self, literal: &LiteralSql, written: &str, found: &ProjectRelation) -> String { + match &found.compatibility_for { + Some(model) => format!( + "{} names '{written}' in SQL passed to ctx.{}(); it is the old name of \ + model:{model}, kept only as a compatibility view for consumers outside the \ + project", + self.owner.label, literal.method + ), + None => format!( + "{} names {}:{} as '{written}' in SQL passed to ctx.{}()", + self.owner.label, found.target.0, found.target.1, literal.method + ), + } + } + + fn help(&self, relation: &Relation, written: &str, found: &ProjectRelation) -> String { + let qualify: String = if relation.schema.is_none() { + format!( + "\n = help: if '{written}' is an external table that shares the name, qualify \ + it with its schema" + ) + } else { + String::new() + }; + format!( + "{}{qualify}\n = help: {}", + self.remedy(&found.target), + self.request.explicit_help + ) + } + + /// `hard_coded_relation_remedy_impl`. + fn remedy(&self, (kind, name): &ResourceKey) -> String { + let typed: String = format!("{kind}(\"{name}\")"); + if self.owner.kind == LOADER_OWNER { + if kind != SOURCE_TYPE { + return format!( + "loaders run before models and seeds and cannot read them; read \ + {kind}:{name} from a task or asset instead" + ); + } + return match self + .owner + .upstream_loaders + .iter() + .find(|(source, _)| source == name) + { + Some((_, loader)) => { + format!("use ctx.loader({loader}) instead of the relation name") + } + None => format!("use ctx.source(\"{name}\") instead of the relation name"), + }; + } + let declaration: String = if self.owner.kind == HOOK_OWNER { + format!("@hook(reads={typed})") + } else { + format!("depends_on={typed}") + }; + format!( + "declare it with {declaration} and use ctx.relation({typed}) instead of the relation \ + name" + ) + } +} + +fn extracted( + request: &ReferenceRequest, + literal: &LiteralSql, +) -> Result, ReferenceFailure> { + extract_relation_names(&literal.sql, request.dialect.as_deref()).map_err( + |failure| match failure { + RelationNamesFailure::UnknownDialect(message) => { + ReferenceFailure::UnknownDialect(message) + } + RelationNamesFailure::Internal(reason) => ReferenceFailure::Internal(reason), + }, + ) +} + +/// The relation's non-empty database, schema and name parts joined by `separator`. +fn joined(relation: &Relation, separator: &str) -> String { + let mut parts: Vec<&str> = Vec::new(); + for part in [&relation.database, &relation.schema].into_iter().flatten() { + parts.push(part); + } + parts.push(&relation.name); + parts.retain(|part| !part.is_empty()); + parts.join(separator) +} + +/// `LiteralSqlRelation` equality: owner label, kind and path, line, method and relation. +fn unmatched_identity(request: &ReferenceRequest, item: &UnmatchedRelation) -> UnmatchedRelation { + let owner: &SqlOwner = &request.owners[item.owner]; + let canonical: usize = request + .owners + .iter() + .position(|other| { + other.label == owner.label + && other.kind == owner.kind + && other.path_order == owner.path_order + }) + .unwrap_or(item.owner); + UnmatchedRelation { + owner: canonical, + ..item.clone() + } +} diff --git a/crates/sqlbuild-analysis/src/explicit_references/_helpers/relations.rs b/crates/sqlbuild-analysis/src/explicit_references/_helpers/relations.rs new file mode 100644 index 0000000000..69747194a0 --- /dev/null +++ b/crates/sqlbuild-analysis/src/explicit_references/_helpers/relations.rs @@ -0,0 +1,153 @@ +//! Python's compiled project-relation index and its qualifier-tolerant matcher. + +use std::collections::HashSet; + +use sqlbuild_core::text::main::active_python_text::active_python_text; +use sqlbuild_core::text::main::python_casefold::python_casefold; +use sqlbuild_core::text::main::python_strip::python_strip; + +use crate::explicit_references::constants::{ + MIGRATE_FROM_QUOTES, MODEL_TYPE, SCHEMA_QUALIFIED_PARTS, SEED_TYPE, SOURCE_TYPE, +}; +use crate::explicit_references::models::{ReferenceRequest, Relation, SourceRelation}; +use crate::explicit_references::types::ResourceKey; + +/// A relation SQLBuild manages for one resource, or a model's retained old name. +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub(crate) struct ProjectRelation { + pub(crate) target: ResourceKey, + pub(crate) relation: Relation, + /// The model an old-name compatibility view keeps this name for. + pub(crate) compatibility_for: Option, +} + +/// `compiled_project_relations_impl`: models, seeds and table sources, then retained old names. +pub(crate) fn project_relations(request: &ReferenceRequest) -> Vec { + let mut declared: Vec = request + .models + .iter() + .map(|model| relation(MODEL_TYPE, &model.name, model.destination.clone())) + .collect(); + declared.extend( + request + .seeds + .iter() + .map(|seed| relation(SEED_TYPE, &seed.name, seed.relation.clone())), + ); + declared.extend( + request + .sources + .iter() + .filter(|source| !source.expression) + .map(source_relation), + ); + let declared: Vec = deduplicated(declared); + let old_names: Vec = old_names(request, &declared); + deduplicated(declared.into_iter().chain(old_names).collect()) +} + +/// `match_project_relation_impl` without default qualifiers: the first relation that matches. +pub(crate) fn matched<'a>( + index: &'a [ProjectRelation], + relation: &Relation, +) -> Option<&'a ProjectRelation> { + let name: String = folded(&relation.name); + index.iter().find(|candidate| { + folded(&candidate.relation.name) == name + && compatible(relation.schema.as_ref(), candidate.relation.schema.as_ref()) + && compatible( + relation.database.as_ref(), + candidate.relation.database.as_ref(), + ) + }) +} + +fn folded(text: &str) -> String { + python_casefold(active_python_text(), text) +} + +/// `_parts_compatible`: either part missing, or equal casefolded. +fn compatible(left: Option<&String>, right: Option<&String>) -> bool { + match (left, right) { + (Some(left), Some(right)) => folded(left) == folded(right), + _ => true, + } +} + +/// `_declared_old_names`: `migrate_from` names not already a declared relation. +fn old_names(request: &ReferenceRequest, declared: &[ProjectRelation]) -> Vec { + let model_names: HashSet<&str> = request + .models + .iter() + .map(|model| model.name.as_str()) + .collect(); + let mut found: Vec = Vec::new(); + for model in &request.models { + let Some(raw) = &model.migrate_from else { + continue; + }; + let parts: Vec<&str> = raw + .split('.') + .map(|part| python_strip(part).trim_matches(MIGRATE_FROM_QUOTES)) + .collect(); + if parts.len() == 1 && model_names.contains(parts[0]) { + continue; + } + let count: usize = parts.len(); + let old = Relation { + name: parts[count - 1].to_owned(), + schema: if count > 1 { + Some(parts[count - 2].to_owned()) + } else { + model.destination.schema.clone() + }, + database: if count > SCHEMA_QUALIFIED_PARTS { + Some(parts[count - 3].to_owned()) + } else { + model.destination.database.clone() + }, + }; + if matched(declared, &old).is_some() { + continue; + } + found.push(ProjectRelation { + target: (MODEL_TYPE.to_owned(), model.name.clone()), + relation: old, + compatibility_for: Some(model.name.clone()), + }); + } + found +} + +/// A table source's relation: its table, or its name where the table is unset or empty. +fn source_relation(source: &SourceRelation) -> ProjectRelation { + let name: String = match &source.table { + Some(table) if !table.is_empty() => table.clone(), + _ => source.name.clone(), + }; + relation( + SOURCE_TYPE, + &source.name, + Relation { + name, + schema: source.schema.clone(), + database: source.database.clone(), + }, + ) +} + +fn relation(kind: &str, name: &str, relation: Relation) -> ProjectRelation { + ProjectRelation { + target: (kind.to_owned(), name.to_owned()), + relation, + compatibility_for: None, + } +} + +fn deduplicated(relations: Vec) -> Vec { + let mut seen: HashSet = HashSet::new(); + relations + .into_iter() + .filter(|relation| seen.insert(relation.clone())) + .collect() +} diff --git a/crates/sqlbuild-analysis/src/explicit_references/constants.rs b/crates/sqlbuild-analysis/src/explicit_references/constants.rs new file mode 100644 index 0000000000..2517aae27c --- /dev/null +++ b/crates/sqlbuild-analysis/src/explicit_references/constants.rs @@ -0,0 +1,26 @@ +//! Resource kinds, codes and wording Python's explicit-reference checks use. + +pub(crate) const MODEL_TYPE: &str = "model"; +pub(crate) const SOURCE_TYPE: &str = "source"; +pub(crate) const SEED_TYPE: &str = "seed"; +pub(crate) const UDF_TYPE: &str = "udf"; +pub(crate) const TABLE_FUNCTION_TYPE: &str = "table_fn"; +pub(crate) const SQL_TEST_TYPE: &str = "sql_test"; +/// Resource types an attached audit's extra reads can gate on. +pub(crate) const READABLE_TYPES: [&str; 5] = [ + MODEL_TYPE, + SEED_TYPE, + SOURCE_TYPE, + UDF_TYPE, + TABLE_FUNCTION_TYPE, +]; +pub(crate) const AUDIT_GATE_CODE: &str = "P005"; +pub(crate) const HOOK_READ_CODE: &str = "P007"; +pub(crate) const HARD_CODED_RELATION_CODE: &str = "P008"; +pub(crate) const LOADER_OWNER: &str = "loader"; +pub(crate) const HOOK_OWNER: &str = "hook"; +pub(crate) const PYTHON_DESTINATION: &str = "ctx.destination"; +pub(crate) const SQL_DESTINATION: &str = "@@CTX:destination.qualified"; +/// The quotes Python strips from each `migrate_from` part. +pub(crate) const MIGRATE_FROM_QUOTES: [char; 2] = ['"', '`']; +pub(crate) const SCHEMA_QUALIFIED_PARTS: usize = 2; diff --git a/crates/sqlbuild-analysis/src/explicit_references/errors.rs b/crates/sqlbuild-analysis/src/explicit_references/errors.rs new file mode 100644 index 0000000000..3d112118bf --- /dev/null +++ b/crates/sqlbuild-analysis/src/explicit_references/errors.rs @@ -0,0 +1,11 @@ +//! Why the explicit-reference checks stop. + +/// The error Python's checks raise, or an internal native failure. +#[derive(Debug, Clone, PartialEq, Eq)] +pub enum ReferenceFailure { + /// `CompileInputError(message)`: a Python hook reads an unknown resource. + CompileInput(String), + /// The relation-name parse's `ValueError` for an unknown dialect. + UnknownDialect(String), + Internal(String), +} diff --git a/crates/sqlbuild-analysis/src/explicit_references/main/check_explicit_references.rs b/crates/sqlbuild-analysis/src/explicit_references/main/check_explicit_references.rs new file mode 100644 index 0000000000..21f50afd64 --- /dev/null +++ b/crates/sqlbuild-analysis/src/explicit_references/main/check_explicit_references.rs @@ -0,0 +1,37 @@ +//! Compile's explicit-reference checks over one compiled project, in Python's order. + +use sqlbuild_core::panics::main::catch_compiler_panic::catch_compiler_panic; + +use crate::explicit_references::_helpers::audit_gates::{gate_diagnostics, gate_edges}; +use crate::explicit_references::_helpers::hook_reads::{hook_diagnostics, unknown_read}; +use crate::explicit_references::_helpers::python_sql::python_sql_report; +use crate::explicit_references::errors::ReferenceFailure; +use crate::explicit_references::models::{ReferenceReport, ReferenceRequest}; + +/// P005, P007 then P008 diagnostics and unmatched Python-SQL relations, or the error Python raises. +pub fn check_explicit_references( + request: &ReferenceRequest, +) -> Result { + catch_compiler_panic(|| Ok(checked(request))) + .map_err(ReferenceFailure::Internal) + .and_then(|outcome| outcome) +} + +fn checked(request: &ReferenceRequest) -> Result { + let python_sql: ReferenceReport = if request.enforce_explicit { + python_sql_report(request)? + } else { + ReferenceReport::default() + }; + let gates = gate_edges(request); + let mut diagnostics = gate_diagnostics(request, &gates); + if let Some(message) = unknown_read(request) { + return Err(ReferenceFailure::CompileInput(message)); + } + diagnostics.extend(hook_diagnostics(request, &gates)); + diagnostics.extend(python_sql.diagnostics); + Ok(ReferenceReport { + diagnostics, + unmatched: python_sql.unmatched, + }) +} diff --git a/crates/sqlbuild-analysis/src/explicit_references/main/mod.rs b/crates/sqlbuild-analysis/src/explicit_references/main/mod.rs new file mode 100644 index 0000000000..7cb27294a1 --- /dev/null +++ b/crates/sqlbuild-analysis/src/explicit_references/main/mod.rs @@ -0,0 +1 @@ +pub mod check_explicit_references; diff --git a/crates/sqlbuild-analysis/src/explicit_references/mod.rs b/crates/sqlbuild-analysis/src/explicit_references/mod.rs new file mode 100644 index 0000000000..a24dd11bfb --- /dev/null +++ b/crates/sqlbuild-analysis/src/explicit_references/mod.rs @@ -0,0 +1,11 @@ +//! Compile's explicit-reference checks: audit gates, hook reads and Python-SQL relation names. + +pub(crate) mod _helpers; +mod constants; +pub mod errors; +pub mod main; +pub mod models; +pub mod types; + +#[cfg(test)] +mod tests; diff --git a/crates/sqlbuild-analysis/src/explicit_references/models.rs b/crates/sqlbuild-analysis/src/explicit_references/models.rs new file mode 100644 index 0000000000..6c730de62d --- /dev/null +++ b/crates/sqlbuild-analysis/src/explicit_references/models.rs @@ -0,0 +1,151 @@ +//! The plain project facts the explicit-reference checks read, and what they report. + +use serde::{Deserialize, Serialize}; + +use crate::explicit_references::types::ResourceKey; + +/// Everything the checks read, collected from the compiled project and user Python by Python. +#[derive(Debug, Clone, Deserialize)] +pub struct ReferenceRequest { + /// `[references] enforce_explicit`: whether Python SQL is checked at all. + pub enforce_explicit: bool, + pub dialect: Option, + /// `explicit_references_help(allowed="hard-coded relation names")`. + pub explicit_help: String, + /// The text Python substitutes for f-string values in literal SQL. + pub placeholder: String, + /// Models, sources, seeds and functions in project order, with their dependencies. + pub resources: Vec, + pub models: Vec, + pub sources: Vec, + pub seeds: Vec, + pub audits: Vec, + /// `project.hook_functions` in order. + pub hooks: Vec, + /// Python SQL owners: tasks, assets, checks, loaders, then hooks. + pub owners: Vec, +} + +/// One resource's key and dependencies. +#[derive(Debug, Clone, Deserialize)] +pub struct GraphResource { + pub key: ResourceKey, + pub deps: Vec, +} + +/// A relation name with the qualifiers written or configured. +#[derive(Debug, Clone, PartialEq, Eq, Hash, Deserialize, Serialize)] +pub struct Relation { + pub name: String, + pub schema: Option, + pub database: Option, +} + +/// One model's destination, hooks and old name. +#[derive(Debug, Clone, Deserialize)] +pub struct ModelReferences { + pub name: String, + pub path: String, + pub destination: Relation, + /// `model_python_hook_names(model)`. + pub python_hooks: Vec, + pub sql_hooks: Vec, + /// The `migrate_from` text where it is a string and old-name views are retained. + pub migrate_from: Option, +} + +/// One SQL hook entry with declared reads: its hook key, position and identity. +#[derive(Debug, Clone, Deserialize)] +pub struct SqlHook { + pub hook_key: String, + pub index: usize, + pub name: Option, + pub path: Option, + pub reads: Vec, +} + +/// One source: its table or name and namespace, or an expression source. +#[derive(Debug, Clone, Deserialize)] +pub struct SourceRelation { + pub name: String, + pub table: Option, + pub schema: Option, + pub database: Option, + pub expression: bool, +} + +/// A seed's name and destination. +#[derive(Debug, Clone, Deserialize)] +pub struct NamedRelation { + pub name: String, + pub relation: Relation, +} + +/// One audit: its file, attached target and scope dependencies. +#[derive(Debug, Clone, Deserialize)] +pub struct AuditGate { + pub name: String, + pub path: String, + pub target: Option, + pub scope_deps: Vec, +} + +/// One Python hook function and the resources it declares it reads. +#[derive(Debug, Clone, Deserialize)] +pub struct PythonHook { + pub name: String, + pub path: String, + pub reads: Vec, +} + +/// Python code whose literal SQL is checked, and what it may name itself. +#[derive(Debug, Clone, Deserialize)] +pub struct SqlOwner { + pub label: String, + /// `HardCodedRelationOwnerKind`: `node`, `hook` or `loader`. + pub kind: String, + /// The owner's position among its project's paths in Python's `Path` order. + pub path_order: usize, + pub own_refs: Vec, + /// Source name to the upstream loader function that writes it. + pub upstream_loaders: Vec<(String, String)>, + pub literals: Vec, +} + +/// One literal SQL string passed to `ctx.query` or `ctx.execute_sql`. +#[derive(Debug, Clone, Deserialize)] +pub struct LiteralSql { + pub method: String, + pub sql: String, + pub line: usize, +} + +/// The diagnostics in Python's order and literal SQL relations that matched no project relation. +#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize)] +pub struct ReferenceReport { + pub diagnostics: Vec, + pub unmatched: Vec, +} + +/// One compile error diagnostic. +#[derive(Debug, Clone, PartialEq, Eq, Serialize)] +pub struct ReferenceDiagnostic { + pub code: &'static str, + pub message: String, + pub help: String, + /// A file path as Python passed it, or None. + pub path: Option, + /// The owner whose path and line locate a Python-SQL diagnostic. + pub owner: Option, + pub line: Option, + pub resource: Option, +} + +/// A relation literal SQL names that is not a project relation. +#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize)] +pub struct UnmatchedRelation { + pub owner: usize, + pub line: usize, + pub method: String, + pub relation: Relation, +} diff --git a/crates/sqlbuild-analysis/src/explicit_references/tests.rs b/crates/sqlbuild-analysis/src/explicit_references/tests.rs new file mode 100644 index 0000000000..212540b8af --- /dev/null +++ b/crates/sqlbuild-analysis/src/explicit_references/tests.rs @@ -0,0 +1,6 @@ +#[path = "tests/test_explicit_references.rs"] +mod explicit_references; +#[path = "tests/helpers.rs"] +mod helpers; +#[path = "tests/test_types.rs"] +mod test_types; diff --git a/crates/sqlbuild-analysis/src/explicit_references/tests/helpers.rs b/crates/sqlbuild-analysis/src/explicit_references/tests/helpers.rs new file mode 100644 index 0000000000..132b5bad09 --- /dev/null +++ b/crates/sqlbuild-analysis/src/explicit_references/tests/helpers.rs @@ -0,0 +1,60 @@ +use crate::explicit_references::models::{ + ModelReferences, NamedRelation, ReferenceRequest, Relation, SourceRelation, +}; + +pub(crate) fn relation(name: &str, schema: Option<&str>, database: Option<&str>) -> Relation { + Relation { + name: name.to_owned(), + schema: schema.map(str::to_owned), + database: database.map(str::to_owned), + } +} + +fn model(name: &str, migrate_from: Option<&str>) -> ModelReferences { + ModelReferences { + name: name.to_owned(), + path: format!("models/{name}.sql"), + destination: relation(name, Some("main"), Some("memory")), + python_hooks: Vec::new(), + sql_hooks: Vec::new(), + migrate_from: migrate_from.map(str::to_owned), + } +} + +pub(crate) fn request() -> ReferenceRequest { + ReferenceRequest { + enforce_explicit: true, + dialect: None, + explicit_help: String::new(), + placeholder: "__sqlbuild_python_value_".to_owned(), + resources: Vec::new(), + models: vec![ + model("customers", Some(" `legacy_customers` ")), + model("orders", Some("\"archive\".old_orders")), + model("regions", Some("customers")), + ], + sources: vec![ + SourceRelation { + name: "raw_orders".to_owned(), + table: Some(String::new()), + schema: Some("landing".to_owned()), + database: None, + expression: false, + }, + SourceRelation { + name: "computed".to_owned(), + table: None, + schema: None, + database: None, + expression: true, + }, + ], + seeds: vec![NamedRelation { + name: "country_codes".to_owned(), + relation: relation("country_codes", Some("seeds"), None), + }], + audits: Vec::new(), + hooks: Vec::new(), + owners: Vec::new(), + } +} diff --git a/crates/sqlbuild-analysis/src/explicit_references/tests/test_explicit_references.rs b/crates/sqlbuild-analysis/src/explicit_references/tests/test_explicit_references.rs new file mode 100644 index 0000000000..9fe8f52a87 --- /dev/null +++ b/crates/sqlbuild-analysis/src/explicit_references/tests/test_explicit_references.rs @@ -0,0 +1,57 @@ +use crate::explicit_references::_helpers::relations::{matched, project_relations}; +use crate::explicit_references::tests::helpers::{relation, request}; +use crate::explicit_references::tests::test_types::MatchTestCase; + +#[test] +fn given_written_relations_when_matching_project_relations_then_matches_python() { + let test_cases = [ + MatchTestCase { + description: "an unqualified name matches case-insensitively", + written: ("CUSTOMERS", None, None), + expected_match: Some(("model", "customers", None)), + }, + MatchTestCase { + description: "a conflicting schema does not match", + written: ("customers", Some("other"), None), + expected_match: None, + }, + MatchTestCase { + description: "an empty source table falls back to the source name", + written: ("raw_orders", Some("LANDING"), None), + expected_match: Some(("source", "raw_orders", None)), + }, + MatchTestCase { + description: "an expression source is no relation", + written: ("computed", None, None), + expected_match: None, + }, + MatchTestCase { + description: "a stripped, unquoted old name inherits the destination namespace", + written: ("legacy_customers", Some("main"), Some("memory")), + expected_match: Some(("model", "customers", Some("customers"))), + }, + MatchTestCase { + description: "a schema-qualified old name keeps its schema", + written: ("old_orders", Some("archive"), None), + expected_match: Some(("model", "orders", Some("orders"))), + }, + MatchTestCase { + description: "an old name equal to another model is that model, not an old name", + written: ("customers", None, None), + expected_match: Some(("model", "customers", None)), + }, + ]; + let index = project_relations(&request()); + + for test_case in test_cases { + let (name, schema, database) = test_case.written; + let found = matched(&index, &relation(name, schema, database)).map(|found| { + ( + found.target.0.as_str(), + found.target.1.as_str(), + found.compatibility_for.as_deref(), + ) + }); + assert_eq!(found, test_case.expected_match, "{}", test_case.description); + } +} diff --git a/crates/sqlbuild-analysis/src/explicit_references/tests/test_types.rs b/crates/sqlbuild-analysis/src/explicit_references/tests/test_types.rs new file mode 100644 index 0000000000..3d4be469e1 --- /dev/null +++ b/crates/sqlbuild-analysis/src/explicit_references/tests/test_types.rs @@ -0,0 +1,7 @@ +pub(crate) struct MatchTestCase { + pub(crate) description: &'static str, + /// `(name, schema, database)` written in SQL. + pub(crate) written: (&'static str, Option<&'static str>, Option<&'static str>), + /// The matched `(kind, name, compatibility_for)`, or None. + pub(crate) expected_match: Option<(&'static str, &'static str, Option<&'static str>)>, +} diff --git a/crates/sqlbuild-analysis/src/explicit_references/types.rs b/crates/sqlbuild-analysis/src/explicit_references/types.rs new file mode 100644 index 0000000000..7e1941e481 --- /dev/null +++ b/crates/sqlbuild-analysis/src/explicit_references/types.rs @@ -0,0 +1,4 @@ +//! Explicit-reference key aliases. + +/// A `CompiledObjectKey`: `(resource type, name)`; typed SQL refs use the same kind names. +pub type ResourceKey = (String, String); diff --git a/crates/sqlbuild-analysis/src/lib.rs b/crates/sqlbuild-analysis/src/lib.rs index 2c6aee23ac..4d62706cbb 100644 --- a/crates/sqlbuild-analysis/src/lib.rs +++ b/crates/sqlbuild-analysis/src/lib.rs @@ -7,8 +7,10 @@ pub mod column_references; pub mod compiler; mod constants; pub mod contracts; +pub mod explicit_references; pub mod lineage; pub mod query_analysis; +pub mod relation_names; pub mod semantic_checks; pub mod semantic_usage; pub mod semantic_validation; diff --git a/crates/sqlbuild-analysis/src/lineage/_helpers/parsed_lineage.rs b/crates/sqlbuild-analysis/src/lineage/_helpers/parsed_lineage.rs index 55e9557c5f..93f982d537 100644 --- a/crates/sqlbuild-analysis/src/lineage/_helpers/parsed_lineage.rs +++ b/crates/sqlbuild-analysis/src/lineage/_helpers/parsed_lineage.rs @@ -12,8 +12,8 @@ use crate::lineage::_helpers::references::{PhysicalResource, normalized_sql, phy use crate::lineage::_helpers::stars::star_lineage; use crate::lineage::constants::{KIND_SELECT, KIND_UNION, MAX_FUNCTION_CALL_DEPTH}; use crate::lineage::models::{ - FastLineageOutcome, LineageColumn, LineageConfidence, LineageDeferral, LineageResourceType, - LineageSource, LineageTransformKind, + FastLineageOutcome, LineageColumn, LineageConfidence, LineageResourceType, LineageSource, + LineageTransformKind, }; /// The parse options SQLBuild's Polyglot proxy gives `parse_one`, decoded as the wheel does. @@ -30,28 +30,32 @@ pub(crate) struct ParsedModel<'a> { pub(crate) query_sql: &'a str, pub(crate) inferred_names: &'a [String], pub(crate) schema: &'a HashMap>, - pub(crate) dialect: Option, + /// The parser dialect, or the dialect name Polyglot does not know. + pub(crate) dialect: Result, pub(crate) options: &'a Result, } -pub(crate) fn parsed_model_lineage(model: &ParsedModel<'_>) -> FastLineageOutcome { - let Some(dialect) = model.dialect else { - return FastLineageOutcome::Deferred(LineageDeferral::UnsupportedDialect); - }; - let Ok(options) = model.options else { - return FastLineageOutcome::Deferred(LineageDeferral::NativeFailure); +/// The model's lineage outcome; fails on a tree the lineage walk cannot read. +pub(crate) fn parsed_model_lineage(model: &ParsedModel<'_>) -> Result { + let dialect: DialectType = match model.dialect { + Ok(dialect) => dialect, + Err(name) => return Ok(FastLineageOutcome::UnknownDialect(name.to_owned())), }; + let options: &ParseOptions = model + .options + .as_ref() + .map_err(|_| "the parse options do not build".to_owned())?; let physical = physical_resources(model.query_sql); let sql = normalized_sql(model.query_sql); let mut statements = match Dialect::get(dialect).parse_with_options(&sql, options) { Ok(statements) => statements, - Err(error) => return FastLineageOutcome::Unparsed(error.to_string()), + Err(error) => return Ok(FastLineageOutcome::Unparsed(error.to_string())), }; if statements.len() != 1 { - return FastLineageOutcome::Unparsed(format!( + return Ok(FastLineageOutcome::Unparsed(format!( "Expected 1 statement, found {}", statements.len() - )); + ))); } let parsed = statements.remove(0); let built = match parsed.variant_name() { @@ -60,9 +64,9 @@ pub(crate) fn parsed_model_lineage(model: &ParsedModel<'_>) -> FastLineageOutcom _ => Ok(None), }; match built { - Ok(Some((columns, has_star))) => FastLineageOutcome::Built { columns, has_star }, - Ok(None) => FastLineageOutcome::Omitted, - Err(UnreadableExpression) => FastLineageOutcome::Deferred(LineageDeferral::NativeFailure), + Ok(Some((columns, has_star))) => Ok(FastLineageOutcome::Built { columns, has_star }), + Ok(None) => Ok(FastLineageOutcome::Omitted), + Err(UnreadableExpression) => Err("a parsed tree the lineage walk cannot read".to_owned()), } } diff --git a/crates/sqlbuild-analysis/src/lineage/_helpers/projections.rs b/crates/sqlbuild-analysis/src/lineage/_helpers/projections.rs index d13bb561dc..eca2b47d55 100644 --- a/crates/sqlbuild-analysis/src/lineage/_helpers/projections.rs +++ b/crates/sqlbuild-analysis/src/lineage/_helpers/projections.rs @@ -15,9 +15,6 @@ use crate::lineage::models::{ LineageConfidence, LineageResourceType, LineageSource, LineageTransformKind, }; -/// Payload nesting past which Python's recursive `to_dict` walk may exceed its recursion limit. -const MAX_PAYLOAD_DEPTH: usize = 400; - /// A read Python would make differently, or fail on, so the model is deferred to Python. #[derive(Debug)] pub(crate) struct UnreadableExpression; @@ -265,41 +262,34 @@ fn column_refs(expression: &Expression) -> Result, Unreada }; return Ok(vec![(expression.get_name().to_owned(), table_name)]); } - payload_column_refs(&payload, 0) + Ok(payload_column_refs(&payload)) } -/// Python's recursive `visit`: a `column` dict ends its branch; tuples are never entered. -fn payload_column_refs( - node: &PythonValue, - depth: usize, -) -> Result, UnreadableExpression> { - if depth > MAX_PAYLOAD_DEPTH { - return Err(UnreadableExpression); - } - let children: Vec<&PythonValue> = match node { - PythonValue::Dict(entries) => { - if let Some(column @ PythonValue::Dict(_)) = node.get(PAYLOAD_COLUMN) { - let table_name = match column.get(PAYLOAD_TABLE) { - Some(table @ PythonValue::Dict(_)) => { - name_payload_value(table.get(PAYLOAD_NAME)) - } - _ => String::new(), - }; - return Ok(vec![( - name_payload_value(column.get(PAYLOAD_NAME)), - table_name, - )]); - } - entries.iter().map(|(_, value)| value).collect() - } - PythonValue::List(values) => values.iter().collect(), - _ => Vec::new(), - }; +/// Python's recursive `visit`, depth first in payload order. +fn payload_column_refs(root: &PythonValue) -> Vec<(String, String)> { let mut refs: Vec<(String, String)> = Vec::new(); - for child in children { - refs.extend(payload_column_refs(child, depth + 1)?); + let mut pending: Vec<&PythonValue> = vec![root]; + while let Some(node) = pending.pop() { + let children: Vec<&PythonValue> = match node { + PythonValue::Dict(entries) => { + if let Some(column @ PythonValue::Dict(_)) = node.get(PAYLOAD_COLUMN) { + let table_name = match column.get(PAYLOAD_TABLE) { + Some(table @ PythonValue::Dict(_)) => { + name_payload_value(table.get(PAYLOAD_NAME)) + } + _ => String::new(), + }; + refs.push((name_payload_value(column.get(PAYLOAD_NAME)), table_name)); + continue; + } + entries.iter().map(|(_, value)| value).collect() + } + PythonValue::List(values) => values.iter().collect(), + _ => Vec::new(), + }; + pending.extend(children.into_iter().rev()); } - Ok(refs) + refs } /// Python's `_polyglot_name_payload_value`. diff --git a/crates/sqlbuild-analysis/src/lineage/main/build_fast_lineage.rs b/crates/sqlbuild-analysis/src/lineage/main/build_fast_lineage.rs index 4eeb8c3c90..94dcca4ac8 100644 --- a/crates/sqlbuild-analysis/src/lineage/main/build_fast_lineage.rs +++ b/crates/sqlbuild-analysis/src/lineage/main/build_fast_lineage.rs @@ -6,6 +6,7 @@ use polyglot_sql::ParseOptions; use rayon::ThreadPool; use rayon::prelude::{IntoParallelRefIterator, ParallelIterator}; use sqlbuild_core::panics::main::catch_compiler_panic::catch_compiler_panic; +use sqlbuild_core::panics::main::native_failure::native_failure; use crate::lineage::_helpers::parsed_lineage::{ ParsedModel, parsed_model_lineage, proxy_parse_options, @@ -13,24 +14,44 @@ use crate::lineage::_helpers::parsed_lineage::{ use crate::lineage::_helpers::references::physical_resources; use crate::lineage::_helpers::stars::{schema_mapping, star_lineage}; use crate::lineage::main::parser_dialect::parser_dialect; -use crate::lineage::models::{ - FastLineageModel, FastLineageOutcome, FastLineageRequest, LineageDeferral, -}; +use crate::lineage::models::{FastLineageModel, FastLineageOutcome, FastLineageRequest}; +use crate::semantic_validation::main::new_analysis_pool::new_analysis_pool; use crate::semantic_validation::models::ProjectCatalog; /// One outcome per model, in request order, run on the compile's deep-stack analysis pool. pub fn build_fast_lineage( request: &FastLineageRequest, - catalog: &ProjectCatalog, + catalog: Option<&ProjectCatalog>, ) -> Result, String> { - let pool: Arc = catalog.analysis_pool()?; - Ok(pool.install(|| model_outcomes(request))) + let pool: Arc = match catalog { + Some(catalog) => catalog.analysis_pool()?, + None => Arc::new(new_analysis_pool()?), + }; + let outcomes: Vec> = + pool.install(|| model_outcomes(request)); + outcomes + .into_iter() + .enumerate() + .map(|(index, outcome)| { + outcome.map_err(|reason| { + native_failure( + &format!("native fast lineage of request model {index}"), + &reason, + ) + }) + }) + .collect() } -/// A parser panic defers only its own model. -fn model_outcomes(request: &FastLineageRequest) -> Vec { +/// Each model's outcome or internal failure, panics included, in request order. +fn model_outcomes(request: &FastLineageRequest) -> Vec> { let schema = schema_mapping(&request.schema); - let dialect = parser_dialect(request.dialect.as_deref()); + let name: &str = request + .dialect + .as_deref() + .filter(|name| !name.is_empty()) + .unwrap_or("generic"); + let dialect = parser_dialect(Some(name)); let options: Result = proxy_parse_options(); request .models @@ -39,11 +60,11 @@ fn model_outcomes(request: &FastLineageRequest) -> Vec { FastLineageModel::StarExpansion { query_sql, existing_columns, - } => FastLineageOutcome::StarColumns(star_lineage( + } => Ok(FastLineageOutcome::StarColumns(star_lineage( &schema, &physical_resources(query_sql), existing_columns.iter().map(String::as_str), - )), + ))), FastLineageModel::Parse { query_sql, inferred_columns, @@ -55,8 +76,7 @@ fn model_outcomes(request: &FastLineageRequest) -> Vec { dialect, options: &options, }; - catch_compiler_panic(|| Ok(parsed_model_lineage(&model))) - .unwrap_or(FastLineageOutcome::Deferred(LineageDeferral::NativeFailure)) + catch_compiler_panic(|| parsed_model_lineage(&model)) } }) .collect() diff --git a/crates/sqlbuild-analysis/src/lineage/main/parser_dialect.rs b/crates/sqlbuild-analysis/src/lineage/main/parser_dialect.rs index 61a7005ee7..fd78378ea2 100644 --- a/crates/sqlbuild-analysis/src/lineage/main/parser_dialect.rs +++ b/crates/sqlbuild-analysis/src/lineage/main/parser_dialect.rs @@ -1,22 +1,9 @@ -//! The polyglot dialect Python's `dialect or "generic"` names, if this parser build carries it. +//! The polyglot dialect Python's `dialect or "generic"` names, if Polyglot knows the name. use polyglot_sql::DialectType; -/// Python's `parse_one(dialect=dialect or "generic")` dialect, if this parser build carries it. -pub fn parser_dialect(name: Option<&str>) -> Option { +/// Python's `parse_one(dialect=dialect or "generic")` dialect, or the name Polyglot does not know. +pub fn parser_dialect(name: Option<&str>) -> Result { let name = name.filter(|name| !name.is_empty()).unwrap_or("generic"); - let Ok(dialect) = name.parse::() else { - return None; - }; - matches!( - dialect, - DialectType::Generic - | DialectType::PostgreSQL - | DialectType::BigQuery - | DialectType::Snowflake - | DialectType::DuckDB - | DialectType::TSQL - | DialectType::Databricks - ) - .then_some(dialect) + name.parse::().map_err(|_unknown_dialect| name) } diff --git a/crates/sqlbuild-analysis/src/lineage/models.rs b/crates/sqlbuild-analysis/src/lineage/models.rs index 7076c5dcaa..f4821c90fb 100644 --- a/crates/sqlbuild-analysis/src/lineage/models.rs +++ b/crates/sqlbuild-analysis/src/lineage/models.rs @@ -118,24 +118,6 @@ pub struct LineageColumn { pub upstream_columns: Vec, } -/// Why a model is handed back to Python, which builds its lineage exactly as before. -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -pub enum LineageDeferral { - /// The dialect is not compiled into the native parser. - UnsupportedDialect, - /// The parsed SQL could not be read as Python reads it. - NativeFailure, -} - -impl LineageDeferral { - pub fn as_str(self) -> &'static str { - match self { - Self::UnsupportedDialect => "unsupported_dialect", - Self::NativeFailure => "native_failure", - } - } -} - #[derive(Debug, Clone, PartialEq, Eq)] pub enum FastLineageOutcome { /// Star columns to append to the model's compact facts. @@ -149,23 +131,19 @@ pub enum FastLineageOutcome { Omitted, /// The SQL did not parse; Python logs this message and records no lineage. Unparsed(String), - Deferred(LineageDeferral), + /// Polyglot does not know the dialect name, so Python's parse raises `ValueError`. + UnknownDialect(String), } impl FastLineageOutcome { - /// `(status, columns, has_star, detail)`: detail is the parse error or the deferral kind. + /// `(status, columns, has_star, detail)`: detail is the parse error or the unknown dialect. pub fn into_parts(self) -> (&'static str, Vec, bool, Option) { match self { Self::StarColumns(columns) => ("star", columns, true, None), Self::Built { columns, has_star } => ("built", columns, has_star, None), Self::Omitted => ("omitted", Vec::new(), false, None), Self::Unparsed(message) => ("unparsed", Vec::new(), false, Some(message)), - Self::Deferred(kind) => ( - "deferred", - Vec::new(), - false, - Some(kind.as_str().to_owned()), - ), + Self::UnknownDialect(name) => ("unknown_dialect", Vec::new(), false, Some(name)), } } } diff --git a/crates/sqlbuild-analysis/src/lineage/tests/helpers.rs b/crates/sqlbuild-analysis/src/lineage/tests/helpers.rs index c375293a7a..a2876a6ac4 100644 --- a/crates/sqlbuild-analysis/src/lineage/tests/helpers.rs +++ b/crates/sqlbuild-analysis/src/lineage/tests/helpers.rs @@ -21,9 +21,10 @@ pub(crate) fn outcome_lines( schema: schema(), models: vec![model], }; - let outcomes: Vec = - build_fast_lineage(&request, &catalog()).expect("the analysis pool builds"); - outcomes.into_iter().map(described_outcome).collect() + build_fast_lineage(&request, Some(&catalog())).map_or_else( + |error| vec![("error", Vec::new(), false, Some(error))], + |outcomes| outcomes.into_iter().map(described_outcome).collect(), + ) } /// A `branches`-deep `UNION ALL` chain built from a caller thread with a `stack_bytes` stack. diff --git a/crates/sqlbuild-analysis/src/lineage/tests/test_build_fast_lineage.rs b/crates/sqlbuild-analysis/src/lineage/tests/test_build_fast_lineage.rs index c166eb7c97..a384f09acf 100644 --- a/crates/sqlbuild-analysis/src/lineage/tests/test_build_fast_lineage.rs +++ b/crates/sqlbuild-analysis/src/lineage/tests/test_build_fast_lineage.rs @@ -196,34 +196,37 @@ fn given_models_without_compact_facts_when_building_then_matches_python_lineage( expected_detail: Some("Expected 1 statement, found 2"), }, ParsedLineageTestCase { - description: "a parser panic on truncated T-SQL defers only that model", + description: "a parser panic on truncated T-SQL fails as an internal error", sql: "SELECT IF(region > 1, re", dialect: Some("tsql"), inferred_columns: &[], - expected_status: "deferred", + expected_status: "error", expected_lines: &[], expected_has_star: false, - expected_detail: Some("native_failure"), + expected_detail: Some( + "NativeCompilerError: native SQL compilation panicked \ + (native fast lineage of request model 0)", + ), }, ParsedLineageTestCase { - description: "a dialect outside this parser build is deferred", + description: "a dialect outside the old parser build is parsed natively", dialect: Some("mysql"), sql: "SELECT 1", inferred_columns: &[], - expected_status: "deferred", - expected_lines: &[], + expected_status: "built", + expected_lines: &["1 constant high []"], expected_has_star: false, - expected_detail: Some("unsupported_dialect"), + expected_detail: None, }, ParsedLineageTestCase { - description: "an unknown dialect is deferred", + description: "an unknown dialect raises Python's error", dialect: Some("not-a-dialect"), sql: "SELECT 1", inferred_columns: &[], - expected_status: "deferred", + expected_status: "unknown_dialect", expected_lines: &[], expected_has_star: false, - expected_detail: Some("unsupported_dialect"), + expected_detail: Some("not-a-dialect"), }, ]; for test_case in test_cases { diff --git a/crates/sqlbuild-analysis/src/relation_names/_helpers/mod.rs b/crates/sqlbuild-analysis/src/relation_names/_helpers/mod.rs new file mode 100644 index 0000000000..208de6bb67 --- /dev/null +++ b/crates/sqlbuild-analysis/src/relation_names/_helpers/mod.rs @@ -0,0 +1 @@ +pub(crate) mod walk; diff --git a/crates/sqlbuild-analysis/src/relation_names/_helpers/walk.rs b/crates/sqlbuild-analysis/src/relation_names/_helpers/walk.rs new file mode 100644 index 0000000000..e9cea286ab --- /dev/null +++ b/crates/sqlbuild-analysis/src/relation_names/_helpers/walk.rs @@ -0,0 +1,141 @@ +//! Python's dict walk over each parsed statement: tables, CTE names and temporary tables. + +use polyglot_sql::{ComplexityGuardOptions, Dialect, Expression, ParseOptions}; +use serde_json::{Map, Value, json}; +use sqlbuild_core::text::main::active_python_text::active_python_text; +use sqlbuild_core::text::main::python_casefold::python_casefold; +use sqlbuild_core::text::models::PythonText; + +use crate::relation_names::constants::{ + CATALOG_KEY, CREATE_TABLE_KEY, CTE_ALIAS_KEY, CTE_LIST_KEY, GENERIC_DIALECT, + MAX_FUNCTION_CALL_DEPTH, NAME_KEY, QUALIFIER_SEPARATOR, SCHEMA_KEY, TABLE_KEYS, TEMPORARY_KEY, +}; +use crate::relation_names::errors::RelationNamesFailure; +use crate::relation_names::models::{ExtractedRelations, RelationName}; + +/// Python's `extract_relation_names_impl`: None where the wheel's `parse` raises `PolyglotError`. +pub(crate) fn extracted_relations( + sql: &str, + dialect: Option<&str>, +) -> Result, RelationNamesFailure> { + let dialect: &str = dialect + .filter(|name| !name.is_empty()) + .unwrap_or(GENERIC_DIALECT); + let Some(statements) = parsed_statements(sql, dialect)? else { + return Ok(None); + }; + let python: PythonText = active_python_text(); + let mut extracted: ExtractedRelations = ExtractedRelations::default(); + for statement in &statements { + let tree: Value = serde_json::to_value(statement) + .map_err(|error| RelationNamesFailure::Internal(error.to_string()))?; + let nodes: Vec<&Map> = walked(&tree); + let cte_names: Vec = nodes + .iter() + .flat_map(|node| cte_names(python, node)) + .collect(); + extracted + .temporary + .extend(nodes.iter().filter_map(|node| temporary_name(python, node))); + let relations = nodes.iter().filter_map(|node| table_name(node)); + for relation in relations { + let unqualified: bool = relation.schema.is_none() && relation.database.is_none(); + if unqualified && cte_names.contains(&python_casefold(python, &relation.name)) { + continue; + } + if !extracted.relations.contains(&relation) { + extracted.relations.push(relation); + } + } + } + Ok(Some(extracted)) +} + +/// The wheel's guarded `parse`: Ok(None) is the `PolyglotError` Python catches. +fn parsed_statements( + sql: &str, + dialect: &str, +) -> Result>, RelationNamesFailure> { + let parser: Dialect = Dialect::get_by_name(dialect).ok_or_else(|| { + RelationNamesFailure::UnknownDialect(format!("Unknown dialect: {dialect}")) + })?; + let guard: ComplexityGuardOptions = + serde_json::from_value(json!({"maxFunctionCallDepth": MAX_FUNCTION_CALL_DEPTH})) + .map_err(|error| RelationNamesFailure::Internal(error.to_string()))?; + let options: ParseOptions = ParseOptions { + complexity_guard: Some(guard), + }; + match parser.parse_with_options(sql, &options) { + Ok(statements) => Ok(Some(statements)), + Err(_polyglot_error) => Ok(None), + } +} + +/// Python's `_walk`: every object, popping the last pending value first. +fn walked(tree: &Value) -> Vec<&Map> { + let mut nodes: Vec<&Map> = Vec::new(); + let mut pending: Vec<&Value> = vec![tree]; + while let Some(current) = pending.pop() { + match current { + Value::Object(map) => { + nodes.push(map); + pending.extend(map.values()); + } + Value::Array(items) => pending.extend(items.iter()), + _ => {} + } + } + nodes +} + +/// Python's `_identifier`: the `name` string of an object. +fn identifier(value: Option<&Value>) -> Option<&str> { + value?.as_object()?.get(NAME_KEY)?.as_str() +} + +/// Python's `_table_names` for one node. +fn table_name(node: &Map) -> Option { + if !TABLE_KEYS.iter().all(|key| node.contains_key(*key)) { + return None; + } + let name: &str = identifier(node.get(NAME_KEY))?; + let schema: Option<&str> = identifier(node.get(SCHEMA_KEY)); + let database: Option<&str> = identifier(node.get(CATALOG_KEY)); + if schema.is_none() && database.is_none() && name.contains(QUALIFIER_SEPARATOR) { + let parts: Vec<&str> = name.split(QUALIFIER_SEPARATOR).collect(); + return Some(RelationName { + name: parts[parts.len() - 1].to_owned(), + schema: Some(parts[parts.len() - 2].to_owned()), + database: parts + .len() + .checked_sub(3) + .map(|index| parts[index].to_owned()), + }); + } + Some(RelationName { + name: name.to_owned(), + schema: schema.map(str::to_owned), + database: database.map(str::to_owned), + }) +} + +/// Python's `_cte_names` for one node, casefolded. +fn cte_names(python: PythonText, node: &Map) -> Vec { + let Some(Value::Array(ctes)) = node.get(CTE_LIST_KEY) else { + return Vec::new(); + }; + ctes.iter() + .filter_map(|cte| identifier(cte.as_object()?.get(CTE_ALIAS_KEY))) + .map(|alias| python_casefold(python, alias)) + .collect() +} + +/// Python's `_temporary_table_names` for one node, casefolded. +fn temporary_name(python: PythonText, node: &Map) -> Option { + let create: &Map = node.get(CREATE_TABLE_KEY)?.as_object()?; + if create.get(TEMPORARY_KEY) != Some(&Value::Bool(true)) { + return None; + } + let table: &Map = create.get(NAME_KEY)?.as_object()?; + identifier(table.get(NAME_KEY)).map(|name| python_casefold(python, name)) +} diff --git a/crates/sqlbuild-analysis/src/relation_names/constants.rs b/crates/sqlbuild-analysis/src/relation_names/constants.rs new file mode 100644 index 0000000000..f8cab78a94 --- /dev/null +++ b/crates/sqlbuild-analysis/src/relation_names/constants.rs @@ -0,0 +1,15 @@ +//! Payload keys and parse limits Python's relation-name walk reads. + +/// Keys every table payload carries; Python's `_TABLE_KEYS`. +pub(crate) const TABLE_KEYS: [&str; 5] = ["name", "schema", "catalog", "alias", "hints"]; +pub(crate) const NAME_KEY: &str = "name"; +pub(crate) const SCHEMA_KEY: &str = "schema"; +pub(crate) const CATALOG_KEY: &str = "catalog"; +pub(crate) const CTE_LIST_KEY: &str = "ctes"; +pub(crate) const CTE_ALIAS_KEY: &str = "alias"; +pub(crate) const CREATE_TABLE_KEY: &str = "create_table"; +pub(crate) const TEMPORARY_KEY: &str = "temporary"; +pub(crate) const QUALIFIER_SEPARATOR: char = '.'; +pub(crate) const GENERIC_DIALECT: &str = "generic"; +/// The guarded proxy's `maxFunctionCallDepth` for the wheel's `parse`. +pub(crate) const MAX_FUNCTION_CALL_DEPTH: usize = 512; diff --git a/crates/sqlbuild-analysis/src/relation_names/errors.rs b/crates/sqlbuild-analysis/src/relation_names/errors.rs new file mode 100644 index 0000000000..223fa4c588 --- /dev/null +++ b/crates/sqlbuild-analysis/src/relation_names/errors.rs @@ -0,0 +1,8 @@ +//! Why relation-name extraction fails. + +/// The wheel's `ValueError` for an unknown dialect, or an internal native failure. +#[derive(Debug, Clone, PartialEq, Eq)] +pub enum RelationNamesFailure { + UnknownDialect(String), + Internal(String), +} diff --git a/crates/sqlbuild-analysis/src/relation_names/main/extract_relation_names.rs b/crates/sqlbuild-analysis/src/relation_names/main/extract_relation_names.rs new file mode 100644 index 0000000000..54c5de8840 --- /dev/null +++ b/crates/sqlbuild-analysis/src/relation_names/main/extract_relation_names.rs @@ -0,0 +1,13 @@ +//! Python's `extract_relation_names_impl`. + +use crate::relation_names::_helpers::walk::extracted_relations; +use crate::relation_names::errors::RelationNamesFailure; +use crate::relation_names::models::ExtractedRelations; + +/// Relations `sql` names and temporary tables it creates; None where the parse fails. +pub fn extract_relation_names( + sql: &str, + dialect: Option<&str>, +) -> Result, RelationNamesFailure> { + extracted_relations(sql, dialect) +} diff --git a/crates/sqlbuild-analysis/src/relation_names/main/mod.rs b/crates/sqlbuild-analysis/src/relation_names/main/mod.rs new file mode 100644 index 0000000000..13e389d148 --- /dev/null +++ b/crates/sqlbuild-analysis/src/relation_names/main/mod.rs @@ -0,0 +1 @@ +pub mod extract_relation_names; diff --git a/crates/sqlbuild-analysis/src/relation_names/mod.rs b/crates/sqlbuild-analysis/src/relation_names/mod.rs new file mode 100644 index 0000000000..42fadd7136 --- /dev/null +++ b/crates/sqlbuild-analysis/src/relation_names/mod.rs @@ -0,0 +1,7 @@ +//! Python's hard-coded relation-name extraction over the parsed statements' dict walk. + +pub(crate) mod _helpers; +mod constants; +pub mod errors; +pub mod main; +pub mod models; diff --git a/crates/sqlbuild-analysis/src/relation_names/models.rs b/crates/sqlbuild-analysis/src/relation_names/models.rs new file mode 100644 index 0000000000..e778893775 --- /dev/null +++ b/crates/sqlbuild-analysis/src/relation_names/models.rs @@ -0,0 +1,16 @@ +//! Relations named in SQL, as Python's `RelationName` holds them. + +/// One relation a statement names, with the qualifiers it spells. +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct RelationName { + pub name: String, + pub schema: Option, + pub database: Option, +} + +/// Relations in first-seen order and the casefolded temporary tables the SQL creates. +#[derive(Debug, Clone, Default, PartialEq, Eq)] +pub struct ExtractedRelations { + pub relations: Vec, + pub temporary: Vec, +} diff --git a/crates/sqlbuild-analysis/src/semantic_checks/_helpers/explanation/columns.rs b/crates/sqlbuild-analysis/src/semantic_checks/_helpers/explanation/columns.rs index 8a242d2165..7c5278a784 100644 --- a/crates/sqlbuild-analysis/src/semantic_checks/_helpers/explanation/columns.rs +++ b/crates/sqlbuild-analysis/src/semantic_checks/_helpers/explanation/columns.rs @@ -2,14 +2,14 @@ use std::cmp::Ordering; -use crate::semantic_checks::_helpers::sql_text::text::{ascii, casefold}; +use crate::semantic_checks::_helpers::sql_text::text::casefold; use crate::semantic_checks::constants::{MAX_EDIT_DISTANCE, MIN_ABBREVIATION_LENGTH}; -use crate::semantic_checks::models::SemanticDeferral; +use crate::semantic_checks::models::SemanticFailure; /// Python's `column_distance`: Levenshtein distance between case-folded names. pub(crate) fn column_distance(left: &str, right: &str) -> usize { - let left: Vec = casefold(left).into_bytes(); - let right: Vec = casefold(right).into_bytes(); + let left: Vec = casefold(left).chars().collect(); + let right: Vec = casefold(right).chars().collect(); let mut row: Vec = (0..=right.len()).collect(); for (i, a) in left.iter().enumerate() { let mut following: Vec = Vec::with_capacity(right.len() + 1); @@ -31,12 +31,11 @@ pub(crate) fn column_distance(left: &str, right: &str) -> usize { pub(crate) fn ordered_columns<'a>( name: &str, columns: &'a [(String, String)], -) -> Result, SemanticDeferral> { - ascii(name)?; +) -> Result, SemanticFailure> { + let name_length: usize = name.chars().count(); let mut keyed: Vec<(f64, &'a str)> = Vec::with_capacity(columns.len()); for (column, _) in columns { - ascii(column)?; - let longest = name.len().max(column.len()).max(1); + let longest = name_length.max(column.chars().count()).max(1); keyed.push(( column_distance(name, column) as f64 / longest as f64, column.as_str(), @@ -55,15 +54,17 @@ pub(crate) fn ordered_columns<'a>( pub(crate) fn closest_column<'a>( name: &str, columns: &'a [(String, String)], -) -> Result, SemanticDeferral> { - let folded_name: String = casefold(name); +) -> Result, SemanticFailure> { + let folded_name: Vec = casefold(name).chars().collect(); + let name_first: String = folded_end(name, str::chars); + let name_last: String = folded_end(name, |text| text.chars().rev()); for candidate in ordered_columns(name, columns)? { let distance = column_distance(name, candidate); - let folded_candidate: String = casefold(candidate); - let abbreviation = name.len() >= MIN_ABBREVIATION_LENGTH - && folded_candidate.as_bytes().first() == folded_name.as_bytes().first() - && folded_candidate.as_bytes().last() == folded_name.as_bytes().last() - && is_subsequence(folded_name.as_bytes(), folded_candidate.as_bytes()); + let folded_candidate: Vec = casefold(candidate).chars().collect(); + let abbreviation = name.chars().count() >= MIN_ABBREVIATION_LENGTH + && folded_end(candidate, str::chars) == name_first + && folded_end(candidate, |text| text.chars().rev()) == name_last + && is_subsequence(&folded_name, &folded_candidate); if distance <= MAX_EDIT_DISTANCE || abbreviation { return Ok(Some(candidate)); } @@ -71,8 +72,18 @@ pub(crate) fn closest_column<'a>( Ok(None) } +/// Python's `text[:1].casefold()` or `text[-1:].casefold()`, by the end `characters` reads first. +fn folded_end<'t, I: Iterator>( + text: &'t str, + characters: impl Fn(&'t str) -> I, +) -> String { + characters(text) + .next() + .map_or_else(String::new, |character| casefold(&character.to_string())) +} + /// Python's `all(character in remaining for character in name)` over one shared iterator. -fn is_subsequence(name: &[u8], candidate: &[u8]) -> bool { +fn is_subsequence(name: &[char], candidate: &[char]) -> bool { let mut position: usize = 0; for character in name { match candidate[position..] diff --git a/crates/sqlbuild-analysis/src/semantic_checks/_helpers/explanation/completion.rs b/crates/sqlbuild-analysis/src/semantic_checks/_helpers/explanation/completion.rs index 2c08a9399c..5183917553 100644 --- a/crates/sqlbuild-analysis/src/semantic_checks/_helpers/explanation/completion.rs +++ b/crates/sqlbuild-analysis/src/semantic_checks/_helpers/explanation/completion.rs @@ -19,25 +19,22 @@ use crate::semantic_checks::_helpers::recovery::poison::Poison; use crate::semantic_checks::_helpers::sql_text::parsed_sql::{ ParsedModelFacts, parsed_model_facts, }; -use crate::semantic_checks::_helpers::sql_text::text::{LineIndex, ascii, plain_text}; +use crate::semantic_checks::_helpers::sql_text::text::LineIndex; use crate::semantic_checks::constants::{ MODEL_RESOURCE_TYPE, SEMANTIC_CODE_PREFIX, SQL_TEST_COLUMN_CODE, SQL_TEST_COLUMN_PATTERN, UNKNOWN_COLUMN_CODE, }; use crate::semantic_checks::models::{ CompletedDiagnostic, CompletionModel, CompletionOutcome, CompletionRequest, FinalDiagnostic, - LineageOutput, SemanticDeferral, SemanticDiagnostic, + LineageOutput, SemanticDiagnostic, SemanticFailure, }; static SQL_TEST_COLUMN: LazyLock> = LazyLock::new(|| compiled(SQL_TEST_COLUMN_PATTERN)); -/// Complete recovery, explanation and opt-out rejection, or defer all three to Python. -pub(crate) fn complete(request: &CompletionRequest) -> CompletionOutcome { - match completed(request) { - Ok(outcome) => outcome, - Err(deferral) => CompletionOutcome::Deferred(deferral), - } +/// Complete recovery, explanation and opt-out rejection. +pub(crate) fn complete(request: &CompletionRequest) -> Result { + completed(request) } /// The request with its shapes and models indexed, and the parsed facts of failing models. @@ -49,7 +46,7 @@ struct Completion<'a> { } impl<'a> Completion<'a> { - fn new(request: &'a CompletionRequest) -> Result { + fn new(request: &'a CompletionRequest) -> Result { let models: HashMap<&'a str, usize> = request .models .iter() @@ -95,14 +92,14 @@ impl<'a> Completion<'a> { .map(|index| (*index, &self.request.models[*index])) } - fn facts(&self, index: usize) -> Result<&ParsedModelFacts, SemanticDeferral> { + fn facts(&self, index: usize) -> Result<&ParsedModelFacts, SemanticFailure> { self.parsed .get(&index) - .ok_or(SemanticDeferral::NativeFailure) + .ok_or_else(|| SemanticFailure::internal("a failing model without parsed facts")) } } -fn completed(request: &CompletionRequest) -> Result { +fn completed(request: &CompletionRequest) -> Result { let completion = Completion::new(request)?; let initial: Vec = request .diagnostics @@ -142,7 +139,7 @@ fn completed(request: &CompletionRequest) -> Result b fn recovered_output( completion: &Completion<'_>, diagnostic: &CompletedDiagnostic, -) -> Result, SemanticDeferral> { +) -> Result, SemanticFailure> { let Some((index, model)) = completion.model(diagnostic) else { return Ok(None); }; @@ -237,7 +234,7 @@ fn recovered_output( fn recover( completion: &Completion<'_>, diagnostics: Vec, -) -> Result>, SemanticDeferral> { +) -> Result>, SemanticFailure> { let mut poisoned = Poison::default(); let mut origins: HashMap = HashMap::new(); let mut has_roots = false; @@ -300,10 +297,7 @@ fn recover( } /// The `(table, column)` use a diagnostic reports, which a poisoned output may explain. -fn recovery_target( - code: &str, - message: &str, -) -> Result, SemanticDeferral> { +fn recovery_target(code: &str, message: &str) -> Result, SemanticFailure> { let mut target: Option<(String, String)> = None; if code == UNKNOWN_COLUMN_CODE && let Some((column, Some(table))) = missing_column(message)? @@ -311,7 +305,7 @@ fn recovery_target( target = Some((table, column)); } if code == SQL_TEST_COLUMN_CODE - && let Some(captures) = pattern(&SQL_TEST_COLUMN)?.captures(ascii(message)?) + && let Some(captures) = pattern(&SQL_TEST_COLUMN)?.captures(message) { target = Some((captures[1].to_owned(), captures[2].to_owned())); } @@ -322,14 +316,14 @@ fn recovery_target( fn explain( completion: &Completion<'_>, diagnostics: Vec, -) -> Result, SemanticDeferral> { +) -> Result, SemanticFailure> { let mut binaries: HashMap> = HashMap::new(); let mut explained: Vec = Vec::with_capacity(diagnostics.len()); for diagnostic in diagnostics { let code: &str = &completion.source(&diagnostic).code; match completion.model(&diagnostic) { Some((index, model)) if is_explained_code(code) => { - let authored_sql: &str = plain_text(&model.authored_sql)?; + let authored_sql: &str = &model.authored_sql; if is_type_code(code) && !binaries.contains_key(&index) { binaries.insert(index, binary_index(authored_sql)?); } @@ -360,7 +354,7 @@ fn explain( fn with_semantic_help( diagnostic: CompletedDiagnostic, code: &str, -) -> Result { +) -> Result { let Some(help) = semantic_help(code) else { return Ok(diagnostic); }; @@ -394,7 +388,7 @@ fn hidden_by_opt_out(source: &SemanticDiagnostic, rejected: &BTreeMap<&str, usiz fn reject_opt_outs( completion: &Completion<'_>, diagnostics: &[CompletedDiagnostic], -) -> Result, SemanticDeferral> { +) -> Result, SemanticFailure> { let mut rejected: BTreeMap<&str, usize> = BTreeMap::new(); for (index, model) in completion.request.models.iter().enumerate() { if model.rejected_opt_out_file.is_some() { diff --git a/crates/sqlbuild-analysis/src/semantic_checks/_helpers/explanation/explain.rs b/crates/sqlbuild-analysis/src/semantic_checks/_helpers/explanation/explain.rs index f6d3eaa26d..e69f3ffa2a 100644 --- a/crates/sqlbuild-analysis/src/semantic_checks/_helpers/explanation/explain.rs +++ b/crates/sqlbuild-analysis/src/semantic_checks/_helpers/explanation/explain.rs @@ -7,31 +7,48 @@ use regex::Regex; use crate::semantic_checks::_helpers::explanation::columns::{closest_column, ordered_columns}; use crate::semantic_checks::_helpers::explanation::messages::{ - comparison_help, compiled, missing_column, pattern, semantic_help, sentence_message, type_words, + comparison_help, missing_column, pattern, semantic_help, sentence_message, type_words, }; +use crate::semantic_checks::_helpers::sql_text::python_regex::{ignorecase_word, python_regex}; use crate::semantic_checks::_helpers::sql_text::text::{ - LineIndex, ascii, last_newline_before, newlines_before, prefix, + LineIndex, byte_offset, code_point_offset, last_newline_before, newlines_before, prefix, upper, }; use crate::semantic_checks::constants::{ COMPARISON_CODE, DECIMAL_OPERAND_PATTERN, DISPLAY_LIMIT, INTEGER_OPERAND_PATTERN, OPERAND_PATTERN, QUALIFIER_PATTERN, TEMPORAL_OPERAND_PATTERN, TYPE_CODES, UNKNOWN_COLUMN_CODE, }; -use crate::semantic_checks::models::{CompletedDiagnostic, SemanticDeferral, SemanticLocation}; +use crate::semantic_checks::models::{CompletedDiagnostic, SemanticFailure, SemanticLocation}; -static QUALIFIER: LazyLock> = LazyLock::new(|| compiled(QUALIFIER_PATTERN)); +/// A diagnostic located past the model's authored lines, where Python raised `IndexError`. +const OUTSIDE_AUTHORED_LINES: &str = "a diagnostic line outside the model's authored SQL"; + +static QUALIFIER: LazyLock> = + LazyLock::new(|| python_regex(QUALIFIER_PATTERN)); static BINARY: LazyLock> = LazyLock::new(|| { - compiled(&format!( - r"(?i)(?P{OPERAND_PATTERN})\s*(?:>=|<=|<>|!=|=|>|<|\+|\*|/|-)\s*(?P{OPERAND_PATTERN})" + let operand: String = operand_template(); + python_regex(&format!( + r"(?P{operand}){{S}}*(?:>=|<=|<>|!=|=|>|<|\+|\*|/|-){{S}}*(?P{operand})" )) }); static OPERAND_AT: LazyLock> = - LazyLock::new(|| compiled(&format!(r"(?i)\A{OPERAND_PATTERN}"))); + LazyLock::new(|| python_regex(&format!(r"\A{}", operand_template()))); static TEMPORAL_OPERAND: LazyLock> = - LazyLock::new(|| compiled(TEMPORAL_OPERAND_PATTERN)); + LazyLock::new(|| python_regex(&temporal_words(TEMPORAL_OPERAND_PATTERN))); static INTEGER_OPERAND: LazyLock> = - LazyLock::new(|| compiled(INTEGER_OPERAND_PATTERN)); + LazyLock::new(|| python_regex(INTEGER_OPERAND_PATTERN)); static DECIMAL_OPERAND: LazyLock> = - LazyLock::new(|| compiled(DECIMAL_OPERAND_PATTERN)); + LazyLock::new(|| python_regex(DECIMAL_OPERAND_PATTERN)); + +/// `TIMESTAMP` and `DATE` in a template, as Python's `re.IGNORECASE` matches them. +fn temporal_words(template: &str) -> String { + template + .replace("{TIMESTAMP}", &ignorecase_word("TIMESTAMP")) + .replace("{DATE}", &ignorecase_word("DATE")) +} + +fn operand_template() -> String { + temporal_words(OPERAND_PATTERN) +} /// Closed relation shapes by name, each in Python's dict order. pub(crate) type Shapes<'a> = HashMap<&'a str, &'a [(String, String)]>; @@ -50,13 +67,16 @@ pub(crate) struct Binary { } /// Python's `_binary_index`: every binary operation in authored SQL, in order. -pub(crate) fn binary_index(sql: &str) -> Result, SemanticDeferral> { +pub(crate) fn binary_index(sql: &str) -> Result, SemanticFailure> { let binary: &Regex = pattern(&BINARY)?; let mut found: Vec = Vec::new(); for captures in binary.captures_iter(sql) { - let (start, end) = captures - .get(0) - .map_or((0, 0), |item| (item.start(), item.end())); + let (start, end) = captures.get(0).map_or((0, 0), |item| { + ( + code_point_offset(sql, item.start()), + code_point_offset(sql, item.end()), + ) + }); found.push(Binary { start, end, @@ -87,7 +107,7 @@ pub(crate) struct ExplainContext<'a> { pub(crate) fn explain_model( diagnostic: &CompletedDiagnostic, context: &ExplainContext<'_>, -) -> Result { +) -> Result { let ExplainContext { code, model, @@ -203,8 +223,8 @@ fn position(offset: usize) -> i64 { i64::try_from(offset).unwrap_or(i64::MAX) } -/// Python's `lines[line - 1]`, including its negative indexing; out of range is not reproduced. -fn python_line<'a>(lines: &'a LineIndex<'a>, line: i64) -> Result<&'a str, SemanticDeferral> { +/// Python's `lines[line - 1]`, including its negative indexing; out of range is internal. +fn python_line<'a>(lines: &'a LineIndex<'a>, line: i64) -> Result<&'a str, SemanticFailure> { let count: i64 = i64::try_from(lines.lines.len()).unwrap_or(i64::MAX); let index: i64 = if line - 1 < 0 { line - 1 + count @@ -216,13 +236,13 @@ fn python_line<'a>(lines: &'a LineIndex<'a>, line: i64) -> Result<&'a str, Seman .lines .get(index) .copied() - .ok_or(SemanticDeferral::UnexpectedPosition), - Err(_) => Err(SemanticDeferral::UnexpectedPosition), + .ok_or_else(|| SemanticFailure::internal(OUTSIDE_AUTHORED_LINES)), + Err(_) => Err(SemanticFailure::internal(OUTSIDE_AUTHORED_LINES)), } } /// The alias qualifying the column that ends `prefix`, with doubled quotes undone. -fn qualifier(prefix: &str) -> Result, SemanticDeferral> { +fn qualifier(prefix: &str) -> Result, SemanticFailure> { let Some(captures) = pattern(&QUALIFIER)?.captures(prefix) else { return Ok(None); }; @@ -242,12 +262,14 @@ fn binary_at(binaries: &[Binary], offset: i64) -> Option<&Binary> { } /// Python's `re.compile(_OPERAND, re.IGNORECASE).match(sql, offset)`. -fn operand_at(sql: &str, offset: i64) -> Result, SemanticDeferral> { +fn operand_at(sql: &str, offset: i64) -> Result, SemanticFailure> { let operand: &Regex = pattern(&OPERAND_AT)?; let start: usize = usize::try_from(offset.max(0)).unwrap_or(usize::MAX); - Ok(sql - .get(start..) - .and_then(|rest| operand.find(rest)) + if start > sql.chars().count() { + return Ok(None); + } + Ok(operand + .find(&sql[byte_offset(sql, start)..]) .map(|found| found.as_str())) } @@ -256,9 +278,9 @@ fn operand_type( text: &str, aliases: &HashMap, shapes: &Shapes<'_>, -) -> Result, SemanticDeferral> { +) -> Result, SemanticFailure> { if let Some(captures) = pattern(&TEMPORAL_OPERAND)?.captures(text) { - return Ok(Some(captures[1].to_ascii_uppercase())); + return Ok(Some(upper(&captures[1]))); } if pattern(&INTEGER_OPERAND)?.is_match(text) { return Ok(Some("INTEGER".to_owned())); @@ -273,7 +295,7 @@ fn operand_type( let table: &str = aliases.get(alias).map_or(alias, String::as_str); let value = shape_type(shapes, table, column); return match value { - Some(value) if !value.is_empty() => Ok(Some(ascii(value)?.to_ascii_uppercase())), + Some(value) if !value.is_empty() => Ok(Some(upper(value))), _ => Ok(None), }; } @@ -281,7 +303,7 @@ fn operand_type( let mut candidates: HashSet = HashSet::new(); for table in tables { if let Some(value) = shape_type(shapes, table, text) { - candidates.insert(ascii(value)?.to_ascii_uppercase()); + candidates.insert(upper(value)); } } Ok(if candidates.len() == 1 { diff --git a/crates/sqlbuild-analysis/src/semantic_checks/_helpers/explanation/messages.rs b/crates/sqlbuild-analysis/src/semantic_checks/_helpers/explanation/messages.rs index 7cb0732827..74e41888a0 100644 --- a/crates/sqlbuild-analysis/src/semantic_checks/_helpers/explanation/messages.rs +++ b/crates/sqlbuild-analysis/src/semantic_checks/_helpers/explanation/messages.rs @@ -2,19 +2,21 @@ use std::sync::LazyLock; -use regex::{Captures, Regex}; +use regex::Regex; +use sqlbuild_core::text::main::active_python_text::active_python_text; +use sqlbuild_core::text::main::is_python_word::is_python_word; -use crate::semantic_checks::_helpers::sql_text::text::ascii; +use crate::semantic_checks::_helpers::sql_text::python_regex::ignorecase_equal; +use crate::semantic_checks::_helpers::sql_text::text::upper; use crate::semantic_checks::constants::{ BIGQUERY_DIALECT, COMPARISON_CODE, CONTEXT_SUFFIX_PATTERN, DATE_TYPE, MISSING_PATTERN, - QUOTED_PIECE_PATTERN, SEMANTIC_HELP, TIMESTAMP_TYPE, TYPE_WORDS_PATTERN, + QUOTED_PIECE_PATTERN, SEMANTIC_HELP, TIMESTAMP_TYPE, TYPE_WORDS, }; -use crate::semantic_checks::models::SemanticDeferral; +use crate::semantic_checks::models::SemanticFailure; -static TYPE_WORDS: LazyLock> = LazyLock::new(|| compiled(TYPE_WORDS_PATTERN)); static MISSING: LazyLock> = LazyLock::new(|| compiled(MISSING_PATTERN)); static CONTEXT_SUFFIX: LazyLock> = - LazyLock::new(|| compiled(CONTEXT_SUFFIX_PATTERN)); + LazyLock::new(|| compiled(&format!(r"{CONTEXT_SUFFIX_PATTERN}\z"))); static QUOTED_PIECE: LazyLock> = LazyLock::new(|| compiled(QUOTED_PIECE_PATTERN)); @@ -23,21 +25,13 @@ pub(crate) fn compiled(pattern: &str) -> Result { Regex::new(pattern).map_err(|error| error.to_string()) } -/// A compiled constant pattern, or a native-failure deferral if it did not compile. +/// A compiled constant pattern, or an internal failure if it did not compile. pub(crate) fn pattern( compiled: &'static Result, -) -> Result<&'static Regex, SemanticDeferral> { +) -> Result<&'static Regex, SemanticFailure> { compiled .as_ref() - .map_err(|_| SemanticDeferral::NativeFailure) -} - -/// A message Python's regexes read the same way, or a deferral. -fn message_text(message: &str) -> Result<&str, SemanticDeferral> { - if message.contains('\n') { - return Err(SemanticDeferral::NonAsciiText); - } - ascii(message) + .map_err(|_| SemanticFailure::internal("a constant pattern does not compile")) } /// Python's `semantic_help`. @@ -48,47 +42,108 @@ pub(crate) fn semantic_help(code: &str) -> Option<&'static str> { .map(|(_, help)| *help) } -/// Python's `sentence_message`: drop the context suffix and upper-case unquoted type words. -pub(crate) fn sentence_message(message: &str) -> Result { +/// Python's `re.sub(r" \(context: [^)]*\)$", "", message)`. +fn without_context_suffix(message: &str) -> Result { let suffix: &Regex = pattern(&CONTEXT_SUFFIX)?; + let (body, newline) = match message.strip_suffix('\n') { + Some(body) => (body, "\n"), + None => (message, ""), + }; + Ok(format!("{}{newline}", suffix.replace(body, ""))) +} + +/// Python's `sentence_message`: drop the context suffix and upper-case unquoted type words. +pub(crate) fn sentence_message(message: &str) -> Result { let quoted: &Regex = pattern("ED_PIECE)?; - let words: &Regex = pattern(&TYPE_WORDS)?; - let text = suffix.replace(message_text(message)?, ""); + let text: String = without_context_suffix(message)?; let mut sentence = String::with_capacity(text.len()); let mut last: usize = 0; for piece in quoted.find_iter(&text) { - sentence.push_str(&upper_type_words(words, &text[last..piece.start()])); + sentence.push_str(&upper_type_words(&text[last..piece.start()])); sentence.push_str(piece.as_str()); last = piece.end(); } - sentence.push_str(&upper_type_words(words, &text[last..])); + sentence.push_str(&upper_type_words(&text[last..])); Ok(sentence) } -fn upper_type_words(words: &Regex, text: &str) -> String { - words.replace_all(text, upper_match).into_owned() +fn upper_type_words(text: &str) -> String { + let characters: Vec = text.chars().collect(); + let mut result = String::with_capacity(text.len()); + let mut last: usize = 0; + for (start, end) in type_word_spans(&characters) { + result.extend(&characters[last..start]); + result.push_str(&upper(&characters[start..end].iter().collect::())); + last = end; + } + result.extend(&characters[last..]); + result +} + +/// The end of the first type word at `start` that also ends on a word boundary. +fn type_word_end( + characters: &[char], + start: usize, + boundary: &impl Fn(usize) -> bool, +) -> Option { + for candidate in TYPE_WORDS { + let end: usize = start + candidate.len(); + if let Some(slice) = characters.get(start..end) + && slice + .iter() + .zip(candidate.chars()) + .all(|(character, letter)| ignorecase_equal(*character, letter)) + && boundary(end) + { + return Some(end); + } + } + None } -fn upper_match(captures: &Captures<'_>) -> String { - captures[0].to_ascii_uppercase() +/// Python's `re.finditer(_TYPE_WORDS, text, re.IGNORECASE)` spans, in code points. +fn type_word_spans(characters: &[char]) -> Vec<(usize, usize)> { + let python = active_python_text(); + let word = |index: usize| { + characters + .get(index) + .is_some_and(|character| is_python_word(python, *character)) + }; + let boundary = |index: usize| (index > 0 && word(index - 1)) != word(index); + let mut spans: Vec<(usize, usize)> = Vec::new(); + let mut start: usize = 0; + while start < characters.len() { + let found: Option = if boundary(start) { + type_word_end(characters, start, &boundary) + } else { + None + }; + match found { + Some(end) => { + spans.push((start, end)); + start = end; + } + None => start += 1, + } + } + spans } /// Python's `re.findall(_TYPE_WORDS, message, re.IGNORECASE)` upper-cased. -pub(crate) fn type_words(message: &str) -> Result, SemanticDeferral> { - let words: &Regex = pattern(&TYPE_WORDS)?; - let mut found: Vec = Vec::new(); - for captures in words.captures_iter(message_text(message)?) { - found.push(captures[1].to_ascii_uppercase()); - } - Ok(found) +pub(crate) fn type_words(message: &str) -> Result, SemanticFailure> { + let characters: Vec = message.chars().collect(); + Ok(type_word_spans(&characters) + .into_iter() + .map(|(start, end)| upper(&characters[start..end].iter().collect::())) + .collect()) } /// Python's `missing_column`: the unknown column and its table, if the message names one. pub(crate) fn missing_column( message: &str, -) -> Result)>, SemanticDeferral> { +) -> Result)>, SemanticFailure> { let missing: &Regex = pattern(&MISSING)?; - let Some(captures) = missing.captures(message_text(message)?) else { + let Some(captures) = missing.captures(message) else { return Ok(None); }; let table: Option = captures.get(2).map(|table| table.as_str().to_owned()); diff --git a/crates/sqlbuild-analysis/src/semantic_checks/_helpers/explanation/opt_outs.rs b/crates/sqlbuild-analysis/src/semantic_checks/_helpers/explanation/opt_outs.rs index 23a2ad7384..fef4cdbd5d 100644 --- a/crates/sqlbuild-analysis/src/semantic_checks/_helpers/explanation/opt_outs.rs +++ b/crates/sqlbuild-analysis/src/semantic_checks/_helpers/explanation/opt_outs.rs @@ -9,7 +9,7 @@ use crate::semantic_checks::constants::{ ADDITIONAL_HELP_SEPARATOR, FINDING_KINDS, PROJECT_CONFIG_FILENAME, REQUIRE_SQL_ANALYSIS_KEY, SETTING_SNIPPET_INDENT, SETTINGS_SECTION, }; -use crate::semantic_checks::models::{OptOutDiagnostic, SemanticDeferral}; +use crate::semantic_checks::models::{OptOutDiagnostic, SemanticFailure}; static FINDING_PATTERNS: LazyLock> = LazyLock::new(|| { let alternatives: Vec = FINDING_KINDS @@ -25,7 +25,7 @@ pub(crate) fn opt_out_diagnostic( name: &str, location_file: Option<&str>, hidden_codes: &[&str], -) -> Result { +) -> Result { let findings: String = finding_counts(pattern(&FINDING_PATTERNS)?, hidden_codes); let opt_out: &str = if location_file == Some(PROJECT_CONFIG_FILENAME) { "`sql_analysis = false` from this [path_defaults] entry" diff --git a/crates/sqlbuild-analysis/src/semantic_checks/_helpers/metadata_checks/argument_types.rs b/crates/sqlbuild-analysis/src/semantic_checks/_helpers/metadata_checks/argument_types.rs index affd4eb433..deec9ab0f8 100644 --- a/crates/sqlbuild-analysis/src/semantic_checks/_helpers/metadata_checks/argument_types.rs +++ b/crates/sqlbuild-analysis/src/semantic_checks/_helpers/metadata_checks/argument_types.rs @@ -5,23 +5,23 @@ use std::collections::HashMap; use polyglot_sql::{DataType, Expression}; use serde_json::Value; -use crate::semantic_checks::_helpers::sql_text::text::ascii; +use crate::semantic_checks::_helpers::sql_text::text::upper; use crate::semantic_checks::constants::{ BOOLEAN_RESULT_KINDS, BOOLEAN_TYPE_NAME, COLUMN_KIND, CUSTOM_TYPE_NAME, DECIMAL_TYPE_NAME, KNOWN_CAST_TYPE_NAMES, TIMESTAMP_KIND, TIMESTAMP_WITH_TIME_ZONE_TYPE_NAME, VARCHAR_DATA_TYPES, }; -use crate::semantic_checks::models::SemanticDeferral; +use crate::semantic_checks::models::SemanticFailure; /// The type Python infers for `expression`, or None. pub(crate) fn expression_type( expression: &Expression, return_types: &HashMap, -) -> Result, SemanticDeferral> { +) -> Result, SemanticFailure> { let kind: &str = expression.variant_name(); let name: &str = expression.get_name(); let function_name: &str = if name.is_empty() { kind } else { name }; if kind != COLUMN_KIND - && let Some(declared) = return_types.get(&ascii(function_name)?.to_ascii_uppercase()) + && let Some(declared) = return_types.get(&upper(function_name)) { return Ok(Some(declared.clone())); } @@ -35,9 +35,9 @@ pub(crate) fn expression_type( } /// Python's reading of a cast's serialised `to` payload. -fn cast_type(data_type: &DataType) -> Result, SemanticDeferral> { - let target: Value = - serde_json::to_value(data_type).map_err(|_| SemanticDeferral::NativeFailure)?; +fn cast_type(data_type: &DataType) -> Result, SemanticFailure> { + let target: Value = serde_json::to_value(data_type) + .map_err(|_| SemanticFailure::internal("a cast type does not serialize"))?; let Some(raw_type) = target .get("data_type") .and_then(Value::as_str) @@ -45,7 +45,6 @@ fn cast_type(data_type: &DataType) -> Result, SemanticDeferral> { else { return Ok(None); }; - let raw_type: &str = ascii(raw_type)?; let custom_name: Option<&str> = target .get("name") .and_then(Value::as_str) @@ -53,7 +52,7 @@ fn cast_type(data_type: &DataType) -> Result, SemanticDeferral> { if raw_type.eq_ignore_ascii_case(CUSTOM_TYPE_NAME) && let Some(name) = custom_name { - return Ok(Some(ascii(name)?.to_ascii_uppercase())); + return Ok(Some(upper(name))); } let lowered: String = raw_type.to_ascii_lowercase(); if lowered == TIMESTAMP_KIND && target.get("timezone") == Some(&Value::Bool(true)) { diff --git a/crates/sqlbuild-analysis/src/semantic_checks/_helpers/metadata_checks/checks.rs b/crates/sqlbuild-analysis/src/semantic_checks/_helpers/metadata_checks/checks.rs index b299cb02b6..759ba69c99 100644 --- a/crates/sqlbuild-analysis/src/semantic_checks/_helpers/metadata_checks/checks.rs +++ b/crates/sqlbuild-analysis/src/semantic_checks/_helpers/metadata_checks/checks.rs @@ -13,14 +13,14 @@ use crate::semantic_checks::_helpers::metadata_checks::function_calls::{ use crate::semantic_checks::_helpers::metadata_checks::positions::{ find_code_point, text_position, }; -use crate::semantic_checks::_helpers::sql_text::text::{ascii, casefold}; +use crate::semantic_checks::_helpers::sql_text::text::casefold; use crate::semantic_checks::constants::{ CURSOR_INPUTS_KEY, SQL_TEST_COLUMN_CODE, SQL_TEST_CTE_PATTERN, TYPE_MISMATCH_CODE, UNKNOWN_COLUMN_REFERENCE_CODE, UNKNOWN_TYPE, }; use crate::semantic_checks::models::{ MetadataFinding, MetadataFunction, MetadataModel, MetadataOutcome, MetadataRequest, - MetadataSource, MetadataSqlTest, ModelMetadataFindings, SemanticDeferral, + MetadataSource, MetadataSqlTest, ModelMetadataFindings, SemanticFailure, }; use crate::type_system::models::TypeFamily; @@ -38,10 +38,10 @@ type Shapes<'a> = HashMap<&'a str, &'a [(String, String)]>; /// One config reference: `(key, column name, the shape it must name a column of)`. type Reference<'a> = (String, &'a str, &'a [(String, String)]); -/// The metadata errors of every model, source and SQL test, or a deferral. +/// The metadata errors of every model, source and SQL test, or the error Python raised. pub(crate) fn check_metadata( request: &MetadataRequest, -) -> Result { +) -> Result { let shapes: Shapes<'_> = request .shapes .iter() @@ -78,7 +78,7 @@ pub(crate) fn check_metadata( fn model_errors( model: &MetadataModel, context: &FunctionContext<'_>, -) -> Result { +) -> Result { if !model.checked { return Ok(ModelMetadataFindings::default()); } @@ -102,7 +102,7 @@ fn model_error( code: &'static str, name: &str, message: String, -) -> Result { +) -> Result { let (line, column) = text_position(&model.authored_sql, name, 0)?; Ok(MetadataFinding { code, @@ -113,10 +113,10 @@ fn model_error( } /// Python's `{column.casefold() for column in shape}`. -fn folded_names(shape: &[(String, String)]) -> Result, SemanticDeferral> { +fn folded_names(shape: &[(String, String)]) -> Result, SemanticFailure> { let mut names: HashSet = HashSet::with_capacity(shape.len()); for (name, _) in shape { - names.insert(casefold(ascii(name)?)); + names.insert(casefold(name)); } Ok(names) } @@ -126,7 +126,7 @@ fn reference_errors( model: &MetadataModel, shape: &[(String, String)], context: &FunctionContext<'_>, -) -> Result, SemanticDeferral> { +) -> Result, SemanticFailure> { let mut references: Vec> = Vec::new(); for (key, names) in &model.references { for name in names { @@ -146,7 +146,7 @@ fn reference_errors( } let mut errors: Vec = Vec::new(); for (key, name, reference_shape) in references { - if !folded_names(reference_shape)?.contains(&casefold(ascii(name)?)) { + if !folded_names(reference_shape)?.contains(&casefold(name)) { let message = format!("{key} references unknown column '{name}'"); errors.push(model_error( model, @@ -167,20 +167,20 @@ fn cursor_error( model: &MetadataModel, shape: &[(String, String)], families: &Families, -) -> Result, SemanticDeferral> { +) -> Result, SemanticFailure> { let (Some(cursor), Some(cursor_type)) = (model.cursor.as_deref(), model.cursor_type.as_deref()) else { return Ok(None); }; - let folded_cursor: String = casefold(ascii(cursor)?); + let folded_cursor: String = casefold(cursor); let mut actual: &str = UNKNOWN_TYPE; for (name, column_type) in shape { - if casefold(ascii(name)?) == folded_cursor { + if casefold(name) == folded_cursor { actual = column_type; break; } } - let allowed: &[TypeFamily] = match ascii(cursor_type)?.to_ascii_lowercase().as_str() { + let allowed: &[TypeFamily] = match cursor_type.to_ascii_lowercase().as_str() { "integer" => INTEGER_CURSOR_FAMILIES, "timestamp" | "date" => TEMPORAL_CURSOR_FAMILIES, _ => return Ok(None), @@ -203,14 +203,14 @@ fn cursor_error( fn source_errors( sources: &[MetadataSource], shapes: &Shapes<'_>, -) -> Result, SemanticDeferral> { +) -> Result, SemanticFailure> { let mut errors: Vec<(usize, MetadataFinding)> = Vec::new(); for (index, source) in sources.iter().enumerate() { let (Some(cursor), Some(shape)) = (&source.cursor_column, shapes.get(source.name.as_str())) else { continue; }; - if folded_names(shape)?.contains(&casefold(ascii(cursor)?)) { + if folded_names(shape)?.contains(&casefold(cursor)) { continue; } let (line, column) = text_position(&source.contents, cursor, 0)?; @@ -231,23 +231,21 @@ fn source_errors( fn sql_test_errors( tests: &[MetadataSqlTest], shapes: &Shapes<'_>, -) -> Result, SemanticDeferral> { +) -> Result, SemanticFailure> { let cte_pattern: &Regex = pattern(&SQL_TEST_CTE)?; let mut errors: Vec<(usize, MetadataFinding, i64)> = Vec::new(); for (index, test) in tests.iter().enumerate() { for (cte_name, columns) in &test.ctes { - if cte_name.ends_with('\n') { - return Err(SemanticDeferral::NonAsciiText); - } + let matched_name: &str = cte_name.strip_suffix('\n').unwrap_or(cte_name); let Some(shape) = cte_pattern - .captures(cte_name) + .captures(matched_name) .and_then(|captures| shapes.get(&captures[1])) else { continue; }; let available: HashSet = folded_names(shape)?; for column_name in columns { - if available.contains(&casefold(ascii(column_name)?)) { + if available.contains(&casefold(column_name)) { continue; } let offset: usize = find_code_point(&test.contents, cte_name).unwrap_or(0); diff --git a/crates/sqlbuild-analysis/src/semantic_checks/_helpers/metadata_checks/families.rs b/crates/sqlbuild-analysis/src/semantic_checks/_helpers/metadata_checks/families.rs index c63fa668ec..e993a1bad8 100644 --- a/crates/sqlbuild-analysis/src/semantic_checks/_helpers/metadata_checks/families.rs +++ b/crates/sqlbuild-analysis/src/semantic_checks/_helpers/metadata_checks/families.rs @@ -3,7 +3,7 @@ use std::cell::RefCell; use crate::semantic_checks::constants::GENERIC_DIALECT; -use crate::semantic_checks::models::SemanticDeferral; +use crate::semantic_checks::models::SemanticFailure; use crate::type_system::main::normalize_type::normalize_type; use crate::type_system::models::{TypeFamily, TypeNormalization}; @@ -29,10 +29,10 @@ impl Families { } } - /// The family of `type_sql`, or a deferral where Python would leave the native type system. - pub(crate) fn family(&self, type_sql: &str) -> Result { + /// The family of `type_sql`, or the error Python's type normalization raised for it. + pub(crate) fn family(&self, type_sql: &str) -> Result { let normalization: TypeNormalization = - normalize_type(type_sql, &self.dialect).ok_or(SemanticDeferral::UnsupportedType)?; + normalize_type(type_sql, &self.dialect).map_err(SemanticFailure::TypeNormalization)?; if normalization.parse_error.is_some() { self.fallback_types.borrow_mut().push(type_sql.to_owned()); } @@ -40,7 +40,7 @@ impl Families { } /// Python's `_different_argument_families`. - pub(crate) fn different(&self, left: &str, right: &str) -> Result { + pub(crate) fn different(&self, left: &str, right: &str) -> Result { let left: TypeFamily = self.family(left)?; let right: TypeFamily = self.family(right)?; let families: [TypeFamily; 2] = [left, right]; diff --git a/crates/sqlbuild-analysis/src/semantic_checks/_helpers/metadata_checks/function_calls.rs b/crates/sqlbuild-analysis/src/semantic_checks/_helpers/metadata_checks/function_calls.rs index 1c9bc2ec0b..d892147d2d 100644 --- a/crates/sqlbuild-analysis/src/semantic_checks/_helpers/metadata_checks/function_calls.rs +++ b/crates/sqlbuild-analysis/src/semantic_checks/_helpers/metadata_checks/function_calls.rs @@ -8,12 +8,12 @@ use polyglot_sql::{Expression, ExpressionWalk}; use crate::semantic_checks::_helpers::metadata_checks::argument_types::expression_type; use crate::semantic_checks::_helpers::metadata_checks::families::Families; use crate::semantic_checks::_helpers::sql_text::parsed_sql::parsed_model; -use crate::semantic_checks::_helpers::sql_text::text::{ascii, casefold}; +use crate::semantic_checks::_helpers::sql_text::text::casefold; use crate::semantic_checks::constants::{ ARGUMENT_COUNT_CODE, NUMBER_LITERAL_TYPE, STRING_LITERAL_TYPE, TYPE_MISMATCH_CODE, UDF_NAME_PREFIX, UNKNOWN_TYPE, }; -use crate::semantic_checks::models::{MetadataFunction, MetadataModel, SemanticDeferral}; +use crate::semantic_checks::models::{MetadataFunction, MetadataModel, SemanticFailure}; /// One function error before it is located: `(code, located name, message)`. pub(crate) type FunctionError = (&'static str, String, String); @@ -41,7 +41,7 @@ type FoldedShape = HashMap>; pub(crate) fn function_errors( model: &MetadataModel, context: &FunctionContext<'_>, -) -> Result, SemanticDeferral> { +) -> Result, SemanticFailure> { if context.functions.is_empty() || !model.calls_functions { return Ok(Vec::new()); } @@ -101,7 +101,7 @@ fn call_name(call: &Function) -> &str { fn declared_calls<'a>( root: &'a Expression, functions: &HashMap<&str, &'a MetadataFunction>, -) -> Result<(Vec>, Vec<&'a Select>), SemanticDeferral> { +) -> Result<(Vec>, Vec<&'a Select>), SemanticFailure> { let mut calls: Vec> = Vec::new(); let mut selects: Vec<&'a Select> = Vec::new(); let mut pending: Vec<(&'a Expression, Option)> = vec![(root, None)]; @@ -112,7 +112,7 @@ fn declared_calls<'a>( selects.push(select); } Expression::Function(call) => { - let key: String = casefold(ascii(call_name(call))?); + let key: String = casefold(call_name(call)); if let Some(function) = functions.get(key.as_str()) { calls.push(DeclaredCall { call, @@ -169,7 +169,7 @@ fn relation_names(relation: &Expression) -> (&str, &str) { fn folded_shapes<'a>( relations: &HashMap>, shapes: &HashMap<&str, &[(String, String)]>, -) -> Result, SemanticDeferral> { +) -> Result, SemanticFailure> { let mut folded: HashMap<&'a str, FoldedShape> = HashMap::new(); for relation in relations.values().flatten() { let (table_name, _) = relation_names(relation); @@ -182,7 +182,7 @@ fn folded_shapes<'a>( let mut columns: FoldedShape = HashMap::new(); for (name, column_type) in *shape { columns - .entry(casefold(ascii(name)?)) + .entry(casefold(name)) .or_default() .push(column_type.clone()); } @@ -197,7 +197,7 @@ fn argument_type_of( scope: Option<&[&Expression]>, folded: &HashMap<&str, FoldedShape>, context: &FunctionContext<'_>, -) -> Result { +) -> Result { match argument { Expression::Literal(literal) => Ok(match literal.as_ref() { Literal::String(_) => STRING_LITERAL_TYPE, @@ -216,20 +216,17 @@ fn argument_column_type( column: &Column, scope: Option<&[&Expression]>, folded: &HashMap<&str, FoldedShape>, -) -> Result { +) -> Result { let Some(relations) = scope else { return Ok(UNKNOWN_TYPE.to_owned()); }; - let qualifier: Option = match &column.table { - Some(table) => Some(casefold(ascii(&table.name)?)), - None => None, - }; - let name: String = casefold(ascii(&column.name.name)?); + let qualifier: Option = column.table.as_ref().map(|table| casefold(&table.name)); + let name: String = casefold(&column.name.name); let mut candidates: Vec<&String> = Vec::new(); for relation in relations { let (table_name, alias) = relation_names(relation); if let Some(qualifier) = &qualifier - && *qualifier != casefold(ascii(alias)?) + && *qualifier != casefold(alias) { continue; } diff --git a/crates/sqlbuild-analysis/src/semantic_checks/_helpers/metadata_checks/positions.rs b/crates/sqlbuild-analysis/src/semantic_checks/_helpers/metadata_checks/positions.rs index a18abde30d..2c1b593632 100644 --- a/crates/sqlbuild-analysis/src/semantic_checks/_helpers/metadata_checks/positions.rs +++ b/crates/sqlbuild-analysis/src/semantic_checks/_helpers/metadata_checks/positions.rs @@ -1,14 +1,13 @@ //! Python's `_text_position`: the first whole-word occurrence of a name, in code points. -use crate::semantic_checks::models::SemanticDeferral; +use sqlbuild_core::text::main::active_python_text::active_python_text; +use sqlbuild_core::text::main::is_python_word::is_python_word; -/// Python's `\w` for a character next to a match; beyond ASCII the two engines may disagree. -fn word_character(character: char) -> Result { - if character.is_ascii() { - Ok(character.is_ascii_alphanumeric() || character == '_') - } else { - Err(SemanticDeferral::NonAsciiText) - } +use crate::semantic_checks::models::SemanticFailure; + +/// Python's `\w` for a character next to a match. +fn word_character(character: char) -> Result { + Ok(is_python_word(active_python_text(), character)) } /// Python's `text.find(needle)` in code points, or None. @@ -22,7 +21,7 @@ fn whole_word_at( name: &[char], start: usize, position: usize, -) -> Result { +) -> Result { if characters[position..position + name.len()] != *name { return Ok(false); } @@ -40,7 +39,7 @@ fn match_start( characters: &[char], name: &[char], offset: usize, -) -> Result { +) -> Result { let start: usize = offset.min(characters.len()); if name.len() <= characters.len() - start { for position in start..=characters.len() - name.len() { @@ -57,7 +56,7 @@ pub(crate) fn text_position( text: &str, name: &str, offset: usize, -) -> Result<(i64, i64), SemanticDeferral> { +) -> Result<(i64, i64), SemanticFailure> { let characters: Vec = text.chars().collect(); let name: Vec = name.chars().collect(); let start: usize = match_start(&characters, &name, offset)?; diff --git a/crates/sqlbuild-analysis/src/semantic_checks/_helpers/recovery/type_recovery.rs b/crates/sqlbuild-analysis/src/semantic_checks/_helpers/recovery/type_recovery.rs index 225ef721ee..1e065476f8 100644 --- a/crates/sqlbuild-analysis/src/semantic_checks/_helpers/recovery/type_recovery.rs +++ b/crates/sqlbuild-analysis/src/semantic_checks/_helpers/recovery/type_recovery.rs @@ -6,20 +6,17 @@ use crate::semantic_checks::_helpers::recovery::bindings::{BindingOwner, binding use crate::semantic_checks::_helpers::recovery::poison::Poison; use crate::semantic_checks::_helpers::sql_text::parsed_sql::{normalized_sql, projection_spans}; use crate::semantic_checks::models::{ - RecoveryModel, SemanticDeferral, TypeRecoveryOutcome, TypeRecoveryPlan, TypeRecoveryRequest, + RecoveryModel, SemanticFailure, TypeRecoveryOutcome, TypeRecoveryPlan, TypeRecoveryRequest, TypeRecoveryStep, }; use crate::semantic_checks::types::RevisedBinding; /// Find poisoned outputs and the failed models Python must revalidate with unknown types. -pub(crate) fn plan(request: &TypeRecoveryRequest) -> TypeRecoveryStep { - match planned(request) { - Ok(step) => step, - Err(deferral) => TypeRecoveryStep::Deferred(deferral), - } +pub(crate) fn plan(request: &TypeRecoveryRequest) -> Result { + planned(request) } -fn planned(request: &TypeRecoveryRequest) -> Result { +fn planned(request: &TypeRecoveryRequest) -> Result { let failed: Vec = failed_models(request); if !has_blocking_error(request, &failed) { return Ok(TypeRecoveryStep::Unchanged); diff --git a/crates/sqlbuild-analysis/src/semantic_checks/_helpers/sql_text/mod.rs b/crates/sqlbuild-analysis/src/semantic_checks/_helpers/sql_text/mod.rs index 4eeca97b60..0f26611802 100644 --- a/crates/sqlbuild-analysis/src/semantic_checks/_helpers/sql_text/mod.rs +++ b/crates/sqlbuild-analysis/src/semantic_checks/_helpers/sql_text/mod.rs @@ -1,2 +1,3 @@ pub(crate) mod parsed_sql; +pub(crate) mod python_regex; pub(crate) mod text; diff --git a/crates/sqlbuild-analysis/src/semantic_checks/_helpers/sql_text/parsed_sql.rs b/crates/sqlbuild-analysis/src/semantic_checks/_helpers/sql_text/parsed_sql.rs index d70a47139a..ca3f08dca7 100644 --- a/crates/sqlbuild-analysis/src/semantic_checks/_helpers/sql_text/parsed_sql.rs +++ b/crates/sqlbuild-analysis/src/semantic_checks/_helpers/sql_text/parsed_sql.rs @@ -11,56 +11,42 @@ use crate::semantic_checks::constants::{ CLOSE_PARENTHESIS, GENERIC_DIALECT, MAX_FUNCTION_CALL_DEPTH, OPEN_PARENTHESIS, PROJECTION_SEPARATOR, }; -use crate::semantic_checks::models::SemanticDeferral; +use crate::semantic_checks::models::SemanticFailure; use crate::semantic_validation::main::normalize::normalize_analysis_sql; use crate::semantic_validation::models::NormalizationInput; -/// The Polyglot dialect the wheel resolves `name` to, when this build includes it. -pub(crate) fn polyglot_dialect(name: &str) -> Result { - let Ok(dialect_type) = name.parse::() else { - return Err(SemanticDeferral::UnsupportedDialect); - }; - if matches!( - dialect_type, - DialectType::Generic - | DialectType::PostgreSQL - | DialectType::BigQuery - | DialectType::Snowflake - | DialectType::DuckDB - | DialectType::TSQL - | DialectType::Databricks - ) { - Ok(Dialect::get(dialect_type)) - } else { - Err(SemanticDeferral::UnsupportedDialect) - } +/// The Polyglot dialect the wheel resolves `name` to, when Polyglot knows the name. +pub(crate) fn polyglot_dialect(name: &str) -> Result { + name.parse::() + .map(Dialect::get) + .map_err(|_| SemanticFailure::UnknownDialect(name.to_owned())) } /// Python's `get_complete_schema_binding_request(...).sql` without placeholders. pub(crate) fn normalized_sql( query_sql: &str, dialect: Option<&str>, -) -> Result { +) -> Result { normalize_analysis_sql(NormalizationInput { sql: query_sql.to_owned(), dialect: dialect.unwrap_or(GENERIC_DIALECT).to_owned(), stubs: HashMap::new(), placeholders: HashMap::new(), }) - .map_err(|_| SemanticDeferral::UnreadableSql) + .map_err(|_| SemanticFailure::internal("model SQL does not normalize")) } /// Python's `_projection_spans`: top-level SELECT-list item spans in code points. pub(crate) fn projection_spans( sql: &str, dialect: Option<&str>, -) -> Result, SemanticDeferral> { +) -> Result, SemanticFailure> { let Some(name) = dialect else { - return Err(SemanticDeferral::UnsupportedDialect); + return Err(SemanticFailure::NoDialect); }; let tokens = polyglot_dialect(name)? .tokenize(sql) - .map_err(|_| SemanticDeferral::UnreadableSql)?; + .map_err(|_| SemanticFailure::internal("model SQL does not tokenize"))?; let mut depth: i64 = 0; let mut start: Option = None; let mut spans: Vec<(usize, usize)> = Vec::new(); @@ -117,7 +103,7 @@ pub(crate) struct ParsedModelFacts { pub(crate) fn parsed_model_facts( query_sql: &str, dialect: Option<&str>, -) -> Result { +) -> Result { let Some(parsed) = parsed_model(query_sql, dialect)? else { return Ok(ParsedModelFacts::default()); }; @@ -131,13 +117,13 @@ pub(crate) fn parsed_model_facts( pub(crate) fn parsed_model( query_sql: &str, dialect: Option<&str>, -) -> Result, SemanticDeferral> { +) -> Result, SemanticFailure> { let sql = normalized_sql(query_sql, dialect)?; let parser = polyglot_dialect(dialect.unwrap_or(GENERIC_DIALECT))?; let guard: ComplexityGuardOptions = serde_json::from_value(serde_json::json!({ "maxFunctionCallDepth": MAX_FUNCTION_CALL_DEPTH, })) - .map_err(|_| SemanticDeferral::NativeFailure)?; + .map_err(|_| SemanticFailure::internal("the parse guard options do not build"))?; let options = ParseOptions { complexity_guard: Some(guard), }; diff --git a/crates/sqlbuild-analysis/src/semantic_checks/_helpers/sql_text/python_regex.rs b/crates/sqlbuild-analysis/src/semantic_checks/_helpers/sql_text/python_regex.rs new file mode 100644 index 0000000000..ae3af9c7ae --- /dev/null +++ b/crates/sqlbuild-analysis/src/semantic_checks/_helpers/sql_text/python_regex.rs @@ -0,0 +1,74 @@ +//! Regexes matching as Python's `re` does, spelling out classes the `regex` crate reads otherwise. + +use std::fmt::Write; +use std::sync::LazyLock; + +use regex::Regex; +use sqlbuild_core::text::main::active_python_text::active_python_text; +use sqlbuild_core::text::models::PythonText; + +/// `(template token, class)`: Python's `\w`, `\d`, `\s` and an ignore-case identifier start. +static CLASSES: LazyLock<[(&'static str, String); 4]> = LazyLock::new(|| { + let python: PythonText = active_python_text(); + [ + ("{W}", ranges_class("_", python.alnum_ranges())), + ("{D}", ranges_class("", python.decimal_ranges())), + ( + "{S}", + String::from( + r"[\t-\r\x{1c}-\x{20}\x{85}\x{a0}\x{1680}\x{2000}-\x{200a}\x{2028}\x{2029}\x{202f}\x{205f}\x{3000}]", + ), + ), + ( + "{L}", + String::from(r"[A-Za-z_\x{130}\x{131}\x{17f}\x{212a}]"), + ), + ] +}); + +fn ranges_class(extra: &str, ranges: &[(u32, u32)]) -> String { + let mut class: String = format!("[{extra}"); + for (start, end) in ranges { + let _ = write!(class, r"\x{{{start:x}}}-\x{{{end:x}}}"); + } + class.push(']'); + class +} + +/// The characters `re.IGNORECASE` matches to one ASCII letter, as a class. +fn ignorecase_letter(letter: char) -> String { + let extra: &str = match letter.to_ascii_lowercase() { + 'i' => r"\x{130}\x{131}", + 'k' => r"\x{212a}", + 's' => r"\x{17f}", + _ => "", + }; + format!( + "[{}{}{extra}]", + letter.to_ascii_lowercase(), + letter.to_ascii_uppercase() + ) +} + +/// Python's `re.IGNORECASE` match of an ASCII word, as a sequence of classes. +pub(crate) fn ignorecase_word(word: &str) -> String { + word.chars().map(ignorecase_letter).collect() +} + +/// Whether `character` matches the ASCII letter `letter` under Python's `re.IGNORECASE`. +pub(crate) fn ignorecase_equal(character: char, letter: char) -> bool { + character.eq_ignore_ascii_case(&letter) + || matches!( + (letter.to_ascii_lowercase(), character), + ('i', '\u{130}' | '\u{131}') | ('k', '\u{212a}') | ('s', '\u{17f}') + ) +} + +/// Compile a pattern template, replacing `{W}`, `{D}`, `{S}` and `{L}` with Python's classes. +pub(crate) fn python_regex(template: &str) -> Result { + let mut pattern: String = template.to_owned(); + for (token, class) in CLASSES.iter() { + pattern = pattern.replace(token, class); + } + Regex::new(&pattern).map_err(|error| error.to_string()) +} diff --git a/crates/sqlbuild-analysis/src/semantic_checks/_helpers/sql_text/text.rs b/crates/sqlbuild-analysis/src/semantic_checks/_helpers/sql_text/text.rs index 9537c2ac40..220b519cff 100644 --- a/crates/sqlbuild-analysis/src/semantic_checks/_helpers/sql_text/text.rs +++ b/crates/sqlbuild-analysis/src/semantic_checks/_helpers/sql_text/text.rs @@ -1,54 +1,56 @@ -//! Python string operations over ASCII text, where byte offsets equal code-point offsets. +//! Python string operations, with offsets in code points as Python's string indexes count them. -use crate::semantic_checks::models::SemanticDeferral; +use sqlbuild_core::text::main::active_python_text::active_python_text; +use sqlbuild_core::text::main::python_casefold::python_casefold; +use sqlbuild_core::text::main::python_upper::python_upper; -/// ASCII text or a deferral, because Python's case folding and regex classes differ beyond it. -pub(crate) fn ascii(text: &str) -> Result<&str, SemanticDeferral> { - if text.is_ascii() { - Ok(text) - } else { - Err(SemanticDeferral::NonAsciiText) - } +/// Python's `str.casefold`. +pub(crate) fn casefold(text: &str) -> String { + python_casefold(active_python_text(), text) } -/// ASCII text without the separators Python's `\s` matches and Rust's does not. -pub(crate) fn plain_text(text: &str) -> Result<&str, SemanticDeferral> { - if ascii(text)? - .bytes() - .any(|byte| (0x1c..=0x1f).contains(&byte)) - { - return Err(SemanticDeferral::NonAsciiText); - } - Ok(text) +/// Python's `str.upper`. +pub(crate) fn upper(text: &str) -> String { + python_upper(active_python_text(), text) } -/// Python's `str.casefold` on ASCII text. -pub(crate) fn casefold(text: &str) -> String { - text.to_ascii_lowercase() +/// The line boundaries Python's `str.splitlines` splits on. +fn is_line_boundary(character: char) -> bool { + matches!( + character, + '\n' | '\r' + | '\u{b}' + | '\u{c}' + | '\u{1c}' + | '\u{1d}' + | '\u{1e}' + | '\u{85}' + | '\u{2028}' + | '\u{2029}' + ) } -/// Python's `str.splitlines(keepends=True)` line lengths on ASCII text. -fn line_ends(text: &str) -> Vec<(usize, usize)> { - let bytes = text.as_bytes(); - let mut lines: Vec<(usize, usize)> = Vec::new(); +/// Python's `str.splitlines(keepends=True)` as `(start, content end, next start)` byte offsets. +fn line_ends(text: &str) -> Vec<(usize, usize, usize)> { + let mut lines: Vec<(usize, usize, usize)> = Vec::new(); let mut start: usize = 0; - let mut index: usize = 0; - while index < bytes.len() { - let byte = bytes[index]; - if matches!(byte, b'\n' | b'\r' | 0x0b | 0x0c | 0x1c | 0x1d | 0x1e) { - let content_end = index; - index += 1; - if byte == b'\r' && bytes.get(index) == Some(&b'\n') { - index += 1; - } - lines.push((start, content_end)); - start = index; - } else { - index += 1; + let mut characters = text.char_indices().peekable(); + while let Some((index, character)) = characters.next() { + if !is_line_boundary(character) { + continue; } + let mut next: usize = index + character.len_utf8(); + if character == '\r' + && let Some((_, '\n')) = characters.peek() + { + let _ = characters.next(); + next += 1; + } + lines.push((start, index, next)); + start = next; } - if start < bytes.len() { - lines.push((start, bytes.len())); + if start < text.len() { + lines.push((start, text.len(), text.len())); } lines } @@ -56,6 +58,7 @@ fn line_ends(text: &str) -> Vec<(usize, usize)> { /// Python's `_line_index`: `splitlines()` and the running starts of `splitlines(keepends=True)`. pub(crate) struct LineIndex<'a> { pub(crate) lines: Vec<&'a str>, + /// Code-point offsets of each line start, then the text length. pub(crate) starts: Vec, } @@ -64,11 +67,10 @@ impl<'a> LineIndex<'a> { let ends = line_ends(text); let mut starts: Vec = vec![0]; let mut lines: Vec<&'a str> = Vec::with_capacity(ends.len()); - for (index, (start, content_end)) in ends.iter().enumerate() { - lines.push(&text[*start..*content_end]); - let next_start = ends.get(index + 1).map_or(text.len(), |(next, _)| *next); + for (start, content_end, next_start) in ends { + lines.push(&text[start..content_end]); let previous = starts.last().copied().unwrap_or(0); - starts.push(previous + (next_start - start)); + starts.push(previous + text[start..next_start].chars().count()); } Self { lines, starts } } @@ -85,9 +87,9 @@ impl<'a> LineIndex<'a> { pub(crate) fn newlines_before(text: &str, end: i64) -> i64 { let end: usize = clamp(text, end); i64::try_from( - text.as_bytes()[..end] - .iter() - .filter(|byte| **byte == b'\n') + text.chars() + .take(end) + .filter(|character| *character == '\n') .count(), ) .unwrap_or(i64::MAX) @@ -96,19 +98,34 @@ pub(crate) fn newlines_before(text: &str, end: i64) -> i64 { /// Python's `text.rfind("\n", 0, end)` with Python's slice clamping. pub(crate) fn last_newline_before(text: &str, end: i64) -> i64 { let end: usize = clamp(text, end); - text.as_bytes()[..end] - .iter() - .rposition(|byte| *byte == b'\n') - .map_or(-1, |index| i64::try_from(index).unwrap_or(i64::MAX)) + text.chars() + .take(end) + .enumerate() + .filter(|(_, character)| *character == '\n') + .last() + .map_or(-1, |(index, _)| i64::try_from(index).unwrap_or(i64::MAX)) } +/// A Python slice bound over `text`'s code points: negative counts from the end. fn clamp(text: &str, end: i64) -> usize { - let length: i64 = i64::try_from(text.len()).unwrap_or(i64::MAX); + let length: i64 = i64::try_from(text.chars().count()).unwrap_or(i64::MAX); let end: i64 = if end < 0 { (length + end).max(0) } else { end }; usize::try_from(end.min(length)).unwrap_or(0) } -/// Python's `text[:end]` for a non-negative end on ASCII text. +/// Python's `text[:end]`. pub(crate) fn prefix(text: &str, end: i64) -> &str { - &text[..clamp(text, end)] + &text[..byte_offset(text, clamp(text, end))] +} + +/// The byte offset of code point `index`, or the text length past the end. +pub(crate) fn byte_offset(text: &str, index: usize) -> usize { + text.char_indices() + .nth(index) + .map_or(text.len(), |(byte, _)| byte) +} + +/// The code-point offset of byte offset `byte` on a character boundary. +pub(crate) fn code_point_offset(text: &str, byte: usize) -> usize { + text[..byte].chars().count() } diff --git a/crates/sqlbuild-analysis/src/semantic_checks/constants.rs b/crates/sqlbuild-analysis/src/semantic_checks/constants.rs index d423aae445..7c9a4a7cc2 100644 --- a/crates/sqlbuild-analysis/src/semantic_checks/constants.rs +++ b/crates/sqlbuild-analysis/src/semantic_checks/constants.rs @@ -77,15 +77,36 @@ pub(crate) const KNOWN_CAST_TYPE_NAMES: [(&str, &str); 13] = [ ("varchar", "TEXT"), ]; -pub(crate) const TYPE_WORDS_PATTERN: &str = r"(?i)\b(timestamp|integer|varchar|boolean|date|interval|double|float|decimal|numeric|bigint|smallint|text|time|string|binary|array|struct)\b"; +/// Python's `_TYPE_WORDS` alternatives, tried in order between word boundaries. +pub(crate) const TYPE_WORDS: [&str; 18] = [ + "timestamp", + "integer", + "varchar", + "boolean", + "date", + "interval", + "double", + "float", + "decimal", + "numeric", + "bigint", + "smallint", + "text", + "time", + "string", + "binary", + "array", + "struct", +]; pub(crate) const MISSING_PATTERN: &str = r"Unknown column '([^']+)'(?: in table '([^']+)')?"; -pub(crate) const CONTEXT_SUFFIX_PATTERN: &str = r" \(context: [^)]*\)$"; +pub(crate) const CONTEXT_SUFFIX_PATTERN: &str = r" \(context: [^)]*\)"; pub(crate) const QUOTED_PIECE_PATTERN: &str = r"'[^']*'"; -pub(crate) const OPERAND_PATTERN: &str = r"(?:TIMESTAMP\s+'[^']*'|DATE\s+'[^']*'|'(?:[^']|'')*'|-?\d+(?:\.\d+)?|[A-Za-z_]\w*(?:\.[A-Za-z_]\w*)?)"; -pub(crate) const QUALIFIER_PATTERN: &str = r#"(?:"((?:[^"]|"")+)"|([A-Za-z_]\w*))\.$"#; -pub(crate) const TEMPORAL_OPERAND_PATTERN: &str = r"(?i)\A(TIMESTAMP|DATE)\s*'"; -pub(crate) const INTEGER_OPERAND_PATTERN: &str = r"\A-?\d+\z"; -pub(crate) const DECIMAL_OPERAND_PATTERN: &str = r"\A-?\d+\.\d+\z"; +/// Python's `_OPERAND` under `re.IGNORECASE`, as a `python_regex` template. +pub(crate) const OPERAND_PATTERN: &str = r"(?:{TIMESTAMP}{S}+'[^']*'|{DATE}{S}+'[^']*'|'(?:[^']|'')*'|-?{D}+(?:\.{D}+)?|{L}{W}*(?:\.{L}{W}*)?)"; +pub(crate) const QUALIFIER_PATTERN: &str = r#"(?:"((?:[^"]|"")+)"|([A-Za-z_]{W}*))\.\z"#; +pub(crate) const TEMPORAL_OPERAND_PATTERN: &str = r"\A({TIMESTAMP}|{DATE}){S}*'"; +pub(crate) const INTEGER_OPERAND_PATTERN: &str = r"\A-?{D}+\z"; +pub(crate) const DECIMAL_OPERAND_PATTERN: &str = r"\A-?{D}+\.{D}+\z"; pub(crate) const SQL_TEST_COLUMN_PATTERN: &str = r"'__(?:expected|ref)__(.+)' names unknown column '([^']+)'"; diff --git a/crates/sqlbuild-analysis/src/semantic_checks/main/check_semantic_metadata.rs b/crates/sqlbuild-analysis/src/semantic_checks/main/check_semantic_metadata.rs index d49d847409..94a9821949 100644 --- a/crates/sqlbuild-analysis/src/semantic_checks/main/check_semantic_metadata.rs +++ b/crates/sqlbuild-analysis/src/semantic_checks/main/check_semantic_metadata.rs @@ -3,17 +3,16 @@ use sqlbuild_core::panics::main::catch_compiler_panic::catch_compiler_panic; use crate::semantic_checks::_helpers::metadata_checks::checks::check_metadata; -use crate::semantic_checks::models::{MetadataOutcome, MetadataRequest, SemanticDeferral}; +use crate::semantic_checks::models::{MetadataOutcome, MetadataRequest, SemanticFailure}; use crate::semantic_validation::models::ProjectCatalog; -/// Check metadata on the compile's analysis pool; a deferral hands the checks back to Python. +/// Check metadata on the compile's analysis pool. pub fn check_semantic_metadata( request: &MetadataRequest, catalog: &ProjectCatalog, -) -> Result, String> { - let pool = catalog.analysis_pool()?; - Ok(pool.install(|| { - catch_compiler_panic(|| Ok(check_metadata(request))) - .unwrap_or(Err(SemanticDeferral::NativeFailure)) - })) +) -> Result { + let pool = catalog.analysis_pool().map_err(SemanticFailure::Internal)?; + pool.install(|| { + catch_compiler_panic(|| Ok(check_metadata(request))).map_err(SemanticFailure::Internal)? + }) } diff --git a/crates/sqlbuild-analysis/src/semantic_checks/main/complete_semantic_diagnostics.rs b/crates/sqlbuild-analysis/src/semantic_checks/main/complete_semantic_diagnostics.rs index 1d0f251c6b..dab3c6d609 100644 --- a/crates/sqlbuild-analysis/src/semantic_checks/main/complete_semantic_diagnostics.rs +++ b/crates/sqlbuild-analysis/src/semantic_checks/main/complete_semantic_diagnostics.rs @@ -3,17 +3,16 @@ use sqlbuild_core::panics::main::catch_compiler_panic::catch_compiler_panic; use crate::semantic_checks::_helpers::explanation::completion::complete; -use crate::semantic_checks::models::{CompletionOutcome, CompletionRequest, SemanticDeferral}; +use crate::semantic_checks::models::{CompletionOutcome, CompletionRequest, SemanticFailure}; use crate::semantic_validation::models::ProjectCatalog; /// Python's recovery, explanation and opt-out rejection, on the compile's analysis pool. pub fn complete_semantic_diagnostics( request: &CompletionRequest, catalog: &ProjectCatalog, -) -> Result { - let pool = catalog.analysis_pool()?; - Ok(pool.install(|| { - catch_compiler_panic(|| Ok(complete(request))) - .unwrap_or(CompletionOutcome::Deferred(SemanticDeferral::NativeFailure)) - })) +) -> Result { + let pool = catalog.analysis_pool().map_err(SemanticFailure::Internal)?; + pool.install(|| { + catch_compiler_panic(|| Ok(complete(request))).map_err(SemanticFailure::Internal)? + }) } diff --git a/crates/sqlbuild-analysis/src/semantic_checks/main/plan_type_recovery.rs b/crates/sqlbuild-analysis/src/semantic_checks/main/plan_type_recovery.rs index 2cfab0de26..c3c582e1f8 100644 --- a/crates/sqlbuild-analysis/src/semantic_checks/main/plan_type_recovery.rs +++ b/crates/sqlbuild-analysis/src/semantic_checks/main/plan_type_recovery.rs @@ -3,17 +3,16 @@ use sqlbuild_core::panics::main::catch_compiler_panic::catch_compiler_panic; use crate::semantic_checks::_helpers::recovery::type_recovery::plan; -use crate::semantic_checks::models::{SemanticDeferral, TypeRecoveryRequest, TypeRecoveryStep}; +use crate::semantic_checks::models::{SemanticFailure, TypeRecoveryRequest, TypeRecoveryStep}; use crate::semantic_validation::models::ProjectCatalog; -/// Plan type recovery on the compile's analysis pool; a native panic defers to Python. +/// Plan type recovery on the compile's analysis pool. pub fn plan_type_recovery( request: &TypeRecoveryRequest, catalog: &ProjectCatalog, -) -> Result { - let pool = catalog.analysis_pool()?; - Ok(pool.install(|| { - catch_compiler_panic(|| Ok(plan(request))) - .unwrap_or(TypeRecoveryStep::Deferred(SemanticDeferral::NativeFailure)) - })) +) -> Result { + let pool = catalog.analysis_pool().map_err(SemanticFailure::Internal)?; + pool.install(|| { + catch_compiler_panic(|| Ok(plan(request))).map_err(SemanticFailure::Internal)? + }) } diff --git a/crates/sqlbuild-analysis/src/semantic_checks/models.rs b/crates/sqlbuild-analysis/src/semantic_checks/models.rs index 8aaa052cea..3ee67376e5 100644 --- a/crates/sqlbuild-analysis/src/semantic_checks/models.rs +++ b/crates/sqlbuild-analysis/src/semantic_checks/models.rs @@ -4,6 +4,7 @@ use std::collections::{HashMap, HashSet}; use std::sync::Arc; use crate::semantic_checks::types::CompletedParts; +use crate::type_system::errors::TypeNormalizationError; /// One compiled model output column and the upstream columns it reads. #[derive(Clone, Debug, Default)] @@ -60,28 +61,23 @@ pub struct TypeRecoveryRequest { pub diagnostics: Vec, } -/// Why native semantic completion hands a stage back to Python. -#[derive(Clone, Copy, Debug, Eq, PartialEq)] -pub enum SemanticDeferral { - UnsupportedDialect, - UnreadableSql, - NonAsciiText, - UnexpectedPosition, - UnsupportedType, - NativeFailure, +/// Why completion fails: Python's error for the same input, or an internal native failure. +#[derive(Clone, Debug, Eq, PartialEq)] +pub enum SemanticFailure { + /// The wheel's `TypeError` for tokenizing without a dialect. + NoDialect, + /// The wheel's `ValueError` for a dialect name Polyglot does not know. + UnknownDialect(String), + /// The error Python's type normalization raised. + TypeNormalization(TypeNormalizationError), + /// An internal native failure, raised as `NativeCompilerError`. + Internal(String), } -impl SemanticDeferral { - /// The deferral kind recorded for the harness. - pub fn as_str(self) -> &'static str { - match self { - Self::UnsupportedDialect => "unsupported_dialect", - Self::UnreadableSql => "unreadable_sql", - Self::NonAsciiText => "non_ascii_text", - Self::UnexpectedPosition => "unexpected_position", - Self::UnsupportedType => "unsupported_type", - Self::NativeFailure => "native_failure", - } +impl SemanticFailure { + /// An internal failure with a fixed reason that never quotes SQL. + pub(crate) fn internal(reason: &str) -> Self { + Self::Internal(reason.to_owned()) } } @@ -109,29 +105,19 @@ impl TypeRecoveryPlan { } } -/// Type recovery's first step: nothing to recover, a plan, or a deferral. +/// Type recovery's first step: nothing to recover, or a plan. #[derive(Clone, Debug)] pub enum TypeRecoveryStep { Unchanged, Planned(TypeRecoveryPlan), - Deferred(SemanticDeferral), } impl TypeRecoveryStep { - /// `unchanged`, `planned` or `deferred`. + /// `unchanged` or `planned`. pub fn status(&self) -> &'static str { match self { Self::Unchanged => "unchanged", Self::Planned(_) => "planned", - Self::Deferred(_) => "deferred", - } - } - - /// The deferral kind, when the stage is handed back to Python. - pub fn deferral(&self) -> Option<&'static str> { - match self { - Self::Deferred(deferral) => Some(deferral.as_str()), - _ => None, } } @@ -240,29 +226,19 @@ impl FinalDiagnostic { } } -/// Recovery, explanation and opt-out rejection, or a deferral. +/// Recovery, explanation and opt-out rejection. #[derive(Clone, Debug)] -pub enum CompletionOutcome { - Completed { - diagnostics: Vec, - /// Indexes into `diagnostics` per model, or `None` when models keep their bindings. - model_bindings: Option>>, - order: Vec, - }, - Deferred(SemanticDeferral), +pub struct CompletionOutcome { + pub diagnostics: Vec, + /// Indexes into `diagnostics` per model, or `None` when models keep their bindings. + pub model_bindings: Option>>, + pub order: Vec, } impl CompletionOutcome { - /// `(deferral kind, completed parts)`: exactly one side is set. - pub fn into_parts(self) -> (Option<&'static str>, Option) { - match self { - Self::Completed { - diagnostics, - model_bindings, - order, - } => (None, Some((diagnostics, model_bindings, order))), - Self::Deferred(deferral) => (Some(deferral.as_str()), None), - } + /// The completed diagnostics, model binding positions and final order. + pub fn into_parts(self) -> CompletedParts { + (self.diagnostics, self.model_bindings, self.order) } } diff --git a/crates/sqlbuild-analysis/src/semantic_checks/tests/helpers.rs b/crates/sqlbuild-analysis/src/semantic_checks/tests/helpers.rs index 3d8ce62526..705a90481b 100644 --- a/crates/sqlbuild-analysis/src/semantic_checks/tests/helpers.rs +++ b/crates/sqlbuild-analysis/src/semantic_checks/tests/helpers.rs @@ -13,8 +13,8 @@ use crate::semantic_checks::models::{ CompletedDiagnostic, CompletionModel, CompletionRequest, DiagnosticOwner, FinalDiagnostic, LineageOutput, MetadataFinding, MetadataFunction, MetadataModel, MetadataOutcome, MetadataRequest, MetadataSource, MetadataSqlTest, ModelBinding, ModelMetadataFindings, - RawBinding, RecoveryModel, SemanticDeferral, SemanticDiagnostic, SemanticLocation, - TypeRecoveryPlan, TypeRecoveryRequest, + RawBinding, RecoveryModel, SemanticDiagnostic, SemanticFailure, SemanticLocation, + TypeRecoveryPlan, TypeRecoveryRequest, TypeRecoveryStep, }; use crate::semantic_checks::tests::test_types::{ CompletionTestCase, DescribedDiagnostic, MetadataTestCase, OperandTypeTestCase, @@ -24,16 +24,16 @@ use crate::semantic_validation::models::ProjectCatalog; /// What type recovery decided: status, poisoned outputs, revalidated models, kept and bindings. pub(crate) type RecoverySummary = ( - &'static str, + String, Vec<(String, String)>, Vec, Vec<(usize, Option)>, Vec>, ); -/// What completion decided: deferral, final diagnostics and model binding positions. +/// What completion decided: its failure, final diagnostics and model binding positions. pub(crate) type CompletionSummary = ( - Option<&'static str>, + Option, Vec, Option>>, ); @@ -57,21 +57,21 @@ pub(crate) fn names(values: &[&str]) -> BTreeSet { strings(values).into_iter().collect() } -pub(crate) fn sentence(message: &str) -> Result { +pub(crate) fn sentence(message: &str) -> Result { sentence_message(message) } /// The missing column and table Python reads from a message. pub(crate) fn missing_parts( message: &str, -) -> Result)>, SemanticDeferral> { +) -> Result)>, SemanticFailure> { missing_column(message) } /// An expected missing column and table as owned strings. pub(crate) fn owned_missing( - expected: Result)>, SemanticDeferral>, -) -> Result)>, SemanticDeferral> { + expected: Result)>, SemanticFailure>, +) -> Result)>, SemanticFailure> { expected.map(|missing| missing.map(owned_parts)) } @@ -197,7 +197,10 @@ fn poisoned_chain(dialect: Option<&str>, is_error: bool) -> TypeRecoveryRequest /// Plan and finish type recovery for one case of the poisoned chain. pub(crate) fn recovery_summary(test_case: &TypeRecoveryTestCase) -> RecoverySummary { let request = poisoned_chain(test_case.dialect, test_case.errors); - let step = plan_type_recovery(&request, &catalog()).expect("the analysis pool runs"); + let (status, step) = plan_type_recovery(&request, &catalog()).map_or_else( + |failure| (format!("{failure:?}"), TypeRecoveryStep::Unchanged), + |step| (step.status().to_owned(), step), + ); let revised = vec![ test_case .revised @@ -210,7 +213,7 @@ pub(crate) fn recovery_summary(test_case: &TypeRecoveryTestCase) -> RecoverySumm .map(|plan| finish_type_recovery(&request, plan, &revised).expect("finishes")) .unwrap_or_default(); ( - step.deferral().unwrap_or(step.status()), + status, step.plan() .map(TypeRecoveryPlan::poisoned_outputs) .unwrap_or_default(), @@ -405,14 +408,16 @@ pub(crate) fn completion_summary(test_case: &CompletionTestCase) -> CompletionSu request.diagnostics.truncate(kept_diagnostics); request.models[2].rejected_opt_out_file = [Some("legacy.sql".to_owned()), None][usize::from(test_case.without_diagnostics)].clone(); - let outcome = complete_semantic_diagnostics(&request, &catalog()).expect("the pool runs"); - let (deferral, parts) = outcome.into_parts(); - let (diagnostics, model_bindings, order) = parts.unwrap_or_default(); + let (failure, (diagnostics, model_bindings, order)) = + complete_semantic_diagnostics(&request, &catalog()).map_or_else( + |failure| (Some(failure), Default::default()), + |outcome| (None, outcome.into_parts()), + ); let described_order: Vec = order .into_iter() .map(|entry| described_entry(&request, &diagnostics, entry)) .collect(); - (deferral, described_order, model_bindings) + (failure, described_order, model_bindings) } fn described_entry( @@ -493,14 +498,16 @@ pub(crate) fn operand_type_summary(test_case: &OperandTypeTestCase) -> Completio .map(|(name, columns)| ((*name).to_owned(), shape(columns))) .collect(), }; - let outcome = complete_semantic_diagnostics(&request, &catalog()).expect("the pool runs"); - let (deferral, parts) = outcome.into_parts(); - let (diagnostics, model_bindings, order) = parts.unwrap_or_default(); + let (failure, (diagnostics, model_bindings, order)) = + complete_semantic_diagnostics(&request, &catalog()).map_or_else( + |failure| (Some(failure), Default::default()), + |outcome| (None, outcome.into_parts()), + ); let described_order: Vec = order .into_iter() .map(|entry| described_entry(&request, &diagnostics, entry)) .collect(); - (deferral, described_order, model_bindings) + (failure, described_order, model_bindings) } /// The type Python infers for the first projection of `SELECT {expression}` on DuckDB. @@ -616,8 +623,8 @@ pub(crate) fn metadata_finding( /// Run the metadata checks on a fresh catalog. pub(crate) fn metadata_outcome( test_case: &MetadataTestCase, -) -> Result { - check_semantic_metadata(&metadata_request(test_case), &catalog()).expect("the pool runs") +) -> Result { + check_semantic_metadata(&metadata_request(test_case), &catalog()) } /// The findings Python reports for the checked mart of `metadata_request`. diff --git a/crates/sqlbuild-analysis/src/semantic_checks/tests/test_columns.rs b/crates/sqlbuild-analysis/src/semantic_checks/tests/test_columns.rs index c1bb607569..c90344ca94 100644 --- a/crates/sqlbuild-analysis/src/semantic_checks/tests/test_columns.rs +++ b/crates/sqlbuild-analysis/src/semantic_checks/tests/test_columns.rs @@ -1,5 +1,4 @@ use crate::semantic_checks::_helpers::explanation::columns::{closest_column, ordered_columns}; -use crate::semantic_checks::models::SemanticDeferral; use crate::semantic_checks::tests::helpers::shape; use crate::semantic_checks::tests::test_types::ClosestColumnTestCase; @@ -45,8 +44,15 @@ fn given_unknown_column_names_when_suggesting_then_matches_python_order_and_choi description: "a column Python case-folds beyond ASCII", name: "strasse", columns: &[("stra\u{df}e", "VARCHAR")], - expected_closest: Err(SemanticDeferral::NonAsciiText), - expected_order: Err(SemanticDeferral::NonAsciiText), + expected_closest: Ok(Some("stra\u{df}e")), + expected_order: Ok(&["stra\u{df}e"]), + }, + ClosestColumnTestCase { + description: "an abbreviation whose first character case-folds to two", + name: "\u{df}ab", + columns: &[("ssxab", "X"), ("sab", "Y")], + expected_closest: Ok(Some("ssxab")), + expected_order: Ok(&["ssxab", "sab"]), }, ]; for test_case in test_cases { diff --git a/crates/sqlbuild-analysis/src/semantic_checks/tests/test_completion.rs b/crates/sqlbuild-analysis/src/semantic_checks/tests/test_completion.rs index 3d21831efe..83d1ef49a8 100644 --- a/crates/sqlbuild-analysis/src/semantic_checks/tests/test_completion.rs +++ b/crates/sqlbuild-analysis/src/semantic_checks/tests/test_completion.rs @@ -16,7 +16,7 @@ fn given_failing_project_when_completing_then_recovers_explains_and_rejects_like description: "a recovered typo, an explained comparison, a test error and an opt-out", non_ascii_comment: false, without_diagnostics: false, - expected_deferral: None, + expected_failure: None, expected_diagnostics: vec![ described( "B002", @@ -47,18 +47,44 @@ fn given_failing_project_when_completing_then_recovers_explains_and_rejects_like expected_bindings: Some(vec![vec![0], vec![1], vec![2]]), }, CompletionTestCase { - description: "non-ASCII authored SQL in an explained model defers to Python", + description: "a trailing non-ASCII comment leaves every explanation unchanged", non_ascii_comment: true, without_diagnostics: false, - expected_deferral: Some("non_ascii_text"), - expected_diagnostics: Vec::new(), - expected_bindings: None, + expected_failure: None, + expected_diagnostics: vec![ + described( + "B002", + "Unknown column 'amonut' in raw_orders", + Some("did you mean 'amount'?"), + &[ + "raw_orders has: amount, status, customer_id, order_id", + "1 downstream uses of stg.amount were not checked because of this error", + ], + Some((5, 18, None, None)), + ), + described( + "B217", + "Cannot compare TIMESTAMP and INTEGER", + Some("compare with a timestamp, for example TIMESTAMP '2026-04-01'"), + &["o.ordered_at is TIMESTAMP, 5 is INTEGER"], + Some((7, 7, Some(7), Some(23))), + ), + described("B002", "Unknown column 'x' in table 'stg'", None, &[], None), + described( + "P009", + "`sql_analysis false` is not needed for model 'legacy'", + Some(OPT_OUT_HELP), + &[OPT_OUT_NOTE], + None, + ), + ], + expected_bindings: Some(vec![vec![0], vec![1], vec![2]]), }, CompletionTestCase { description: "no diagnostics keep every model's bindings", non_ascii_comment: false, without_diagnostics: true, - expected_deferral: None, + expected_failure: None, expected_diagnostics: Vec::new(), expected_bindings: None, }, @@ -67,7 +93,7 @@ fn given_failing_project_when_completing_then_recovers_explains_and_rejects_like assert_eq!( completion_summary(&test_case), ( - test_case.expected_deferral, + test_case.expected_failure.clone(), test_case.expected_diagnostics.clone(), test_case.expected_bindings.clone(), ), diff --git a/crates/sqlbuild-analysis/src/semantic_checks/tests/test_messages.rs b/crates/sqlbuild-analysis/src/semantic_checks/tests/test_messages.rs index b3b665e148..c270825d06 100644 --- a/crates/sqlbuild-analysis/src/semantic_checks/tests/test_messages.rs +++ b/crates/sqlbuild-analysis/src/semantic_checks/tests/test_messages.rs @@ -1,5 +1,4 @@ use crate::semantic_checks::_helpers::explanation::messages::comparison_help; -use crate::semantic_checks::models::SemanticDeferral; use crate::semantic_checks::tests::helpers::{missing_parts, owned_missing, sentence}; use crate::semantic_checks::tests::test_types::{ComparisonHelpTestCase, SentenceMessageTestCase}; @@ -31,16 +30,30 @@ fn given_binding_messages_when_rewriting_then_matches_python_sentences() { expected_missing: Ok(Some(("amonut", None))), }, SentenceMessageTestCase { - description: "a non-ASCII column Python's regex classes read differently", + description: "a non-ASCII column", message: "Unknown column 'stra\u{df}e'", - expected_sentence: Err(SemanticDeferral::NonAsciiText), - expected_missing: Err(SemanticDeferral::NonAsciiText), + expected_sentence: Ok("Unknown column 'stra\u{df}e'"), + expected_missing: Ok(Some(("stra\u{df}e", None))), }, SentenceMessageTestCase { - description: "a line break Python's end anchor treats specially", + description: "a line break before the table", message: "Unknown column 'a'\nin table 'b'", - expected_sentence: Err(SemanticDeferral::NonAsciiText), - expected_missing: Err(SemanticDeferral::NonAsciiText), + expected_sentence: Ok("Unknown column 'a'\nin table 'b'"), + expected_missing: Ok(Some(("a", None))), + }, + SentenceMessageTestCase { + description: "type words Python's ignore-case matches beyond ASCII, before a final newline", + message: "Cannot compare \u{130}nteger with \u{131}nterval (context: x)\n", + expected_sentence: Ok("Cannot compare \u{130}NTEGER with INTERVAL\n"), + expected_missing: Ok(None), + }, + SentenceMessageTestCase { + description: "word boundaries next to non-ASCII word characters", + message: "\u{e9}integer integer\u{e9} \u{17f}tring va\u{212a}lue 'integer' DATE", + expected_sentence: Ok( + "\u{e9}integer integer\u{e9} STRING va\u{212a}lue 'integer' DATE", + ), + expected_missing: Ok(None), }, ]; for test_case in test_cases { diff --git a/crates/sqlbuild-analysis/src/semantic_checks/tests/test_metadata.rs b/crates/sqlbuild-analysis/src/semantic_checks/tests/test_metadata.rs index cf0c72bd2b..a5339d94e8 100644 --- a/crates/sqlbuild-analysis/src/semantic_checks/tests/test_metadata.rs +++ b/crates/sqlbuild-analysis/src/semantic_checks/tests/test_metadata.rs @@ -1,4 +1,3 @@ -use crate::semantic_checks::models::SemanticDeferral; use crate::semantic_checks::tests::helpers::{expected_checked_outcome, metadata_outcome}; use crate::semantic_checks::tests::test_types::MetadataTestCase; @@ -9,7 +8,7 @@ const MART_SHAPE: &[(&str, &str)] = &[ ]; #[test] -fn given_project_metadata_when_checking_then_reports_python_errors_or_defers() { +fn given_project_metadata_when_checking_then_reports_python_errors() { let test_cases = [ MetadataTestCase { description: "function arity and families, config references, cursors and SQL tests", @@ -18,16 +17,20 @@ fn given_project_metadata_when_checking_then_reports_python_errors_or_defers() { expected_outcome: Ok(expected_checked_outcome()), }, MetadataTestCase { - description: "a dialect outside the native parser build", + description: "a dialect the all-dialects parser build added", dialect: "mysql", mart_shape: MART_SHAPE, - expected_outcome: Err(SemanticDeferral::UnsupportedDialect), + expected_outcome: Ok(expected_checked_outcome()), }, MetadataTestCase { - description: "a column name Python case-folds beyond ASCII", + description: "a column name Python case-folds beyond ASCII to a tested name", dialect: "duckdb", - mart_shape: &[("stra\u{df}e", "VARCHAR")], - expected_outcome: Err(SemanticDeferral::NonAsciiText), + mart_shape: &[ + ("order_id", "INTEGER"), + ("\u{17f}caled", "DOUBLE"), + ("label", "VARCHAR"), + ], + expected_outcome: Ok(expected_checked_outcome()), }, ]; for test_case in test_cases { diff --git a/crates/sqlbuild-analysis/src/semantic_checks/tests/test_parsed_sql.rs b/crates/sqlbuild-analysis/src/semantic_checks/tests/test_parsed_sql.rs index fa69b6ac56..ad30d836f9 100644 --- a/crates/sqlbuild-analysis/src/semantic_checks/tests/test_parsed_sql.rs +++ b/crates/sqlbuild-analysis/src/semantic_checks/tests/test_parsed_sql.rs @@ -1,5 +1,5 @@ use crate::semantic_checks::_helpers::sql_text::parsed_sql::projection_spans; -use crate::semantic_checks::models::SemanticDeferral; +use crate::semantic_checks::models::SemanticFailure; use crate::semantic_checks::tests::helpers::{names, pairs, parsed_facts}; use crate::semantic_checks::tests::test_types::{ParsedFactsTestCase, ProjectionSpanTestCase}; @@ -40,13 +40,19 @@ fn given_select_lists_when_finding_projection_spans_then_matches_python_tokens() description: "no dialect, which the wheel's tokenizer rejects", sql: "SELECT a", dialect: None, - expected_spans: Err(SemanticDeferral::UnsupportedDialect), + expected_spans: Err(SemanticFailure::NoDialect), }, ProjectionSpanTestCase { - description: "a dialect outside the native parser build", + description: "a dialect the all-dialects parser build added, as the wheel tokenizes it", sql: "SELECT a", dialect: Some("mysql"), - expected_spans: Err(SemanticDeferral::UnsupportedDialect), + expected_spans: Ok(&[(6, 8)]), + }, + ProjectionSpanTestCase { + description: "a dialect Polyglot does not know", + sql: "SELECT a", + dialect: Some("nonsense"), + expected_spans: Err(SemanticFailure::UnknownDialect("nonsense".to_owned())), }, ]; for test_case in test_cases { diff --git a/crates/sqlbuild-analysis/src/semantic_checks/tests/test_positions.rs b/crates/sqlbuild-analysis/src/semantic_checks/tests/test_positions.rs index bc56c3c127..8a58643df2 100644 --- a/crates/sqlbuild-analysis/src/semantic_checks/tests/test_positions.rs +++ b/crates/sqlbuild-analysis/src/semantic_checks/tests/test_positions.rs @@ -1,5 +1,4 @@ use crate::semantic_checks::_helpers::metadata_checks::positions::text_position; -use crate::semantic_checks::models::SemanticDeferral; use crate::semantic_checks::tests::test_types::TextPositionTestCase; #[test] @@ -48,11 +47,18 @@ fn given_names_in_text_when_locating_then_matches_python_whole_word_positions() expected_position: Ok((1, 1)), }, TextPositionTestCase { - description: "a non-ASCII neighbour Python's word class may read differently", - text: "\u{e9}amount", + description: "a non-ASCII letter before the name is part of the word", + text: "\u{e9}amount amount", name: "amount", offset: 0, - expected_position: Err(SemanticDeferral::NonAsciiText), + expected_position: Ok((1, 9)), + }, + TextPositionTestCase { + description: "a non-ASCII digit joins the word and a line separator is no newline", + text: "a\u{2028}b \u{663}amount amount", + name: "amount", + offset: 0, + expected_position: Ok((1, 13)), }, ]; for test_case in test_cases { diff --git a/crates/sqlbuild-analysis/src/semantic_checks/tests/test_type_recovery.rs b/crates/sqlbuild-analysis/src/semantic_checks/tests/test_type_recovery.rs index e96abd40b0..ed35ef599c 100644 --- a/crates/sqlbuild-analysis/src/semantic_checks/tests/test_type_recovery.rs +++ b/crates/sqlbuild-analysis/src/semantic_checks/tests/test_type_recovery.rs @@ -37,7 +37,7 @@ fn given_poisoned_projection_when_recovering_types_then_counts_and_drops_like_py dialect: None, errors: true, revised: &[], - expected_status: "unsupported_dialect", + expected_status: "NoDialect", expected_poisoned: &[], expected_revalidated: &[], expected_kept: &[], diff --git a/crates/sqlbuild-analysis/src/semantic_checks/tests/test_types.rs b/crates/sqlbuild-analysis/src/semantic_checks/tests/test_types.rs index 4645a0cf36..9300442f68 100644 --- a/crates/sqlbuild-analysis/src/semantic_checks/tests/test_types.rs +++ b/crates/sqlbuild-analysis/src/semantic_checks/tests/test_types.rs @@ -1,4 +1,4 @@ -use crate::semantic_checks::models::{MetadataOutcome, SemanticDeferral}; +use crate::semantic_checks::models::{MetadataOutcome, SemanticFailure}; /// One located `(code, message, help, notes, location)` diagnostic of a completed project. pub(crate) type DescribedDiagnostic = ( @@ -13,7 +13,7 @@ pub(crate) struct ProjectionSpanTestCase { pub(crate) description: &'static str, pub(crate) sql: &'static str, pub(crate) dialect: Option<&'static str>, - pub(crate) expected_spans: Result<&'static [(usize, usize)], SemanticDeferral>, + pub(crate) expected_spans: Result<&'static [(usize, usize)], SemanticFailure>, } pub(crate) struct ParsedFactsTestCase { @@ -27,16 +27,16 @@ pub(crate) struct ClosestColumnTestCase { pub(crate) description: &'static str, pub(crate) name: &'static str, pub(crate) columns: &'static [(&'static str, &'static str)], - pub(crate) expected_closest: Result, SemanticDeferral>, - pub(crate) expected_order: Result<&'static [&'static str], SemanticDeferral>, + pub(crate) expected_closest: Result, SemanticFailure>, + pub(crate) expected_order: Result<&'static [&'static str], SemanticFailure>, } pub(crate) struct SentenceMessageTestCase { pub(crate) description: &'static str, pub(crate) message: &'static str, - pub(crate) expected_sentence: Result<&'static str, SemanticDeferral>, + pub(crate) expected_sentence: Result<&'static str, SemanticFailure>, pub(crate) expected_missing: - Result)>, SemanticDeferral>, + Result)>, SemanticFailure>, } pub(crate) struct ComparisonHelpTestCase { @@ -62,7 +62,7 @@ pub(crate) struct CompletionTestCase { pub(crate) description: &'static str, pub(crate) non_ascii_comment: bool, pub(crate) without_diagnostics: bool, - pub(crate) expected_deferral: Option<&'static str>, + pub(crate) expected_failure: Option, pub(crate) expected_diagnostics: Vec, pub(crate) expected_bindings: Option>>, } @@ -79,7 +79,7 @@ pub(crate) struct TextPositionTestCase { pub(crate) text: &'static str, pub(crate) name: &'static str, pub(crate) offset: usize, - pub(crate) expected_position: Result<(i64, i64), SemanticDeferral>, + pub(crate) expected_position: Result<(i64, i64), SemanticFailure>, } pub(crate) struct ArgumentTypeTestCase { @@ -92,5 +92,5 @@ pub(crate) struct MetadataTestCase { pub(crate) description: &'static str, pub(crate) dialect: &'static str, pub(crate) mart_shape: &'static [(&'static str, &'static str)], - pub(crate) expected_outcome: Result, + pub(crate) expected_outcome: Result, } diff --git a/crates/sqlbuild-analysis/src/semantic_validation/_helpers/catalog.rs b/crates/sqlbuild-analysis/src/semantic_validation/_helpers/catalog.rs index 3ce72f609a..e166e32913 100644 --- a/crates/sqlbuild-analysis/src/semantic_validation/_helpers/catalog.rs +++ b/crates/sqlbuild-analysis/src/semantic_validation/_helpers/catalog.rs @@ -310,14 +310,7 @@ impl ProjectCatalog { if let Some(pool) = pool.as_ref() { return Ok(Arc::clone(pool)); } - let built = Arc::new( - rayon::ThreadPoolBuilder::new() - .num_threads(ANALYSIS_WORKERS) - .stack_size(ANALYSIS_WORKER_STACK_BYTES) - .thread_name(|index| format!("sqlbuild-analysis-{index}")) - .build() - .map_err(|error| error.to_string())?, - ); + let built = Arc::new(new_analysis_pool()?); *pool = Some(Arc::clone(&built)); Ok(built) } @@ -615,3 +608,13 @@ fn has_exact_columns(table: &SchemaTable) -> bool { .iter() .any(|column| column.name.starts_with('"')) } + +/// A deep-stack analysis pool, for work that runs without a compile's catalog. +pub(crate) fn new_analysis_pool() -> Result { + rayon::ThreadPoolBuilder::new() + .num_threads(ANALYSIS_WORKERS) + .stack_size(ANALYSIS_WORKER_STACK_BYTES) + .thread_name(|index| format!("sqlbuild-analysis-{index}")) + .build() + .map_err(|error| error.to_string()) +} diff --git a/crates/sqlbuild-analysis/src/semantic_validation/main.rs b/crates/sqlbuild-analysis/src/semantic_validation/main.rs index 6f02155b91..a600f8fa69 100644 --- a/crates/sqlbuild-analysis/src/semantic_validation/main.rs +++ b/crates/sqlbuild-analysis/src/semantic_validation/main.rs @@ -2,6 +2,7 @@ pub mod diagnostics; pub mod map_diagnostics; +pub mod new_analysis_pool; pub mod normalize; pub mod normalize_batch; pub mod normalize_dialect; diff --git a/crates/sqlbuild-analysis/src/semantic_validation/main/new_analysis_pool.rs b/crates/sqlbuild-analysis/src/semantic_validation/main/new_analysis_pool.rs new file mode 100644 index 0000000000..28f3e3cbc6 --- /dev/null +++ b/crates/sqlbuild-analysis/src/semantic_validation/main/new_analysis_pool.rs @@ -0,0 +1,6 @@ +use crate::semantic_validation::_helpers::catalog; + +/// A deep-stack analysis pool, for work that runs without a compile's catalog. +pub fn new_analysis_pool() -> Result { + catalog::new_analysis_pool() +} diff --git a/crates/sqlbuild-analysis/src/type_system/_helpers/dialects.rs b/crates/sqlbuild-analysis/src/type_system/_helpers/dialects.rs index 6cabfabfeb..dc90fe4dd8 100644 --- a/crates/sqlbuild-analysis/src/type_system/_helpers/dialects.rs +++ b/crates/sqlbuild-analysis/src/type_system/_helpers/dialects.rs @@ -1,27 +1,7 @@ -//! Dialect names: Polyglot's resolution and Python's `TypeDialect` coercion. - -use polyglot_sql::{Dialect, DialectType}; +//! Dialect names: Python's `TypeDialect` coercion. use crate::type_system::models::TypeDialect; -/// The Polyglot dialect Python's wheel resolves `name` to, when this build includes it. -pub(crate) fn polyglot_dialect(name: &str) -> Option { - let Ok(dialect_type) = name.parse::() else { - return None; - }; - matches!( - dialect_type, - DialectType::Generic - | DialectType::PostgreSQL - | DialectType::BigQuery - | DialectType::Snowflake - | DialectType::DuckDB - | DialectType::TSQL - | DialectType::Databricks - ) - .then(|| Dialect::get(dialect_type)) -} - /// Python's `_coerce_type_dialect`: an exact `TypeDialect` value, otherwise None. pub(crate) fn coerce_type_dialect(name: &str) -> Option { Some(match name { diff --git a/crates/sqlbuild-analysis/src/type_system/_helpers/fallback.rs b/crates/sqlbuild-analysis/src/type_system/_helpers/fallback.rs index 53d2ee1d28..fb7a431b68 100644 --- a/crates/sqlbuild-analysis/src/type_system/_helpers/fallback.rs +++ b/crates/sqlbuild-analysis/src/type_system/_helpers/fallback.rs @@ -1,7 +1,9 @@ //! Python's `_normalize_with_fallback`: type text normalized without a parser. +use sqlbuild_core::text::main::python_strip::python_strip; + use crate::type_system::_helpers::python_text::{ - python_strip, remove_python_space, split_type_and_params, + remove_python_space, split_type_and_params, upper, }; use crate::type_system::constants::{ BIGNUMERIC_TYPE_NAME, BOOLEAN_TYPE_NAMES, DATE_TYPE_NAME, DATETIME_TYPE_NAME, @@ -10,32 +12,32 @@ use crate::type_system::constants::{ NORMALIZED_TZ_INPUT_TYPE_NAME, STRING_TYPE_NAMES, TEXT_TYPE_NAME, TIMESTAMP_TYPE_TOKEN, UNBOUNDED_TEXT_TYPE_NAMES, }; -use crate::type_system::models::{NormalizedType, TypeDialect, TypeFamily}; +use crate::type_system::models::{NormalizedType, PythonInteger, TypeDialect, TypeFamily}; -/// Normalize ASCII type text as Python's fallback does; None for integers beyond `i64`. +/// Normalize type text as Python's `_normalize_with_fallback` does. pub(crate) fn normalize_with_fallback( type_sql: &str, dialect: Option, -) -> Option { - let normalized: String = remove_python_space(python_strip(&type_sql.to_ascii_uppercase())); - let (base_type, params) = split_type_and_params(&normalized)?; - let first: Option = params.first().copied(); - let second: Option = params.get(1).copied(); +) -> NormalizedType { + let normalized: String = remove_python_space(python_strip(&upper(type_sql))); + let (base_type, params) = split_type_and_params(&normalized); + let first: Option = params.first().cloned(); + let second: Option = params.get(1).cloned(); let snowflake: bool = dialect == Some(TypeDialect::Snowflake); let bigquery: bool = dialect == Some(TypeDialect::BigQuery); if INTEGER_TYPE_NAMES.contains(&base_type) { if snowflake { - return Some(snowflake_integer()); + return snowflake_integer(); } let name: &str = if bigquery { "INT64" } else { base_type }; - return Some(simple(name, TypeFamily::Integer)); + return simple(name, TypeFamily::Integer); } if DECIMAL_TYPE_NAMES.contains(&base_type) { let (mut precision, mut scale) = (first, second); if snowflake && precision.is_none() { - precision = Some(INTEGER_PRECISION); - scale = Some(INTEGER_SCALE); + precision = Some(INTEGER_PRECISION.into()); + scale = Some(INTEGER_SCALE.into()); } let base_name: &str = if bigquery { if base_type == BIGNUMERIC_TYPE_NAME { @@ -48,25 +50,25 @@ pub(crate) fn normalize_with_fallback( } else { base_type }; - let normalized_name: String = match (precision, scale) { + let normalized_name: String = match (&precision, &scale) { (Some(precision), Some(scale)) => format!("{base_name}({precision},{scale})"), (Some(precision), None) => format!("{base_name}({precision})"), _ => base_name.to_owned(), }; - return Some(NormalizedType { + return NormalizedType { normalized_name, family: TypeFamily::Decimal, precision, scale, length: None, - }); + }; } if FLOAT_TYPE_NAMES.contains(&base_type) { let name: &str = if bigquery { "FLOAT64" } else { base_type }; - return Some(simple(name, TypeFamily::Float)); + return simple(name, TypeFamily::Float); } if STRING_TYPE_NAMES.contains(&base_type) { - let mut length: Option = first; + let mut length: Option = first; let base_name: &str = if bigquery { "STRING" } else if snowflake && base_type == TEXT_TYPE_NAME { @@ -74,40 +76,40 @@ pub(crate) fn normalize_with_fallback( } else { base_type }; - let mut normalized_name: String = match length { + let mut normalized_name: String = match &length { Some(length) => format!("{base_name}({length})"), None => base_name.to_owned(), }; if snowflake && UNBOUNDED_TEXT_TYPE_NAMES.contains(&base_type) { - let bounded: i64 = python_or_default(length); - length = Some(bounded); + let bounded: PythonInteger = python_or_default(length); normalized_name = format!("VARCHAR({bounded})"); + length = Some(bounded); } - return Some(NormalizedType { + return NormalizedType { normalized_name, family: TypeFamily::String, precision: None, scale: None, length, - }); + }; } if BOOLEAN_TYPE_NAMES.contains(&base_type) { let name: &str = if bigquery { "BOOL" } else { base_type }; - return Some(simple(name, TypeFamily::Boolean)); + return simple(name, TypeFamily::Boolean); } if base_type.contains(TIMESTAMP_TYPE_TOKEN) { - return Some(simple( + return simple( ×tamp_normalized_name(base_type, dialect), TypeFamily::Timestamp, - )); + ); } if base_type == DATE_TYPE_NAME { - return Some(simple(base_type, TypeFamily::Date)); + return simple(base_type, TypeFamily::Date); } if base_type == DATETIME_TYPE_NAME { - return Some(simple(base_type, TypeFamily::Datetime)); + return simple(base_type, TypeFamily::Datetime); } - Some(simple(&normalized, TypeFamily::Other)) + simple(&normalized, TypeFamily::Other) } /// Python's `_timestamp_normalized_name`: Snowflake spells its timestamp aliases one way. @@ -136,17 +138,17 @@ pub(crate) fn snowflake_integer() -> NormalizedType { NormalizedType { normalized_name: format!("DECIMAL({INTEGER_PRECISION},{INTEGER_SCALE})"), family: TypeFamily::Decimal, - precision: Some(INTEGER_PRECISION), - scale: Some(INTEGER_SCALE), + precision: Some(INTEGER_PRECISION.into()), + scale: Some(INTEGER_SCALE.into()), length: None, } } /// Python's `length or DEFAULT_TEXT_LENGTH`: a missing or zero length takes the default. -pub(crate) fn python_or_default(length: Option) -> i64 { +pub(crate) fn python_or_default(length: Option) -> PythonInteger { match length { - Some(length) if length != 0 => length, - _ => DEFAULT_TEXT_LENGTH, + Some(length) if !length.is_zero() => length, + _ => DEFAULT_TEXT_LENGTH.into(), } } diff --git a/crates/sqlbuild-analysis/src/type_system/_helpers/mod.rs b/crates/sqlbuild-analysis/src/type_system/_helpers/mod.rs index 51643d4b4a..70cbe23166 100644 --- a/crates/sqlbuild-analysis/src/type_system/_helpers/mod.rs +++ b/crates/sqlbuild-analysis/src/type_system/_helpers/mod.rs @@ -2,3 +2,4 @@ pub(crate) mod dialects; pub(crate) mod fallback; pub(crate) mod parsed; pub(crate) mod python_text; +pub(crate) mod shallow_args; diff --git a/crates/sqlbuild-analysis/src/type_system/_helpers/parsed.rs b/crates/sqlbuild-analysis/src/type_system/_helpers/parsed.rs index dc08a3b5d3..e37fddd4b9 100644 --- a/crates/sqlbuild-analysis/src/type_system/_helpers/parsed.rs +++ b/crates/sqlbuild-analysis/src/type_system/_helpers/parsed.rs @@ -1,6 +1,5 @@ //! Python's `_normalize_with_polyglot`: the parsed type's SQL and arguments. -use polyglot_sql::ast_json::{expression_from_value, expressions_from_value}; use polyglot_sql::{ComplexityGuardOptions, DataType, Dialect, Expression, ParseOptions}; use serde_json::{Map, Value}; @@ -8,7 +7,8 @@ use crate::type_system::_helpers::fallback::{ normalize_with_fallback, python_or_default, simple, snowflake_integer, timestamp_normalized_name, }; -use crate::type_system::_helpers::python_text::split_type_and_params; +use crate::type_system::_helpers::python_text::{python_int, split_type_and_params, upper}; +use crate::type_system::_helpers::shallow_args::shallow_args; use crate::type_system::constants::{ BIGNUMERIC_TYPE_NAME, BOOLEAN_TYPE_NAMES, CUSTOM_NORMALIZATION_TYPE_NAMES, DATE_TYPE_NAME, DATETIME_TYPE_NAME, DECIMAL_TYPE_NAMES, FLOAT_TYPE_NAMES, FLOAT_WIRE_TYPE_NAME, @@ -16,7 +16,8 @@ use crate::type_system::constants::{ MAX_FUNCTION_CALL_DEPTH, POLYGLOT_CUSTOM_TYPE_NAME, POLYGLOT_TYPE_NAME_ALIASES, STRING_TYPE_NAMES, TIMESTAMP_TYPE_NAMES, UNBOUNDED_TEXT_TYPE_NAMES, }; -use crate::type_system::models::{NormalizedType, TypeDialect, TypeFamily}; +use crate::type_system::errors::TypeNormalizationError; +use crate::type_system::models::{NormalizedType, PythonInteger, TypeDialect, TypeFamily}; /// Parse one type with SQLBuild's Polyglot guard; the error text is what Python logs. pub(crate) fn parse_type(type_sql: &str, dialect: &Dialect) -> Result { @@ -33,64 +34,60 @@ pub(crate) fn parse_type(type_sql: &str, dialect: &Dialect) -> Result, -) -> Option { +) -> Result { + let args: Map = shallow_args(&parsed); let expression: Expression = Expression::DataType(parsed); - let Ok(generated) = polyglot.generate(&expression) else { - return None; - }; - if !generated.is_ascii() { - return None; - } - let normalized_name: String = generated.to_ascii_uppercase().replace(' ', ""); - let args: Map = expression_args(&expression)?; - let dtype_name: String = polyglot_type_name(&args)?; - let params: Vec = polyglot_type_params(&args)?; + let generated: String = polyglot + .generate(&expression) + .map_err(|error| TypeNormalizationError::Generation(error.to_string()))?; + let normalized_name: String = upper(&generated).replace(' ', ""); + let dtype_name: String = polyglot_type_name(&args); + let params: Vec = polyglot_type_params(&args); let snowflake: bool = dialect == Some(TypeDialect::Snowflake); let bigquery: bool = dialect == Some(TypeDialect::BigQuery); let dtype: &str = dtype_name.as_str(); if bigquery && INTEGER_PARSE_TYPE_NAMES.contains(&dtype) { - return Some(simple("INT64", TypeFamily::Integer)); + return Ok(simple("INT64", TypeFamily::Integer)); } if bigquery && dtype == BIGNUMERIC_TYPE_NAME { - return Some(simple("BIGNUMERIC", TypeFamily::Decimal)); + return Ok(simple("BIGNUMERIC", TypeFamily::Decimal)); } if bigquery && dtype == FLOAT_WIRE_TYPE_NAME { - return Some(simple("FLOAT64", TypeFamily::Float)); + return Ok(simple("FLOAT64", TypeFamily::Float)); } if dtype == POLYGLOT_CUSTOM_TYPE_NAME { - let raw_name: String = match args.get("name") { - Some(value) => python_str(value)?, + let raw_name: String = upper(&match args.get("name") { + Some(value) => python_str(value), None => normalized_name.clone(), - } - .to_ascii_uppercase() + }) .replace(' ', ""); if snowflake && raw_name.starts_with("NUMBER") { - return snowflake_number(&raw_name); + return Ok(snowflake_number(&raw_name)); } - return normalize_with_fallback(&raw_name, dialect); + return Ok(normalize_with_fallback(&raw_name, dialect)); } if INTEGER_TYPE_NAMES.contains(&dtype) { if snowflake { - return Some(snowflake_integer()); + return Ok(snowflake_integer()); } - return Some(simple(&normalized_name, TypeFamily::Integer)); + return Ok(simple(&normalized_name, TypeFamily::Integer)); } if DECIMAL_TYPE_NAMES.contains(&dtype) { - let mut precision: Option = params.first().copied(); - let mut scale: Option = params.get(1).copied(); + let mut precision: Option = params.first().cloned(); + let mut scale: Option = params.get(1).cloned(); let mut name: String = normalized_name; if snowflake && precision.is_none() { - precision = Some(INTEGER_PRECISION); - scale = Some(INTEGER_SCALE); + precision = Some(INTEGER_PRECISION.into()); + scale = Some(INTEGER_SCALE.into()); name = format!("DECIMAL({INTEGER_PRECISION},{INTEGER_SCALE})"); } - return Some(NormalizedType { + return Ok(NormalizedType { normalized_name: name, family: TypeFamily::Decimal, precision, @@ -99,18 +96,18 @@ pub(crate) fn normalize_parsed( }); } if FLOAT_TYPE_NAMES.contains(&dtype) { - return Some(simple(&normalized_name, TypeFamily::Float)); + return Ok(simple(&normalized_name, TypeFamily::Float)); } if STRING_TYPE_NAMES.contains(&dtype) { - let mut length: Option = params.first().copied(); + let mut length: Option = params.first().cloned(); let mut name: String = normalized_name; let base_name: &str = name.split('(').next().unwrap_or_default(); if snowflake && UNBOUNDED_TEXT_TYPE_NAMES.contains(&base_name) { - let bounded: i64 = python_or_default(length); - length = Some(bounded); + let bounded: PythonInteger = python_or_default(length); name = format!("VARCHAR({bounded})"); + length = Some(bounded); } - return Some(NormalizedType { + return Ok(NormalizedType { normalized_name: name, family: TypeFamily::String, precision: None, @@ -119,124 +116,94 @@ pub(crate) fn normalize_parsed( }); } if BOOLEAN_TYPE_NAMES.contains(&dtype) { - return Some(simple(&normalized_name, TypeFamily::Boolean)); + return Ok(simple(&normalized_name, TypeFamily::Boolean)); } if TIMESTAMP_TYPE_NAMES.contains(&dtype) { - return Some(simple( + return Ok(simple( ×tamp_normalized_name(&normalized_name, dialect), TypeFamily::Timestamp, )); } if dtype == DATE_TYPE_NAME { - return Some(simple(&normalized_name, TypeFamily::Date)); + return Ok(simple(&normalized_name, TypeFamily::Date)); } if dtype == DATETIME_TYPE_NAME { - return Some(simple(&normalized_name, TypeFamily::Datetime)); + return Ok(simple(&normalized_name, TypeFamily::Datetime)); } - Some(simple(&normalized_name, TypeFamily::Other)) + Ok(simple(&normalized_name, TypeFamily::Other)) } /// Snowflake's `NUMBER(p,s)` spelled as a custom type: Python's `DECIMAL` rewrite. -fn snowflake_number(raw_name: &str) -> Option { +fn snowflake_number(raw_name: &str) -> NormalizedType { let mut decimal_name: String = raw_name.replacen("NUMBER", "DECIMAL", 1); - let (_, params) = split_type_and_params(&decimal_name)?; - let mut precision: Option = params.first().copied(); - let mut scale: Option = params.get(1).copied(); + let (_, params) = split_type_and_params(&decimal_name); + let mut precision: Option = params.first().cloned(); + let mut scale: Option = params.get(1).cloned(); if precision.is_none() { - precision = Some(INTEGER_PRECISION); - scale = Some(INTEGER_SCALE); + precision = Some(INTEGER_PRECISION.into()); + scale = Some(INTEGER_SCALE.into()); decimal_name = format!("DECIMAL({INTEGER_PRECISION},{INTEGER_SCALE})"); } - Some(NormalizedType { + NormalizedType { normalized_name: decimal_name, family: TypeFamily::Decimal, precision, scale, length: None, - }) -} - -/// The wheel's `Expression.args`: the serde payload of the expression's variant. -fn expression_args(expression: &Expression) -> Option> { - let Ok(value) = serde_json::to_value(expression) else { - return None; - }; - match value { - Value::Object(map) => match map.into_iter().next() { - Some((_, Value::Object(payload))) => Some(payload), - _ => Some(Map::new()), - }, - _ => Some(Map::new()), } } /// Python's `_polyglot_type_name`. -fn polyglot_type_name(args: &Map) -> Option { - let data_type: String = match args.get("data_type") { - Some(value) => python_str(value)?, +fn polyglot_type_name(args: &Map) -> String { + let data_type: String = upper(&match args.get("data_type") { + Some(value) => python_str(value), None => String::new(), - } - .to_ascii_uppercase(); + }); if let Some((_, alias)) = POLYGLOT_TYPE_NAME_ALIASES .iter() .find(|(name, _)| *name == data_type) { - return Some((*alias).to_owned()); + return (*alias).to_owned(); } if data_type == POLYGLOT_CUSTOM_TYPE_NAME { - let name: String = match args.get("name") { - Some(value) => python_str(value)?, + let name: String = upper(&match args.get("name") { + Some(value) => python_str(value), None => String::new(), - } - .to_ascii_uppercase() + }) .replace(' ', ""); if CUSTOM_NORMALIZATION_TYPE_NAMES.contains(&name.as_str()) { - return Some(name); + return name; } } - Some(data_type) + data_type } -/// Python's `_polyglot_type_params`; text and integers beyond `i64` defer. -fn polyglot_type_params(args: &Map) -> Option> { - let mut params: Vec = Vec::new(); +/// Python's `_polyglot_type_params`: `int(value)` of each parameter, skipping what it rejects. +fn polyglot_type_params(args: &Map) -> Vec { + let mut params: Vec = Vec::new(); for key in ["precision", "scale", "length"] { let Some(value) = args.get(key) else { continue; }; - match value { - Value::Null | Value::Array(_) | Value::Object(_) => {} - Value::Bool(flag) => params.push(i64::from(*flag)), - Value::Number(number) => params.push(number.as_i64()?), - Value::String(_) if is_python_expression(value) => {} - Value::String(_) => return None, - } + let param: Option = match value { + Value::Null | Value::Array(_) | Value::Object(_) => None, + Value::Bool(flag) => Some(i64::from(*flag).into()), + Value::Number(number) => python_int(&number.to_string()), + Value::String(text) => python_int(text), + }; + params.extend(param); } - Some(params) + params } -/// Python's `str(value)` for the text values Polyglot returns; None for anything else. -fn python_str(value: &Value) -> Option { - if is_python_expression(value) { - return None; - } +/// Python's `str(value)` for the scalar values Polyglot gives a parsed type's tag and name. +fn python_str(value: &Value) -> String { match value { - Value::String(text) if text.is_ascii() => Some(text.clone()), - Value::Null => Some("None".to_owned()), - _ => None, + Value::String(text) => text.clone(), + Value::Null => "None".to_owned(), + Value::Bool(true) => "True".to_owned(), + Value::Bool(false) => "False".to_owned(), + Value::Number(number) => number.to_string(), + Value::Array(_) | Value::Object(_) => value.to_string(), } } - -/// Whether the wheel hands Python an expression object; every variant holds data, so not a scalar. -fn is_python_expression(value: &Value) -> bool { - if !matches!(value, Value::Object(_) | Value::Array(_)) { - return false; - } - if let Ok(_expression) = expression_from_value(value.clone()) { - return true; - } - let Ok(_expressions) = expressions_from_value(value.clone()) else { - return false; - }; - true -} diff --git a/crates/sqlbuild-analysis/src/type_system/_helpers/python_text.rs b/crates/sqlbuild-analysis/src/type_system/_helpers/python_text.rs index a1dda52dbf..0a8533b3da 100644 --- a/crates/sqlbuild-analysis/src/type_system/_helpers/python_text.rs +++ b/crates/sqlbuild-analysis/src/type_system/_helpers/python_text.rs @@ -1,100 +1,79 @@ -//! Python string and integer semantics the type normalization relies on, for ASCII text. +//! Python string and integer semantics the type normalization relies on. -use crate::type_system::constants::PYTHON_ASCII_WHITESPACE; +use sqlbuild_core::text::main::active_python_text::active_python_text; +use sqlbuild_core::text::main::is_python_space::is_python_space; +use sqlbuild_core::text::main::python_decimal_value::python_decimal_value; +use sqlbuild_core::text::main::python_strip::python_strip; +use sqlbuild_core::text::main::python_upper::python_upper; +use sqlbuild_core::text::models::PythonText; -/// The result of Python's `int(text)` on one parameter. -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -pub(crate) enum PythonInt { - Value(i64), - Invalid, - /// A valid integer outside `i64`; Python keeps it, so the caller defers. - TooLarge, -} - -pub(crate) fn is_python_space(byte: u8) -> bool { - PYTHON_ASCII_WHITESPACE.contains(&byte) -} +use crate::type_system::models::PythonInteger; -/// Python's `str.strip()`. -pub(crate) fn python_strip(text: &str) -> &str { - text.trim_matches(|character: char| character.is_ascii() && is_python_space(character as u8)) +/// Python's `text.upper()` under the running Python's Unicode version. +pub(crate) fn upper(text: &str) -> String { + python_upper(active_python_text(), text) } /// Python's `re.sub(r"\s+", "", text)`. pub(crate) fn remove_python_space(text: &str) -> String { text.chars() - .filter(|character| !(character.is_ascii() && is_python_space(*character as u8))) + .filter(|character| !is_python_space(*character)) .collect() } -/// Python's base-10 `int(text)`: whitespace, a sign, and single underscores between digits. -pub(crate) fn python_int(text: &str) -> PythonInt { +/// Python's base-10 `int(text)`, None where Python raises `ValueError`. +pub(crate) fn python_int(text: &str) -> Option { + let python: PythonText = active_python_text(); let stripped: &str = python_strip(text); - let (negative, digits) = match stripped.as_bytes().first() { - Some(b'-') => (true, &stripped[1..]), - Some(b'+') => (false, &stripped[1..]), + let (negative, digits) = match stripped.chars().next() { + Some('-') => (true, &stripped[1..]), + Some('+') => (false, &stripped[1..]), _ => (false, stripped), }; - let bytes: &[u8] = digits.as_bytes(); - let valid: bool = !bytes.is_empty() - && bytes.first().is_some_and(u8::is_ascii_digit) - && bytes.last().is_some_and(u8::is_ascii_digit) - && bytes - .iter() - .all(|byte| byte.is_ascii_digit() || *byte == b'_') - && !digits.contains("__"); - if !valid { - return PythonInt::Invalid; - } - let mut value: i64 = 0; - for byte in bytes.iter().filter(|byte| byte.is_ascii_digit()) { - let digit: i64 = i64::from(byte - b'0'); - let next: Option = value.checked_mul(10).and_then(|scaled| { - if negative { - scaled.checked_sub(digit) - } else { - scaled.checked_add(digit) + let mut value: String = String::with_capacity(digits.len() + 1); + let mut previous_underscore: bool = true; + for character in digits.chars() { + if character == '_' { + if previous_underscore { + return None; } - }); - let Some(next) = next else { - return PythonInt::TooLarge; - }; - value = next; + previous_underscore = true; + continue; + } + let digit: u32 = python_decimal_value(python, character)?; + value.push(char::from_digit(digit, 10)?); + previous_underscore = false; + } + if value.is_empty() || previous_underscore { + return None; } - PythonInt::Value(value) + Some(PythonInteger::from_digits(negative, &value)) } -/// Python's `_split_type_and_params`; None for a parameter beyond `i64`. -pub(crate) fn split_type_and_params(type_sql: &str) -> Option<(&str, Vec)> { +/// Python's `_split_type_and_params`. +pub(crate) fn split_type_and_params(type_sql: &str) -> (&str, Vec) { let candidate: &str = type_sql.strip_suffix('\n').unwrap_or(type_sql); let name_end: usize = candidate .bytes() .position(|byte| !(byte.is_ascii_uppercase() || byte.is_ascii_digit() || byte == b'_')) .unwrap_or(candidate.len()); if name_end == 0 { - return Some((type_sql, Vec::new())); + return (type_sql, Vec::new()); } let (name, rest) = candidate.split_at(name_end); if rest.is_empty() { - return Some((name, Vec::new())); + return (name, Vec::new()); } let Some(raw_params) = rest .strip_prefix('(') .and_then(|inner| inner.strip_suffix(')')) .filter(|inner| !inner.contains(')')) else { - return Some((type_sql, Vec::new())); + return (type_sql, Vec::new()); }; - let mut params: Vec = Vec::new(); if raw_params.is_empty() { - return Some((name, params)); - } - for raw_part in raw_params.split(',') { - match python_int(raw_part) { - PythonInt::Value(value) => params.push(value), - PythonInt::Invalid => {} - PythonInt::TooLarge => return None, - } + return (name, Vec::new()); } - Some((name, params)) + let params: Vec = raw_params.split(',').filter_map(python_int).collect(); + (name, params) } diff --git a/crates/sqlbuild-analysis/src/type_system/_helpers/shallow_args.rs b/crates/sqlbuild-analysis/src/type_system/_helpers/shallow_args.rs new file mode 100644 index 0000000000..411f17c653 --- /dev/null +++ b/crates/sqlbuild-analysis/src/type_system/_helpers/shallow_args.rs @@ -0,0 +1,442 @@ +//! The wheel's `DataType.args` scalars, read without walking nested types. + +use std::fmt::Display; + +use serde::ser::{ + Impossible, Serialize, SerializeMap, SerializeSeq, SerializeStruct, SerializeStructVariant, + SerializeTuple, SerializeTupleStruct, SerializeTupleVariant, Serializer, +}; +use serde_json::{Map, Number, Value}; + +/// The top-level scalar fields of one serialized value; nested values are absent. +pub(crate) fn shallow_args(value: &T) -> Map { + value.serialize(Fields::default()).unwrap_or_default() +} + +#[derive(Debug)] +pub(crate) struct Unsupported; + +impl Display for Unsupported { + fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + formatter.write_str("not a struct") + } +} + +impl std::error::Error for Unsupported {} + +impl serde::ser::Error for Unsupported { + fn custom(_message: T) -> Self { + Self + } +} + +/// Collects one struct's scalar fields. +#[derive(Default)] +struct Fields { + fields: Map, +} + +impl SerializeStruct for Fields { + type Ok = Map; + type Error = Unsupported; + + fn serialize_field( + &mut self, + key: &'static str, + value: &T, + ) -> Result<(), Unsupported> { + if let Some(scalar) = value.serialize(Scalar)? { + let _ = self.fields.insert(key.to_owned(), scalar); + } + Ok(()) + } + + fn end(self) -> Result, Unsupported> { + Ok(self.fields) + } +} + +impl SerializeStructVariant for Fields { + type Ok = Map; + type Error = Unsupported; + + fn serialize_field( + &mut self, + key: &'static str, + value: &T, + ) -> Result<(), Unsupported> { + SerializeStruct::serialize_field(self, key, value) + } + + fn end(self) -> Result, Unsupported> { + Ok(self.fields) + } +} + +impl SerializeMap for Fields { + type Ok = Map; + type Error = Unsupported; + + fn serialize_key(&mut self, _key: &T) -> Result<(), Unsupported> { + Err(Unsupported) + } + + fn serialize_value(&mut self, _value: &T) -> Result<(), Unsupported> { + Err(Unsupported) + } + + fn end(self) -> Result, Unsupported> { + Ok(self.fields) + } +} + +macro_rules! not_a_struct { + ($($method:ident($($argument:ty),*)),* $(,)?) => { + $(fn $method(self, $(_: $argument),*) -> Result { + Err(Unsupported) + })* + }; +} + +impl Serializer for Fields { + type Ok = Map; + type Error = Unsupported; + type SerializeSeq = Impossible; + type SerializeTuple = Impossible; + type SerializeTupleStruct = Impossible; + type SerializeTupleVariant = Impossible; + type SerializeMap = Self; + type SerializeStruct = Self; + type SerializeStructVariant = Self; + + not_a_struct!( + serialize_bool(bool), + serialize_i8(i8), + serialize_i16(i16), + serialize_i32(i32), + serialize_i64(i64), + serialize_u8(u8), + serialize_u16(u16), + serialize_u32(u32), + serialize_u64(u64), + serialize_f32(f32), + serialize_f64(f64), + serialize_char(char), + serialize_str(&str), + serialize_bytes(&[u8]), + serialize_none(), + serialize_unit(), + serialize_unit_struct(&'static str), + serialize_unit_variant(&'static str, u32, &'static str), + ); + + fn serialize_some(self, value: &T) -> Result { + value.serialize(self) + } + + fn serialize_newtype_struct( + self, + _name: &'static str, + value: &T, + ) -> Result { + value.serialize(self) + } + + fn serialize_newtype_variant( + self, + _name: &'static str, + _index: u32, + _variant: &'static str, + _value: &T, + ) -> Result { + Err(Unsupported) + } + + fn serialize_seq(self, _len: Option) -> Result { + Err(Unsupported) + } + + fn serialize_tuple(self, _len: usize) -> Result { + Err(Unsupported) + } + + fn serialize_tuple_struct( + self, + _name: &'static str, + _len: usize, + ) -> Result { + Err(Unsupported) + } + + fn serialize_tuple_variant( + self, + _name: &'static str, + _index: u32, + _variant: &'static str, + _len: usize, + ) -> Result { + Err(Unsupported) + } + + fn serialize_map(self, _len: Option) -> Result { + Ok(self) + } + + fn serialize_struct( + self, + _name: &'static str, + _len: usize, + ) -> Result { + Ok(self) + } + + fn serialize_struct_variant( + self, + _name: &'static str, + _index: u32, + _variant: &'static str, + _len: usize, + ) -> Result { + Ok(self) + } +} + +/// One field's value if it is a scalar; nested values are skipped without visiting them. +struct Scalar; + +/// Swallows the children of a nested value unvisited. +struct Skipped; + +macro_rules! skip_children { + ($($trait:ident :: $method:ident),* $(,)?) => { + $(impl $trait for Skipped { + type Ok = Option; + type Error = Unsupported; + + fn $method(&mut self, _value: &T) -> Result<(), Unsupported> { + Ok(()) + } + + fn end(self) -> Result, Unsupported> { + Ok(None) + } + })* + }; +} + +skip_children!( + SerializeSeq::serialize_element, + SerializeTuple::serialize_element, + SerializeTupleStruct::serialize_field, + SerializeTupleVariant::serialize_field, +); + +impl SerializeMap for Skipped { + type Ok = Option; + type Error = Unsupported; + + fn serialize_key(&mut self, _key: &T) -> Result<(), Unsupported> { + Ok(()) + } + + fn serialize_value(&mut self, _value: &T) -> Result<(), Unsupported> { + Ok(()) + } + + fn end(self) -> Result, Unsupported> { + Ok(None) + } +} + +impl SerializeStruct for Skipped { + type Ok = Option; + type Error = Unsupported; + + fn serialize_field( + &mut self, + _key: &'static str, + _value: &T, + ) -> Result<(), Unsupported> { + Ok(()) + } + + fn end(self) -> Result, Unsupported> { + Ok(None) + } +} + +impl SerializeStructVariant for Skipped { + type Ok = Option; + type Error = Unsupported; + + fn serialize_field( + &mut self, + _key: &'static str, + _value: &T, + ) -> Result<(), Unsupported> { + Ok(()) + } + + fn end(self) -> Result, Unsupported> { + Ok(None) + } +} + +fn number(value: impl Into) -> Result, Unsupported> { + Ok(Some(Value::Number(value.into()))) +} + +impl Serializer for Scalar { + type Ok = Option; + type Error = Unsupported; + type SerializeSeq = Skipped; + type SerializeTuple = Skipped; + type SerializeTupleStruct = Skipped; + type SerializeTupleVariant = Skipped; + type SerializeMap = Skipped; + type SerializeStruct = Skipped; + type SerializeStructVariant = Skipped; + + fn serialize_bool(self, value: bool) -> Result { + Ok(Some(Value::Bool(value))) + } + + fn serialize_i8(self, value: i8) -> Result { + number(value) + } + + fn serialize_i16(self, value: i16) -> Result { + number(value) + } + + fn serialize_i32(self, value: i32) -> Result { + number(value) + } + + fn serialize_i64(self, value: i64) -> Result { + number(value) + } + + fn serialize_u8(self, value: u8) -> Result { + number(value) + } + + fn serialize_u16(self, value: u16) -> Result { + number(value) + } + + fn serialize_u32(self, value: u32) -> Result { + number(value) + } + + fn serialize_u64(self, value: u64) -> Result { + number(value) + } + + fn serialize_f32(self, value: f32) -> Result { + self.serialize_f64(f64::from(value)) + } + + fn serialize_f64(self, value: f64) -> Result { + Ok(Number::from_f64(value).map(Value::Number)) + } + + fn serialize_char(self, value: char) -> Result { + Ok(Some(Value::String(value.to_string()))) + } + + fn serialize_str(self, value: &str) -> Result { + Ok(Some(Value::String(value.to_owned()))) + } + + fn serialize_bytes(self, _value: &[u8]) -> Result { + Ok(None) + } + + fn serialize_none(self) -> Result { + Ok(Some(Value::Null)) + } + + fn serialize_some(self, value: &T) -> Result { + value.serialize(self) + } + + fn serialize_unit(self) -> Result { + Ok(Some(Value::Null)) + } + + fn serialize_unit_struct(self, _name: &'static str) -> Result { + Ok(Some(Value::Null)) + } + + fn serialize_unit_variant( + self, + _name: &'static str, + _index: u32, + variant: &'static str, + ) -> Result { + Ok(Some(Value::String(variant.to_owned()))) + } + + fn serialize_newtype_struct( + self, + _name: &'static str, + value: &T, + ) -> Result { + value.serialize(self) + } + + fn serialize_newtype_variant( + self, + _name: &'static str, + _index: u32, + _variant: &'static str, + _value: &T, + ) -> Result { + Ok(None) + } + + fn serialize_seq(self, _len: Option) -> Result { + Ok(Skipped) + } + + fn serialize_tuple(self, _len: usize) -> Result { + Ok(Skipped) + } + + fn serialize_tuple_struct( + self, + _name: &'static str, + _len: usize, + ) -> Result { + Ok(Skipped) + } + + fn serialize_tuple_variant( + self, + _name: &'static str, + _index: u32, + _variant: &'static str, + _len: usize, + ) -> Result { + Ok(Skipped) + } + + fn serialize_map(self, _len: Option) -> Result { + Ok(Skipped) + } + + fn serialize_struct(self, _name: &'static str, _len: usize) -> Result { + Ok(Skipped) + } + + fn serialize_struct_variant( + self, + _name: &'static str, + _index: u32, + _variant: &'static str, + _len: usize, + ) -> Result { + Ok(Skipped) + } +} diff --git a/crates/sqlbuild-analysis/src/type_system/constants.rs b/crates/sqlbuild-analysis/src/type_system/constants.rs index 9e05c81f24..39f858f52d 100644 --- a/crates/sqlbuild-analysis/src/type_system/constants.rs +++ b/crates/sqlbuild-analysis/src/type_system/constants.rs @@ -33,9 +33,7 @@ pub(crate) const POLYGLOT_TYPE_NAME_ALIASES: &[(&str, &str)] = &[ ("TINY_INT", "TINYINT"), ("VAR_CHAR", "VARCHAR"), ]; -/// The most `[` a type may hold before Python decides it; Polyglot's guards do not bound `[]`. -pub(crate) const MAX_TYPE_BRACKETS: usize = 32; /// The function call depth limit SQLBuild passes to every Polyglot parse. pub(crate) const MAX_FUNCTION_CALL_DEPTH: usize = 512; -/// Characters Python's `str.strip()` and the `\s` regex class treat as ASCII whitespace. -pub(crate) const PYTHON_ASCII_WHITESPACE: &[u8] = b" \t\n\r\x0b\x0c\x1c\x1d\x1e\x1f"; +/// Python's `str(0)`, the only integer text Python treats as false. +pub(crate) const ZERO_TEXT: &str = "0"; diff --git a/crates/sqlbuild-analysis/src/type_system/errors.rs b/crates/sqlbuild-analysis/src/type_system/errors.rs new file mode 100644 index 0000000000..05145a1c60 --- /dev/null +++ b/crates/sqlbuild-analysis/src/type_system/errors.rs @@ -0,0 +1,21 @@ +//! Why type normalization fails. + +/// Why Python's `normalize_type` raises instead of returning a type. +#[derive(Debug, Clone, PartialEq, Eq)] +pub enum TypeNormalizationError { + /// Polyglot does not know the dialect name: the wheel's `ValueError`. + UnknownDialect(String), + /// Polyglot cannot write the parsed type back as SQL: the wheel's `PolyglotError`. + Generation(String), +} + +impl TypeNormalizationError { + /// The message Python's exception carries. + #[must_use] + pub fn message(&self) -> String { + match self { + Self::UnknownDialect(name) => format!("Unknown dialect: {name}"), + Self::Generation(message) => message.clone(), + } + } +} diff --git a/crates/sqlbuild-analysis/src/type_system/main/normalize_type.rs b/crates/sqlbuild-analysis/src/type_system/main/normalize_type.rs index 466d0d2186..ef9005288c 100644 --- a/crates/sqlbuild-analysis/src/type_system/main/normalize_type.rs +++ b/crates/sqlbuild-analysis/src/type_system/main/normalize_type.rs @@ -1,29 +1,35 @@ //! Python's `normalize_type`: Polyglot's parsed type first, then the text fallback. -use crate::type_system::_helpers::dialects::{coerce_type_dialect, polyglot_dialect}; +use polyglot_sql::{Dialect, DialectType}; + +use crate::type_system::_helpers::dialects::coerce_type_dialect; use crate::type_system::_helpers::fallback::normalize_with_fallback; use crate::type_system::_helpers::parsed::{normalize_parsed, parse_type}; -use crate::type_system::constants::MAX_TYPE_BRACKETS; +use crate::type_system::errors::TypeNormalizationError; use crate::type_system::models::{TypeDialect, TypeNormalization}; -/// Normalize one type as Python does for the dialect name it hands Polyglot, or None to defer. -#[must_use] -pub fn normalize_type(type_sql: &str, dialect: &str) -> Option { - if !type_sql.is_ascii() - || !dialect.is_ascii() - || type_sql.bytes().filter(|byte| *byte == b'[').count() > MAX_TYPE_BRACKETS - { - return None; - } - let polyglot = polyglot_dialect(dialect)?; +/// Normalize one type as Python does for the dialect name it hands Polyglot. +pub fn normalize_type( + type_sql: &str, + dialect: &str, +) -> Result { + let name: &str = if dialect.is_empty() { + "generic" + } else { + dialect + }; + let polyglot: Dialect = name + .parse::() + .map(Dialect::get) + .map_err(|_| TypeNormalizationError::UnknownDialect(name.to_owned()))?; let type_dialect: Option = coerce_type_dialect(dialect); match parse_type(type_sql, &polyglot) { - Ok(parsed) => Some(TypeNormalization { + Ok(parsed) => Ok(TypeNormalization { normalized: normalize_parsed(parsed, &polyglot, type_dialect)?, parse_error: None, }), - Err(error) => Some(TypeNormalization { - normalized: normalize_with_fallback(type_sql, type_dialect)?, + Err(error) => Ok(TypeNormalization { + normalized: normalize_with_fallback(type_sql, type_dialect), parse_error: Some(error), }), } diff --git a/crates/sqlbuild-analysis/src/type_system/mod.rs b/crates/sqlbuild-analysis/src/type_system/mod.rs index 89ff092ae4..8c83e15b79 100644 --- a/crates/sqlbuild-analysis/src/type_system/mod.rs +++ b/crates/sqlbuild-analysis/src/type_system/mod.rs @@ -2,6 +2,7 @@ pub(crate) mod _helpers; mod constants; +pub mod errors; pub mod main; pub mod models; diff --git a/crates/sqlbuild-analysis/src/type_system/models.rs b/crates/sqlbuild-analysis/src/type_system/models.rs index 0250342b03..9497d5bf9f 100644 --- a/crates/sqlbuild-analysis/src/type_system/models.rs +++ b/crates/sqlbuild-analysis/src/type_system/models.rs @@ -1,5 +1,7 @@ //! Normalized type shapes, matching Python's `NormalizedType` and `TypeFamily`. +use crate::type_system::constants::ZERO_TEXT; + /// The semantic family of one normalized type. #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum TypeFamily { @@ -45,14 +47,58 @@ pub enum TypeDialect { Tsql, } +/// A Python `int` of any size, held as its canonical base-10 text. +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct PythonInteger(String); + +impl PythonInteger { + /// The integer whose sign and base-10 digits are given. + #[must_use] + pub fn from_digits(negative: bool, digits: &str) -> Self { + let significant: &str = digits.trim_start_matches('0'); + if significant.is_empty() { + return Self("0".to_owned()); + } + Self(if negative { + format!("-{significant}") + } else { + significant.to_owned() + }) + } + + /// Whether the integer is zero, so Python treats it as false. + #[must_use] + pub fn is_zero(&self) -> bool { + self.0 == ZERO_TEXT + } + + /// The integer's canonical base-10 text, as Python's `str(value)` spells it. + #[must_use] + pub fn as_str(&self) -> &str { + &self.0 + } +} + +impl From for PythonInteger { + fn from(value: i64) -> Self { + Self(value.to_string()) + } +} + +impl std::fmt::Display for PythonInteger { + fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + formatter.write_str(&self.0) + } +} + /// One type string's comparison shape. #[derive(Debug, Clone, PartialEq, Eq)] pub struct NormalizedType { pub normalized_name: String, pub family: TypeFamily, - pub precision: Option, - pub scale: Option, - pub length: Option, + pub precision: Option, + pub scale: Option, + pub length: Option, } /// A normalized type and the Polyglot parse error Python logs before its text fallback. diff --git a/crates/sqlbuild-analysis/src/type_system/tests/helpers.rs b/crates/sqlbuild-analysis/src/type_system/tests/helpers.rs index 300ca546a8..cc51b6f245 100644 --- a/crates/sqlbuild-analysis/src/type_system/tests/helpers.rs +++ b/crates/sqlbuild-analysis/src/type_system/tests/helpers.rs @@ -1,15 +1,16 @@ -use crate::type_system::models::TypeNormalization; +use crate::type_system::models::{PythonInteger, TypeNormalization}; pub(super) fn normalization_text(normalization: &TypeNormalization) -> String { - let optional = |value: Option| value.map_or("-".to_owned(), |value| value.to_string()); + let optional = + |value: &Option| value.as_ref().map_or("-".to_owned(), ToString::to_string); let normalized = &normalization.normalized; format!( "{} | {} | {} | {} | {} | {}", normalized.normalized_name, normalized.family.as_str(), - optional(normalized.precision), - optional(normalized.scale), - optional(normalized.length), + optional(&normalized.precision), + optional(&normalized.scale), + optional(&normalized.length), normalization.parse_error.as_deref().unwrap_or("-"), ) } diff --git a/crates/sqlbuild-analysis/src/type_system/tests/test_normalize_type.rs b/crates/sqlbuild-analysis/src/type_system/tests/test_normalize_type.rs index 63ea20f15e..207359e441 100644 --- a/crates/sqlbuild-analysis/src/type_system/tests/test_normalize_type.rs +++ b/crates/sqlbuild-analysis/src/type_system/tests/test_normalize_type.rs @@ -1,3 +1,4 @@ +use crate::type_system::errors::TypeNormalizationError; use crate::type_system::main::normalize_type::normalize_type; use crate::type_system::tests::helpers::normalization_text; use crate::type_system::tests::test_types::{BracketDepthTestCase, NormalizeTypeTestCase}; @@ -9,87 +10,98 @@ fn given_type_strings_when_normalizing_then_python_normalization_is_returned() { description: "integer aliases keep their spelling outside Snowflake and BigQuery", type_sql: "integer", dialect: "duckdb", - expected_normalization: Some("INT | integer | - | - | - | -"), + expected_normalization: Ok("INT | integer | - | - | - | -"), }, NormalizeTypeTestCase { description: "BigQuery integers are INT64", type_sql: "INT", dialect: "bigquery", - expected_normalization: Some("INT64 | integer | - | - | - | -"), + expected_normalization: Ok("INT64 | integer | - | - | - | -"), }, NormalizeTypeTestCase { description: "Snowflake integers are DECIMAL(38,0)", type_sql: "BIGINT", dialect: "snowflake", - expected_normalization: Some("DECIMAL(38,0) | decimal | 38 | 0 | - | -"), + expected_normalization: Ok("DECIMAL(38,0) | decimal | 38 | 0 | - | -"), }, NormalizeTypeTestCase { description: "Snowflake NUMBER is a custom type rewritten to DECIMAL", type_sql: "NUMBER(12, 2)", dialect: "snowflake", - expected_normalization: Some("DECIMAL(12,2) | decimal | 12 | 2 | - | -"), + expected_normalization: Ok("DECIMAL(12,2) | decimal | 12 | 2 | - | -"), }, NormalizeTypeTestCase { description: "Snowflake NUMBER without precision takes the integer default", type_sql: "NUMBER", dialect: "snowflake", - expected_normalization: Some("DECIMAL(38,0) | decimal | 38 | 0 | - | -"), + expected_normalization: Ok("DECIMAL(38,0) | decimal | 38 | 0 | - | -"), }, NormalizeTypeTestCase { description: "Snowflake unbounded text takes the default length", type_sql: "TEXT", dialect: "snowflake", - expected_normalization: Some("VARCHAR(16777216) | string | - | - | 16777216 | -"), + expected_normalization: Ok("VARCHAR(16777216) | string | - | - | 16777216 | -"), }, NormalizeTypeTestCase { description: "Snowflake timestamp aliases", type_sql: "TIMESTAMP_NTZ", dialect: "snowflake", - expected_normalization: Some("TIMESTAMP_NTZ | timestamp | - | - | - | -"), + expected_normalization: Ok("TIMESTAMP_NTZ | timestamp | - | - | - | -"), }, NormalizeTypeTestCase { description: "decimal precision and scale", type_sql: "decimal(10, 2)", dialect: "duckdb", - expected_normalization: Some("DECIMAL(10,2) | decimal | 10 | 2 | - | -"), + expected_normalization: Ok("DECIMAL(10,2) | decimal | 10 | 2 | - | -"), }, NormalizeTypeTestCase { description: "nested types are other", type_sql: "ARRAY>", dialect: "bigquery", - expected_normalization: Some("ARRAY> | other | - | - | - | -"), + expected_normalization: Ok("ARRAY> | other | - | - | - | -"), }, NormalizeTypeTestCase { description: "a parse failure falls back to the text and reports the error", type_sql: "order status", dialect: "generic", - expected_normalization: Some( + expected_normalization: Ok( "ORDERSTATUS | other | - | - | - | Parse error at line 1, column 13: Unexpected token after data type: status", ), }, NormalizeTypeTestCase { - description: "a dialect this build does not include defers", + description: "every Polyglot dialect is normalized natively", type_sql: "INT", dialect: "mysql", - expected_normalization: None, + expected_normalization: Ok("INT | integer | - | - | - | -"), }, NormalizeTypeTestCase { - description: "a dialect Polyglot does not know defers so Python raises", + description: "a dialect Polyglot does not know raises Python's error", type_sql: "INT", dialect: "motherduck", - expected_normalization: None, + expected_normalization: Err("Unknown dialect: motherduck"), }, NormalizeTypeTestCase { - description: "non-ASCII text defers", - type_sql: "caf\u{e9}", + description: "non-ASCII text upper-cases with Python's Unicode mapping", + type_sql: "stra\u{df}e", dialect: "generic", - expected_normalization: None, + expected_normalization: Ok("STRASSE | other | - | - | - | -"), }, NormalizeTypeTestCase { - description: "a parameter beyond i64 defers", - type_sql: "order status(99999999999999999999)", - dialect: "generic", - expected_normalization: None, + description: "a parameter beyond i64 keeps Python's integer", + type_sql: "DECIMAL(99999999999999999999, 2)", + dialect: "duckdb", + expected_normalization: Ok( + "DECIMAL(99999999999999999999,2) | decimal | 99999999999999999999 | 2 | - | \ + Parse error at line 1, column 30: Invalid number: 99999999999999999999", + ), + }, + NormalizeTypeTestCase { + description: "Unicode decimal digits are Python integers", + type_sql: "VARCHAR(\u{663})", + dialect: "snowflake", + expected_normalization: Ok( + "VARCHAR(3) | string | - | - | 3 | Parse error at line 1, column 10: Expected number", + ), }, ]; @@ -98,7 +110,10 @@ fn given_type_strings_when_normalizing_then_python_normalization_is_returned() { normalize_type(test_case.type_sql, test_case.dialect) .as_ref() .map(normalization_text) - .as_deref(), + .map_err(TypeNormalizationError::message) + .as_ref() + .map(String::as_str) + .map_err(String::as_str), test_case.expected_normalization, "{}", test_case.description @@ -107,30 +122,35 @@ fn given_type_strings_when_normalizing_then_python_normalization_is_returned() { } #[test] -fn given_array_suffixes_when_normalizing_on_a_small_stack_then_deep_types_defer() { +fn given_array_suffixes_when_normalizing_on_a_worker_stack_then_python_supported_depths_answer() { let test_cases = [ BracketDepthTestCase { - description: "at the bracket cap, parsed on a 1 MiB debug-build stack", + description: "at the old native bracket cap", depth: 32, expected_native: true, }, BracketDepthTestCase { - description: "one past the bracket cap", + description: "one past the old native bracket cap", depth: 33, - expected_native: false, + expected_native: true, }, BracketDepthTestCase { - description: "far past the bracket cap", - depth: 100_000, - expected_native: false, + description: "a depth the Python wheel also normalizes, within a debug-build worker stack", + depth: 200, + expected_native: true, }, ]; for test_case in test_cases { let type_sql: String = format!("INT{}", "[]".repeat(test_case.depth)); + let expected_name: String = type_sql.clone(); let answered: bool = std::thread::Builder::new() - .stack_size(1024 * 1024) - .spawn(move || normalize_type(&type_sql, "generic").is_some()) + .stack_size(2 * 1024 * 1024) + .spawn(move || { + normalize_type(&type_sql, "duckdb").is_ok_and(|normalization| { + normalization.normalized.normalized_name == expected_name + }) + }) .expect("the test thread starts") .join() .expect("normalization does not overflow the stack"); diff --git a/crates/sqlbuild-analysis/src/type_system/tests/test_python_text.rs b/crates/sqlbuild-analysis/src/type_system/tests/test_python_text.rs index aec6520811..d695a9b51b 100644 --- a/crates/sqlbuild-analysis/src/type_system/tests/test_python_text.rs +++ b/crates/sqlbuild-analysis/src/type_system/tests/test_python_text.rs @@ -1,4 +1,5 @@ -use crate::type_system::_helpers::python_text::{PythonInt, python_int, split_type_and_params}; +use crate::type_system::_helpers::python_text::{python_int, split_type_and_params}; +use crate::type_system::models::PythonInteger; use crate::type_system::tests::test_types::{PythonIntTestCase, SplitTypeTestCase}; #[test] @@ -7,49 +8,49 @@ fn given_parameter_text_when_parsing_as_python_int_then_python_result_is_returne PythonIntTestCase { description: "padded digits", text: " \t42\x1c", - expected_value: PythonInt::Value(42), + expected_value: Some(42), }, PythonIntTestCase { description: "signs", text: "-7", - expected_value: PythonInt::Value(-7), + expected_value: Some(-7), }, PythonIntTestCase { description: "single underscores between digits", text: "+1_000", - expected_value: PythonInt::Value(1000), + expected_value: Some(1000), }, PythonIntTestCase { description: "double underscores", text: "1__0", - expected_value: PythonInt::Invalid, + expected_value: None, }, PythonIntTestCase { description: "leading underscore", text: "_1", - expected_value: PythonInt::Invalid, + expected_value: None, }, PythonIntTestCase { description: "words", text: "MAX", - expected_value: PythonInt::Invalid, + expected_value: None, }, PythonIntTestCase { description: "the smallest i64", text: "-9223372036854775808", - expected_value: PythonInt::Value(i64::MIN), + expected_value: Some(i64::MIN), }, PythonIntTestCase { - description: "beyond i64", - text: "9223372036854775808", - expected_value: PythonInt::TooLarge, + description: "Unicode decimal digits", + text: "\u{663}\u{661}", + expected_value: Some(31), }, ]; for test_case in test_cases { assert_eq!( python_int(test_case.text), - test_case.expected_value, + test_case.expected_value.map(PythonInteger::from), "{}", test_case.description ); @@ -62,39 +63,56 @@ fn given_type_text_when_splitting_then_python_name_and_parameters_are_returned() SplitTypeTestCase { description: "name only", type_sql: "VARCHAR", - expected_split: Some(("VARCHAR", vec![])), + expected_split: ("VARCHAR", vec![]), }, SplitTypeTestCase { description: "parameters skip what int() rejects", type_sql: "DECIMAL(10,X,2)", - expected_split: Some(("DECIMAL", vec![10, 2])), + expected_split: ("DECIMAL", vec!["10", "2"]), }, SplitTypeTestCase { description: "a final newline is allowed by the regex end anchor", type_sql: "NUMBER(5)\n", - expected_split: Some(("NUMBER", vec![5])), + expected_split: ("NUMBER", vec!["5"]), }, SplitTypeTestCase { description: "anything else keeps the whole text", type_sql: "ARRAY", - expected_split: Some(("ARRAY", vec![])), + expected_split: ("ARRAY", vec![]), }, SplitTypeTestCase { description: "nested parentheses keep the whole text", type_sql: "A(1)(2)", - expected_split: Some(("A(1)(2)", vec![])), + expected_split: ("A(1)(2)", vec![]), }, SplitTypeTestCase { - description: "a parameter beyond i64 defers", + description: "a parameter beyond i64 keeps Python's integer", type_sql: "A(99999999999999999999)", - expected_split: None, + expected_split: ("A", vec!["99999999999999999999"]), }, ]; for test_case in test_cases { assert_eq!( - split_type_and_params(test_case.type_sql), - test_case.expected_split, + { + let (name, params) = split_type_and_params(test_case.type_sql); + ( + name, + params + .iter() + .map(|param| param.as_str().to_owned()) + .collect::>(), + ) + }, + ( + test_case.expected_split.0, + test_case + .expected_split + .1 + .into_iter() + .map(str::to_owned) + .collect::>() + ), "{}", test_case.description ); diff --git a/crates/sqlbuild-analysis/src/type_system/tests/test_types.rs b/crates/sqlbuild-analysis/src/type_system/tests/test_types.rs index 6044e68168..f731088453 100644 --- a/crates/sqlbuild-analysis/src/type_system/tests/test_types.rs +++ b/crates/sqlbuild-analysis/src/type_system/tests/test_types.rs @@ -1,23 +1,21 @@ -use crate::type_system::_helpers::python_text::PythonInt; - pub(super) struct NormalizeTypeTestCase { pub(super) description: &'static str, pub(super) type_sql: &'static str, pub(super) dialect: &'static str, - /// `name | family | precision | scale | length | parse error`, or None to defer. - pub(super) expected_normalization: Option<&'static str>, + /// `name | family | precision | scale | length | parse error`, or Python's error. + pub(super) expected_normalization: Result<&'static str, &'static str>, } pub(super) struct PythonIntTestCase { pub(super) description: &'static str, pub(super) text: &'static str, - pub(super) expected_value: PythonInt, + pub(super) expected_value: Option, } pub(super) struct SplitTypeTestCase { pub(super) description: &'static str, pub(super) type_sql: &'static str, - pub(super) expected_split: Option<(&'static str, Vec)>, + pub(super) expected_split: (&'static str, Vec<&'static str>), } pub(super) struct BracketDepthTestCase { diff --git a/crates/sqlbuild-core/src/constants.rs b/crates/sqlbuild-core/src/constants.rs index 423634b200..cfb324eb8c 100644 --- a/crates/sqlbuild-core/src/constants.rs +++ b/crates/sqlbuild-core/src/constants.rs @@ -4,3 +4,5 @@ pub const OPEN_PAREN: &str = "("; pub const CLOSE_PAREN: &str = ")"; /// The error text every caught native panic carries across the boundary. pub const PANIC_MESSAGE: &str = "NativeCompilerError: native SQL compilation panicked"; +/// The prefix every native internal failure carries, so the boundary raises `NativeCompilerError`. +pub const NATIVE_FAILURE_PREFIX: &str = "NativeCompilerError: "; diff --git a/crates/sqlbuild-core/src/panics/main/is_compiler_panic.rs b/crates/sqlbuild-core/src/panics/main/is_compiler_panic.rs index 51b2e937c2..caa8db3575 100644 --- a/crates/sqlbuild-core/src/panics/main/is_compiler_panic.rs +++ b/crates/sqlbuild-core/src/panics/main/is_compiler_panic.rs @@ -1,5 +1,6 @@ -use crate::constants::PANIC_MESSAGE; +use crate::constants::NATIVE_FAILURE_PREFIX; +/// Whether `message` is a caught panic or another native internal failure. pub fn is_compiler_panic(message: &str) -> bool { - message == PANIC_MESSAGE + message.starts_with(NATIVE_FAILURE_PREFIX) } diff --git a/crates/sqlbuild-core/src/panics/main/mod.rs b/crates/sqlbuild-core/src/panics/main/mod.rs index c40fe7bcb0..b25c155466 100644 --- a/crates/sqlbuild-core/src/panics/main/mod.rs +++ b/crates/sqlbuild-core/src/panics/main/mod.rs @@ -1,2 +1,3 @@ pub mod catch_compiler_panic; pub mod is_compiler_panic; +pub mod native_failure; diff --git a/crates/sqlbuild-core/src/panics/main/native_failure.rs b/crates/sqlbuild-core/src/panics/main/native_failure.rs new file mode 100644 index 0000000000..9888ceb7ea --- /dev/null +++ b/crates/sqlbuild-core/src/panics/main/native_failure.rs @@ -0,0 +1,10 @@ +use crate::constants::NATIVE_FAILURE_PREFIX; + +/// An internal native failure the boundary raises as `NativeCompilerError`. +pub fn native_failure(context: &str, reason: &str) -> String { + if reason.starts_with(NATIVE_FAILURE_PREFIX) { + format!("{reason} ({context})") + } else { + format!("{NATIVE_FAILURE_PREFIX}{context}: {reason}") + } +} diff --git a/crates/sqlbuild-core/src/panics/tests/test_panics.rs b/crates/sqlbuild-core/src/panics/tests/test_panics.rs index f0992c1245..ce02e2ff2c 100644 --- a/crates/sqlbuild-core/src/panics/tests/test_panics.rs +++ b/crates/sqlbuild-core/src/panics/tests/test_panics.rs @@ -1,5 +1,6 @@ use crate::panics::main::catch_compiler_panic::catch_compiler_panic; use crate::panics::main::is_compiler_panic::is_compiler_panic; +use crate::panics::main::native_failure::native_failure; use crate::panics::tests::test_types::PanicTestCase; #[test] @@ -11,6 +12,16 @@ fn given_native_failure_when_crossing_python_boundary_then_only_unwinds_become_n operation: || std::panic::panic_any("synthetic compiler failure"), expected_named_error: true, }, + PanicTestCase { + description: "an internal native failure is a named compiler error", + operation: || { + Err(native_failure( + "model analysis of 'orders'", + "a broken invariant", + )) + }, + expected_named_error: true, + }, PanicTestCase { description: "ordinary compiler error keeps its own message", operation: || Err("unknown column 'customer_id'".to_owned()), diff --git a/crates/sqlbuild-core/src/text/_helpers/active_text.rs b/crates/sqlbuild-core/src/text/_helpers/active_text.rs new file mode 100644 index 0000000000..a907ea865f --- /dev/null +++ b/crates/sqlbuild-core/src/text/_helpers/active_text.rs @@ -0,0 +1,28 @@ +//! The running Python's string semantics, recorded once per process. + +use std::sync::OnceLock; + +use crate::text::_helpers::alnum_tables::{ALNUM_TABLES, ALPHA_TABLES, DECIMAL_TABLES}; +use crate::text::_helpers::case_tables::{CASEFOLD_TABLES, IGNORECASE_KEY_TABLES, UPPER_TABLES}; +use crate::text::models::{CleandocMargin, PythonText}; + +static ACTIVE: OnceLock = OnceLock::new(); + +/// Record the running Python's semantics; later calls keep the first value. +pub(crate) fn record(python: PythonText) { + let _ = ACTIVE.set(python); +} + +/// The recorded semantics, or Python 3.12's where none were recorded. +pub(crate) fn active() -> PythonText { + *ACTIVE.get_or_init(|| PythonText { + alnum_ranges: ALNUM_TABLES[0].1, + alpha_ranges: ALPHA_TABLES[0].1, + decimal_ranges: DECIMAL_TABLES[0].1, + casefold_mappings: CASEFOLD_TABLES[0].1, + upper_mappings: UPPER_TABLES[0].1, + ignorecase_keys: IGNORECASE_KEY_TABLES[0].1, + cleandoc_margin: CleandocMargin::Whitespace, + minor_version: 12, + }) +} diff --git a/crates/sqlbuild-core/src/text/_helpers/case_tables.rs b/crates/sqlbuild-core/src/text/_helpers/case_tables.rs new file mode 100644 index 0000000000..91949421ae --- /dev/null +++ b/crates/sqlbuild-core/src/text/_helpers/case_tables.rs @@ -0,0 +1,44 @@ +//! The generated `str.casefold()` and `str.upper()` mappings, per Unicode version. + +/// `(unicodedata.unidata_version, mappings)` of every character `str.casefold()` changes. +pub(crate) const CASEFOLD_TABLES: [(&str, &[(u32, &str)]); 3] = [ + ("15.0.0", include!("../casefold_mappings/unicode_15_0_0.in")), + ("15.1.0", include!("../casefold_mappings/unicode_15_1_0.in")), + ("16.0.0", include!("../casefold_mappings/unicode_16_0_0.in")), +]; + +/// `(unicodedata.unidata_version, mappings)` of every character `str.upper()` changes. +pub(crate) const UPPER_TABLES: [(&str, &[(u32, &str)]); 3] = [ + ("15.0.0", include!("../upper_mappings/unicode_15_0_0.in")), + ("15.1.0", include!("../upper_mappings/unicode_15_1_0.in")), + ("16.0.0", include!("../upper_mappings/unicode_16_0_0.in")), +]; + +/// `(unicodedata.unidata_version, keys)` of every character whose ignorecase key differs. +pub(crate) const IGNORECASE_KEY_TABLES: [(&str, &[(u32, u32)]); 3] = [ + ( + "15.0.0", + include!("../re_ignorecase_keys/unicode_15_0_0.in"), + ), + ( + "15.1.0", + include!("../re_ignorecase_keys/unicode_15_1_0.in"), + ), + ( + "16.0.0", + include!("../re_ignorecase_keys/unicode_16_0_0.in"), + ), +]; + +/// One string with each character replaced by its `mappings` entry, if it has one. +pub(crate) fn mapped(mappings: &[(u32, &str)], text: &str) -> String { + let mut result: String = String::with_capacity(text.len()); + for character in text.chars() { + let code_point: u32 = u32::from(character); + match mappings.binary_search_by_key(&code_point, |(key, _)| *key) { + Ok(index) => result.push_str(mappings[index].1), + Err(_) => result.push(character), + } + } + result +} diff --git a/crates/sqlbuild-core/src/text/_helpers/mod.rs b/crates/sqlbuild-core/src/text/_helpers/mod.rs index ede18696f6..07c6ab70ae 100644 --- a/crates/sqlbuild-core/src/text/_helpers/mod.rs +++ b/crates/sqlbuild-core/src/text/_helpers/mod.rs @@ -1,4 +1,6 @@ +pub(crate) mod active_text; pub(crate) mod alnum_tables; +pub(crate) mod case_tables; pub(crate) mod cleandoc; pub(crate) mod code_point_ranges; pub(crate) mod sequence_matcher; diff --git a/crates/sqlbuild-core/src/text/casefold_mappings/unicode_15_0_0.in b/crates/sqlbuild-core/src/text/casefold_mappings/unicode_15_0_0.in new file mode 100644 index 0000000000..c1553126bb --- /dev/null +++ b/crates/sqlbuild-core/src/text/casefold_mappings/unicode_15_0_0.in @@ -0,0 +1,1534 @@ +// Generated by `scripts/generate_python_char_table.py`; do not edit. +// Every character `str.casefold()` changes in Unicode 15.0.0, in code point order. +&[ + (0x0041, "\u{61}"), + (0x0042, "\u{62}"), + (0x0043, "\u{63}"), + (0x0044, "\u{64}"), + (0x0045, "\u{65}"), + (0x0046, "\u{66}"), + (0x0047, "\u{67}"), + (0x0048, "\u{68}"), + (0x0049, "\u{69}"), + (0x004A, "\u{6a}"), + (0x004B, "\u{6b}"), + (0x004C, "\u{6c}"), + (0x004D, "\u{6d}"), + (0x004E, "\u{6e}"), + (0x004F, "\u{6f}"), + (0x0050, "\u{70}"), + (0x0051, "\u{71}"), + (0x0052, "\u{72}"), + (0x0053, "\u{73}"), + (0x0054, "\u{74}"), + (0x0055, "\u{75}"), + (0x0056, "\u{76}"), + (0x0057, "\u{77}"), + (0x0058, "\u{78}"), + (0x0059, "\u{79}"), + (0x005A, "\u{7a}"), + (0x00B5, "\u{3bc}"), + (0x00C0, "\u{e0}"), + (0x00C1, "\u{e1}"), + (0x00C2, "\u{e2}"), + (0x00C3, "\u{e3}"), + (0x00C4, "\u{e4}"), + (0x00C5, "\u{e5}"), + (0x00C6, "\u{e6}"), + (0x00C7, "\u{e7}"), + (0x00C8, "\u{e8}"), + (0x00C9, "\u{e9}"), + (0x00CA, "\u{ea}"), + (0x00CB, "\u{eb}"), + (0x00CC, "\u{ec}"), + (0x00CD, "\u{ed}"), + (0x00CE, "\u{ee}"), + (0x00CF, "\u{ef}"), + (0x00D0, "\u{f0}"), + (0x00D1, "\u{f1}"), + (0x00D2, "\u{f2}"), + (0x00D3, "\u{f3}"), + (0x00D4, "\u{f4}"), + (0x00D5, "\u{f5}"), + (0x00D6, "\u{f6}"), + (0x00D8, "\u{f8}"), + (0x00D9, "\u{f9}"), + (0x00DA, "\u{fa}"), + (0x00DB, "\u{fb}"), + (0x00DC, "\u{fc}"), + (0x00DD, "\u{fd}"), + (0x00DE, "\u{fe}"), + (0x00DF, "\u{73}\u{73}"), + (0x0100, "\u{101}"), + (0x0102, "\u{103}"), + (0x0104, "\u{105}"), + (0x0106, "\u{107}"), + (0x0108, "\u{109}"), + (0x010A, "\u{10b}"), + (0x010C, "\u{10d}"), + (0x010E, "\u{10f}"), + (0x0110, "\u{111}"), + (0x0112, "\u{113}"), + (0x0114, "\u{115}"), + (0x0116, "\u{117}"), + (0x0118, "\u{119}"), + (0x011A, "\u{11b}"), + (0x011C, "\u{11d}"), + (0x011E, "\u{11f}"), + (0x0120, "\u{121}"), + (0x0122, "\u{123}"), + (0x0124, "\u{125}"), + (0x0126, "\u{127}"), + (0x0128, "\u{129}"), + (0x012A, "\u{12b}"), + (0x012C, "\u{12d}"), + (0x012E, "\u{12f}"), + (0x0130, "\u{69}\u{307}"), + (0x0132, "\u{133}"), + (0x0134, "\u{135}"), + (0x0136, "\u{137}"), + (0x0139, "\u{13a}"), + (0x013B, "\u{13c}"), + (0x013D, "\u{13e}"), + (0x013F, "\u{140}"), + (0x0141, "\u{142}"), + (0x0143, "\u{144}"), + (0x0145, "\u{146}"), + (0x0147, "\u{148}"), + (0x0149, "\u{2bc}\u{6e}"), + (0x014A, "\u{14b}"), + (0x014C, "\u{14d}"), + (0x014E, "\u{14f}"), + (0x0150, "\u{151}"), + (0x0152, "\u{153}"), + (0x0154, "\u{155}"), + (0x0156, "\u{157}"), + (0x0158, "\u{159}"), + (0x015A, "\u{15b}"), + (0x015C, "\u{15d}"), + (0x015E, "\u{15f}"), + (0x0160, "\u{161}"), + (0x0162, "\u{163}"), + (0x0164, "\u{165}"), + (0x0166, "\u{167}"), + (0x0168, "\u{169}"), + (0x016A, "\u{16b}"), + (0x016C, "\u{16d}"), + (0x016E, "\u{16f}"), + (0x0170, "\u{171}"), + (0x0172, "\u{173}"), + (0x0174, "\u{175}"), + (0x0176, "\u{177}"), + (0x0178, "\u{ff}"), + (0x0179, "\u{17a}"), + (0x017B, "\u{17c}"), + (0x017D, "\u{17e}"), + (0x017F, "\u{73}"), + (0x0181, "\u{253}"), + (0x0182, "\u{183}"), + (0x0184, "\u{185}"), + (0x0186, "\u{254}"), + (0x0187, "\u{188}"), + (0x0189, "\u{256}"), + (0x018A, "\u{257}"), + (0x018B, "\u{18c}"), + (0x018E, "\u{1dd}"), + (0x018F, "\u{259}"), + (0x0190, "\u{25b}"), + (0x0191, "\u{192}"), + (0x0193, "\u{260}"), + (0x0194, "\u{263}"), + (0x0196, "\u{269}"), + (0x0197, "\u{268}"), + (0x0198, "\u{199}"), + (0x019C, "\u{26f}"), + (0x019D, "\u{272}"), + (0x019F, "\u{275}"), + (0x01A0, "\u{1a1}"), + (0x01A2, "\u{1a3}"), + (0x01A4, "\u{1a5}"), + (0x01A6, "\u{280}"), + (0x01A7, "\u{1a8}"), + (0x01A9, "\u{283}"), + (0x01AC, "\u{1ad}"), + (0x01AE, "\u{288}"), + (0x01AF, "\u{1b0}"), + (0x01B1, "\u{28a}"), + (0x01B2, "\u{28b}"), + (0x01B3, "\u{1b4}"), + (0x01B5, "\u{1b6}"), + (0x01B7, "\u{292}"), + (0x01B8, "\u{1b9}"), + (0x01BC, "\u{1bd}"), + (0x01C4, "\u{1c6}"), + (0x01C5, "\u{1c6}"), + (0x01C7, "\u{1c9}"), + (0x01C8, "\u{1c9}"), + (0x01CA, "\u{1cc}"), + (0x01CB, "\u{1cc}"), + (0x01CD, "\u{1ce}"), + (0x01CF, "\u{1d0}"), + (0x01D1, "\u{1d2}"), + (0x01D3, "\u{1d4}"), + (0x01D5, "\u{1d6}"), + (0x01D7, "\u{1d8}"), + (0x01D9, "\u{1da}"), + (0x01DB, "\u{1dc}"), + (0x01DE, "\u{1df}"), + (0x01E0, "\u{1e1}"), + (0x01E2, "\u{1e3}"), + (0x01E4, "\u{1e5}"), + (0x01E6, "\u{1e7}"), + (0x01E8, "\u{1e9}"), + (0x01EA, "\u{1eb}"), + (0x01EC, "\u{1ed}"), + (0x01EE, "\u{1ef}"), + (0x01F0, "\u{6a}\u{30c}"), + (0x01F1, "\u{1f3}"), + (0x01F2, "\u{1f3}"), + (0x01F4, "\u{1f5}"), + (0x01F6, "\u{195}"), + (0x01F7, "\u{1bf}"), + (0x01F8, "\u{1f9}"), + (0x01FA, "\u{1fb}"), + (0x01FC, "\u{1fd}"), + (0x01FE, "\u{1ff}"), + (0x0200, "\u{201}"), + (0x0202, "\u{203}"), + (0x0204, "\u{205}"), + (0x0206, "\u{207}"), + (0x0208, "\u{209}"), + (0x020A, "\u{20b}"), + (0x020C, "\u{20d}"), + (0x020E, "\u{20f}"), + (0x0210, "\u{211}"), + (0x0212, "\u{213}"), + (0x0214, "\u{215}"), + (0x0216, "\u{217}"), + (0x0218, "\u{219}"), + (0x021A, "\u{21b}"), + (0x021C, "\u{21d}"), + (0x021E, "\u{21f}"), + (0x0220, "\u{19e}"), + (0x0222, "\u{223}"), + (0x0224, "\u{225}"), + (0x0226, "\u{227}"), + (0x0228, "\u{229}"), + (0x022A, "\u{22b}"), + (0x022C, "\u{22d}"), + (0x022E, "\u{22f}"), + (0x0230, "\u{231}"), + (0x0232, "\u{233}"), + (0x023A, "\u{2c65}"), + (0x023B, "\u{23c}"), + (0x023D, "\u{19a}"), + (0x023E, "\u{2c66}"), + (0x0241, "\u{242}"), + (0x0243, "\u{180}"), + (0x0244, "\u{289}"), + (0x0245, "\u{28c}"), + (0x0246, "\u{247}"), + (0x0248, "\u{249}"), + (0x024A, "\u{24b}"), + (0x024C, "\u{24d}"), + (0x024E, "\u{24f}"), + (0x0345, "\u{3b9}"), + (0x0370, "\u{371}"), + (0x0372, "\u{373}"), + (0x0376, "\u{377}"), + (0x037F, "\u{3f3}"), + (0x0386, "\u{3ac}"), + (0x0388, "\u{3ad}"), + (0x0389, "\u{3ae}"), + (0x038A, "\u{3af}"), + (0x038C, "\u{3cc}"), + (0x038E, "\u{3cd}"), + (0x038F, "\u{3ce}"), + (0x0390, "\u{3b9}\u{308}\u{301}"), + (0x0391, "\u{3b1}"), + (0x0392, "\u{3b2}"), + (0x0393, "\u{3b3}"), + (0x0394, "\u{3b4}"), + (0x0395, "\u{3b5}"), + (0x0396, "\u{3b6}"), + (0x0397, "\u{3b7}"), + (0x0398, "\u{3b8}"), + (0x0399, "\u{3b9}"), + (0x039A, "\u{3ba}"), + (0x039B, "\u{3bb}"), + (0x039C, "\u{3bc}"), + (0x039D, "\u{3bd}"), + (0x039E, "\u{3be}"), + (0x039F, "\u{3bf}"), + (0x03A0, "\u{3c0}"), + (0x03A1, "\u{3c1}"), + (0x03A3, "\u{3c3}"), + (0x03A4, "\u{3c4}"), + (0x03A5, "\u{3c5}"), + (0x03A6, "\u{3c6}"), + (0x03A7, "\u{3c7}"), + (0x03A8, "\u{3c8}"), + (0x03A9, "\u{3c9}"), + (0x03AA, "\u{3ca}"), + (0x03AB, "\u{3cb}"), + (0x03B0, "\u{3c5}\u{308}\u{301}"), + (0x03C2, "\u{3c3}"), + (0x03CF, "\u{3d7}"), + (0x03D0, "\u{3b2}"), + (0x03D1, "\u{3b8}"), + (0x03D5, "\u{3c6}"), + (0x03D6, "\u{3c0}"), + (0x03D8, "\u{3d9}"), + (0x03DA, "\u{3db}"), + (0x03DC, "\u{3dd}"), + (0x03DE, "\u{3df}"), + (0x03E0, "\u{3e1}"), + (0x03E2, "\u{3e3}"), + (0x03E4, "\u{3e5}"), + (0x03E6, "\u{3e7}"), + (0x03E8, "\u{3e9}"), + (0x03EA, "\u{3eb}"), + (0x03EC, "\u{3ed}"), + (0x03EE, "\u{3ef}"), + (0x03F0, "\u{3ba}"), + (0x03F1, "\u{3c1}"), + (0x03F4, "\u{3b8}"), + (0x03F5, "\u{3b5}"), + (0x03F7, "\u{3f8}"), + (0x03F9, "\u{3f2}"), + (0x03FA, "\u{3fb}"), + (0x03FD, "\u{37b}"), + (0x03FE, "\u{37c}"), + (0x03FF, "\u{37d}"), + (0x0400, "\u{450}"), + (0x0401, "\u{451}"), + (0x0402, "\u{452}"), + (0x0403, "\u{453}"), + (0x0404, "\u{454}"), + (0x0405, "\u{455}"), + (0x0406, "\u{456}"), + (0x0407, "\u{457}"), + (0x0408, "\u{458}"), + (0x0409, "\u{459}"), + (0x040A, "\u{45a}"), + (0x040B, "\u{45b}"), + (0x040C, "\u{45c}"), + (0x040D, "\u{45d}"), + (0x040E, "\u{45e}"), + (0x040F, "\u{45f}"), + (0x0410, "\u{430}"), + (0x0411, "\u{431}"), + (0x0412, "\u{432}"), + (0x0413, "\u{433}"), + (0x0414, "\u{434}"), + (0x0415, "\u{435}"), + (0x0416, "\u{436}"), + (0x0417, "\u{437}"), + (0x0418, "\u{438}"), + (0x0419, "\u{439}"), + (0x041A, "\u{43a}"), + (0x041B, "\u{43b}"), + (0x041C, "\u{43c}"), + (0x041D, "\u{43d}"), + (0x041E, "\u{43e}"), + (0x041F, "\u{43f}"), + (0x0420, "\u{440}"), + (0x0421, "\u{441}"), + (0x0422, "\u{442}"), + (0x0423, "\u{443}"), + (0x0424, "\u{444}"), + (0x0425, "\u{445}"), + (0x0426, "\u{446}"), + (0x0427, "\u{447}"), + (0x0428, "\u{448}"), + (0x0429, "\u{449}"), + (0x042A, "\u{44a}"), + (0x042B, "\u{44b}"), + (0x042C, "\u{44c}"), + (0x042D, "\u{44d}"), + (0x042E, "\u{44e}"), + (0x042F, "\u{44f}"), + (0x0460, "\u{461}"), + (0x0462, "\u{463}"), + (0x0464, "\u{465}"), + (0x0466, "\u{467}"), + (0x0468, "\u{469}"), + (0x046A, "\u{46b}"), + (0x046C, "\u{46d}"), + (0x046E, "\u{46f}"), + (0x0470, "\u{471}"), + (0x0472, "\u{473}"), + (0x0474, "\u{475}"), + (0x0476, "\u{477}"), + (0x0478, "\u{479}"), + (0x047A, "\u{47b}"), + (0x047C, "\u{47d}"), + (0x047E, "\u{47f}"), + (0x0480, "\u{481}"), + (0x048A, "\u{48b}"), + (0x048C, "\u{48d}"), + (0x048E, "\u{48f}"), + (0x0490, "\u{491}"), + (0x0492, "\u{493}"), + (0x0494, "\u{495}"), + (0x0496, "\u{497}"), + (0x0498, "\u{499}"), + (0x049A, "\u{49b}"), + (0x049C, "\u{49d}"), + (0x049E, "\u{49f}"), + (0x04A0, "\u{4a1}"), + (0x04A2, "\u{4a3}"), + (0x04A4, "\u{4a5}"), + (0x04A6, "\u{4a7}"), + (0x04A8, "\u{4a9}"), + (0x04AA, "\u{4ab}"), + (0x04AC, "\u{4ad}"), + (0x04AE, "\u{4af}"), + (0x04B0, "\u{4b1}"), + (0x04B2, "\u{4b3}"), + (0x04B4, "\u{4b5}"), + (0x04B6, "\u{4b7}"), + (0x04B8, "\u{4b9}"), + (0x04BA, "\u{4bb}"), + (0x04BC, "\u{4bd}"), + (0x04BE, "\u{4bf}"), + (0x04C0, "\u{4cf}"), + (0x04C1, "\u{4c2}"), + (0x04C3, "\u{4c4}"), + (0x04C5, "\u{4c6}"), + (0x04C7, "\u{4c8}"), + (0x04C9, "\u{4ca}"), + (0x04CB, "\u{4cc}"), + (0x04CD, "\u{4ce}"), + (0x04D0, "\u{4d1}"), + (0x04D2, "\u{4d3}"), + (0x04D4, "\u{4d5}"), + (0x04D6, "\u{4d7}"), + (0x04D8, "\u{4d9}"), + (0x04DA, "\u{4db}"), + (0x04DC, "\u{4dd}"), + (0x04DE, "\u{4df}"), + (0x04E0, "\u{4e1}"), + (0x04E2, "\u{4e3}"), + (0x04E4, "\u{4e5}"), + (0x04E6, "\u{4e7}"), + (0x04E8, "\u{4e9}"), + (0x04EA, "\u{4eb}"), + (0x04EC, "\u{4ed}"), + (0x04EE, "\u{4ef}"), + (0x04F0, "\u{4f1}"), + (0x04F2, "\u{4f3}"), + (0x04F4, "\u{4f5}"), + (0x04F6, "\u{4f7}"), + (0x04F8, "\u{4f9}"), + (0x04FA, "\u{4fb}"), + (0x04FC, "\u{4fd}"), + (0x04FE, "\u{4ff}"), + (0x0500, "\u{501}"), + (0x0502, "\u{503}"), + (0x0504, "\u{505}"), + (0x0506, "\u{507}"), + (0x0508, "\u{509}"), + (0x050A, "\u{50b}"), + (0x050C, "\u{50d}"), + (0x050E, "\u{50f}"), + (0x0510, "\u{511}"), + (0x0512, "\u{513}"), + (0x0514, "\u{515}"), + (0x0516, "\u{517}"), + (0x0518, "\u{519}"), + (0x051A, "\u{51b}"), + (0x051C, "\u{51d}"), + (0x051E, "\u{51f}"), + (0x0520, "\u{521}"), + (0x0522, "\u{523}"), + (0x0524, "\u{525}"), + (0x0526, "\u{527}"), + (0x0528, "\u{529}"), + (0x052A, "\u{52b}"), + (0x052C, "\u{52d}"), + (0x052E, "\u{52f}"), + (0x0531, "\u{561}"), + (0x0532, "\u{562}"), + (0x0533, "\u{563}"), + (0x0534, "\u{564}"), + (0x0535, "\u{565}"), + (0x0536, "\u{566}"), + (0x0537, "\u{567}"), + (0x0538, "\u{568}"), + (0x0539, "\u{569}"), + (0x053A, "\u{56a}"), + (0x053B, "\u{56b}"), + (0x053C, "\u{56c}"), + (0x053D, "\u{56d}"), + (0x053E, "\u{56e}"), + (0x053F, "\u{56f}"), + (0x0540, "\u{570}"), + (0x0541, "\u{571}"), + (0x0542, "\u{572}"), + (0x0543, "\u{573}"), + (0x0544, "\u{574}"), + (0x0545, "\u{575}"), + (0x0546, "\u{576}"), + (0x0547, "\u{577}"), + (0x0548, "\u{578}"), + (0x0549, "\u{579}"), + (0x054A, "\u{57a}"), + (0x054B, "\u{57b}"), + (0x054C, "\u{57c}"), + (0x054D, "\u{57d}"), + (0x054E, "\u{57e}"), + (0x054F, "\u{57f}"), + (0x0550, "\u{580}"), + (0x0551, "\u{581}"), + (0x0552, "\u{582}"), + (0x0553, "\u{583}"), + (0x0554, "\u{584}"), + (0x0555, "\u{585}"), + (0x0556, "\u{586}"), + (0x0587, "\u{565}\u{582}"), + (0x10A0, "\u{2d00}"), + (0x10A1, "\u{2d01}"), + (0x10A2, "\u{2d02}"), + (0x10A3, "\u{2d03}"), + (0x10A4, "\u{2d04}"), + (0x10A5, "\u{2d05}"), + (0x10A6, "\u{2d06}"), + (0x10A7, "\u{2d07}"), + (0x10A8, "\u{2d08}"), + (0x10A9, "\u{2d09}"), + (0x10AA, "\u{2d0a}"), + (0x10AB, "\u{2d0b}"), + (0x10AC, "\u{2d0c}"), + (0x10AD, "\u{2d0d}"), + (0x10AE, "\u{2d0e}"), + (0x10AF, "\u{2d0f}"), + (0x10B0, "\u{2d10}"), + (0x10B1, "\u{2d11}"), + (0x10B2, "\u{2d12}"), + (0x10B3, "\u{2d13}"), + (0x10B4, "\u{2d14}"), + (0x10B5, "\u{2d15}"), + (0x10B6, "\u{2d16}"), + (0x10B7, "\u{2d17}"), + (0x10B8, "\u{2d18}"), + (0x10B9, "\u{2d19}"), + (0x10BA, "\u{2d1a}"), + (0x10BB, "\u{2d1b}"), + (0x10BC, "\u{2d1c}"), + (0x10BD, "\u{2d1d}"), + (0x10BE, "\u{2d1e}"), + (0x10BF, "\u{2d1f}"), + (0x10C0, "\u{2d20}"), + (0x10C1, "\u{2d21}"), + (0x10C2, "\u{2d22}"), + (0x10C3, "\u{2d23}"), + (0x10C4, "\u{2d24}"), + (0x10C5, "\u{2d25}"), + (0x10C7, "\u{2d27}"), + (0x10CD, "\u{2d2d}"), + (0x13F8, "\u{13f0}"), + (0x13F9, "\u{13f1}"), + (0x13FA, "\u{13f2}"), + (0x13FB, "\u{13f3}"), + (0x13FC, "\u{13f4}"), + (0x13FD, "\u{13f5}"), + (0x1C80, "\u{432}"), + (0x1C81, "\u{434}"), + (0x1C82, "\u{43e}"), + (0x1C83, "\u{441}"), + (0x1C84, "\u{442}"), + (0x1C85, "\u{442}"), + (0x1C86, "\u{44a}"), + (0x1C87, "\u{463}"), + (0x1C88, "\u{a64b}"), + (0x1C90, "\u{10d0}"), + (0x1C91, "\u{10d1}"), + (0x1C92, "\u{10d2}"), + (0x1C93, "\u{10d3}"), + (0x1C94, "\u{10d4}"), + (0x1C95, "\u{10d5}"), + (0x1C96, "\u{10d6}"), + (0x1C97, "\u{10d7}"), + (0x1C98, "\u{10d8}"), + (0x1C99, "\u{10d9}"), + (0x1C9A, "\u{10da}"), + (0x1C9B, "\u{10db}"), + (0x1C9C, "\u{10dc}"), + (0x1C9D, "\u{10dd}"), + (0x1C9E, "\u{10de}"), + (0x1C9F, "\u{10df}"), + (0x1CA0, "\u{10e0}"), + (0x1CA1, "\u{10e1}"), + (0x1CA2, "\u{10e2}"), + (0x1CA3, "\u{10e3}"), + (0x1CA4, "\u{10e4}"), + (0x1CA5, "\u{10e5}"), + (0x1CA6, "\u{10e6}"), + (0x1CA7, "\u{10e7}"), + (0x1CA8, "\u{10e8}"), + (0x1CA9, "\u{10e9}"), + (0x1CAA, "\u{10ea}"), + (0x1CAB, "\u{10eb}"), + (0x1CAC, "\u{10ec}"), + (0x1CAD, "\u{10ed}"), + (0x1CAE, "\u{10ee}"), + (0x1CAF, "\u{10ef}"), + (0x1CB0, "\u{10f0}"), + (0x1CB1, "\u{10f1}"), + (0x1CB2, "\u{10f2}"), + (0x1CB3, "\u{10f3}"), + (0x1CB4, "\u{10f4}"), + (0x1CB5, "\u{10f5}"), + (0x1CB6, "\u{10f6}"), + (0x1CB7, "\u{10f7}"), + (0x1CB8, "\u{10f8}"), + (0x1CB9, "\u{10f9}"), + (0x1CBA, "\u{10fa}"), + (0x1CBD, "\u{10fd}"), + (0x1CBE, "\u{10fe}"), + (0x1CBF, "\u{10ff}"), + (0x1E00, "\u{1e01}"), + (0x1E02, "\u{1e03}"), + (0x1E04, "\u{1e05}"), + (0x1E06, "\u{1e07}"), + (0x1E08, "\u{1e09}"), + (0x1E0A, "\u{1e0b}"), + (0x1E0C, "\u{1e0d}"), + (0x1E0E, "\u{1e0f}"), + (0x1E10, "\u{1e11}"), + (0x1E12, "\u{1e13}"), + (0x1E14, "\u{1e15}"), + (0x1E16, "\u{1e17}"), + (0x1E18, "\u{1e19}"), + (0x1E1A, "\u{1e1b}"), + (0x1E1C, "\u{1e1d}"), + (0x1E1E, "\u{1e1f}"), + (0x1E20, "\u{1e21}"), + (0x1E22, "\u{1e23}"), + (0x1E24, "\u{1e25}"), + (0x1E26, "\u{1e27}"), + (0x1E28, "\u{1e29}"), + (0x1E2A, "\u{1e2b}"), + (0x1E2C, "\u{1e2d}"), + (0x1E2E, "\u{1e2f}"), + (0x1E30, "\u{1e31}"), + (0x1E32, "\u{1e33}"), + (0x1E34, "\u{1e35}"), + (0x1E36, "\u{1e37}"), + (0x1E38, "\u{1e39}"), + (0x1E3A, "\u{1e3b}"), + (0x1E3C, "\u{1e3d}"), + (0x1E3E, "\u{1e3f}"), + (0x1E40, "\u{1e41}"), + (0x1E42, "\u{1e43}"), + (0x1E44, "\u{1e45}"), + (0x1E46, "\u{1e47}"), + (0x1E48, "\u{1e49}"), + (0x1E4A, "\u{1e4b}"), + (0x1E4C, "\u{1e4d}"), + (0x1E4E, "\u{1e4f}"), + (0x1E50, "\u{1e51}"), + (0x1E52, "\u{1e53}"), + (0x1E54, "\u{1e55}"), + (0x1E56, "\u{1e57}"), + (0x1E58, "\u{1e59}"), + (0x1E5A, "\u{1e5b}"), + (0x1E5C, "\u{1e5d}"), + (0x1E5E, "\u{1e5f}"), + (0x1E60, "\u{1e61}"), + (0x1E62, "\u{1e63}"), + (0x1E64, "\u{1e65}"), + (0x1E66, "\u{1e67}"), + (0x1E68, "\u{1e69}"), + (0x1E6A, "\u{1e6b}"), + (0x1E6C, "\u{1e6d}"), + (0x1E6E, "\u{1e6f}"), + (0x1E70, "\u{1e71}"), + (0x1E72, "\u{1e73}"), + (0x1E74, "\u{1e75}"), + (0x1E76, "\u{1e77}"), + (0x1E78, "\u{1e79}"), + (0x1E7A, "\u{1e7b}"), + (0x1E7C, "\u{1e7d}"), + (0x1E7E, "\u{1e7f}"), + (0x1E80, "\u{1e81}"), + (0x1E82, "\u{1e83}"), + (0x1E84, "\u{1e85}"), + (0x1E86, "\u{1e87}"), + (0x1E88, "\u{1e89}"), + (0x1E8A, "\u{1e8b}"), + (0x1E8C, "\u{1e8d}"), + (0x1E8E, "\u{1e8f}"), + (0x1E90, "\u{1e91}"), + (0x1E92, "\u{1e93}"), + (0x1E94, "\u{1e95}"), + (0x1E96, "\u{68}\u{331}"), + (0x1E97, "\u{74}\u{308}"), + (0x1E98, "\u{77}\u{30a}"), + (0x1E99, "\u{79}\u{30a}"), + (0x1E9A, "\u{61}\u{2be}"), + (0x1E9B, "\u{1e61}"), + (0x1E9E, "\u{73}\u{73}"), + (0x1EA0, "\u{1ea1}"), + (0x1EA2, "\u{1ea3}"), + (0x1EA4, "\u{1ea5}"), + (0x1EA6, "\u{1ea7}"), + (0x1EA8, "\u{1ea9}"), + (0x1EAA, "\u{1eab}"), + (0x1EAC, "\u{1ead}"), + (0x1EAE, "\u{1eaf}"), + (0x1EB0, "\u{1eb1}"), + (0x1EB2, "\u{1eb3}"), + (0x1EB4, "\u{1eb5}"), + (0x1EB6, "\u{1eb7}"), + (0x1EB8, "\u{1eb9}"), + (0x1EBA, "\u{1ebb}"), + (0x1EBC, "\u{1ebd}"), + (0x1EBE, "\u{1ebf}"), + (0x1EC0, "\u{1ec1}"), + (0x1EC2, "\u{1ec3}"), + (0x1EC4, "\u{1ec5}"), + (0x1EC6, "\u{1ec7}"), + (0x1EC8, "\u{1ec9}"), + (0x1ECA, "\u{1ecb}"), + (0x1ECC, "\u{1ecd}"), + (0x1ECE, "\u{1ecf}"), + (0x1ED0, "\u{1ed1}"), + (0x1ED2, "\u{1ed3}"), + (0x1ED4, "\u{1ed5}"), + (0x1ED6, "\u{1ed7}"), + (0x1ED8, "\u{1ed9}"), + (0x1EDA, "\u{1edb}"), + (0x1EDC, "\u{1edd}"), + (0x1EDE, "\u{1edf}"), + (0x1EE0, "\u{1ee1}"), + (0x1EE2, "\u{1ee3}"), + (0x1EE4, "\u{1ee5}"), + (0x1EE6, "\u{1ee7}"), + (0x1EE8, "\u{1ee9}"), + (0x1EEA, "\u{1eeb}"), + (0x1EEC, "\u{1eed}"), + (0x1EEE, "\u{1eef}"), + (0x1EF0, "\u{1ef1}"), + (0x1EF2, "\u{1ef3}"), + (0x1EF4, "\u{1ef5}"), + (0x1EF6, "\u{1ef7}"), + (0x1EF8, "\u{1ef9}"), + (0x1EFA, "\u{1efb}"), + (0x1EFC, "\u{1efd}"), + (0x1EFE, "\u{1eff}"), + (0x1F08, "\u{1f00}"), + (0x1F09, "\u{1f01}"), + (0x1F0A, "\u{1f02}"), + (0x1F0B, "\u{1f03}"), + (0x1F0C, "\u{1f04}"), + (0x1F0D, "\u{1f05}"), + (0x1F0E, "\u{1f06}"), + (0x1F0F, "\u{1f07}"), + (0x1F18, "\u{1f10}"), + (0x1F19, "\u{1f11}"), + (0x1F1A, "\u{1f12}"), + (0x1F1B, "\u{1f13}"), + (0x1F1C, "\u{1f14}"), + (0x1F1D, "\u{1f15}"), + (0x1F28, "\u{1f20}"), + (0x1F29, "\u{1f21}"), + (0x1F2A, "\u{1f22}"), + (0x1F2B, "\u{1f23}"), + (0x1F2C, "\u{1f24}"), + (0x1F2D, "\u{1f25}"), + (0x1F2E, "\u{1f26}"), + (0x1F2F, "\u{1f27}"), + (0x1F38, "\u{1f30}"), + (0x1F39, "\u{1f31}"), + (0x1F3A, "\u{1f32}"), + (0x1F3B, "\u{1f33}"), + (0x1F3C, "\u{1f34}"), + (0x1F3D, "\u{1f35}"), + (0x1F3E, "\u{1f36}"), + (0x1F3F, "\u{1f37}"), + (0x1F48, "\u{1f40}"), + (0x1F49, "\u{1f41}"), + (0x1F4A, "\u{1f42}"), + (0x1F4B, "\u{1f43}"), + (0x1F4C, "\u{1f44}"), + (0x1F4D, "\u{1f45}"), + (0x1F50, "\u{3c5}\u{313}"), + (0x1F52, "\u{3c5}\u{313}\u{300}"), + (0x1F54, "\u{3c5}\u{313}\u{301}"), + (0x1F56, "\u{3c5}\u{313}\u{342}"), + (0x1F59, "\u{1f51}"), + (0x1F5B, "\u{1f53}"), + (0x1F5D, "\u{1f55}"), + (0x1F5F, "\u{1f57}"), + (0x1F68, "\u{1f60}"), + (0x1F69, "\u{1f61}"), + (0x1F6A, "\u{1f62}"), + (0x1F6B, "\u{1f63}"), + (0x1F6C, "\u{1f64}"), + (0x1F6D, "\u{1f65}"), + (0x1F6E, "\u{1f66}"), + (0x1F6F, "\u{1f67}"), + (0x1F80, "\u{1f00}\u{3b9}"), + (0x1F81, "\u{1f01}\u{3b9}"), + (0x1F82, "\u{1f02}\u{3b9}"), + (0x1F83, "\u{1f03}\u{3b9}"), + (0x1F84, "\u{1f04}\u{3b9}"), + (0x1F85, "\u{1f05}\u{3b9}"), + (0x1F86, "\u{1f06}\u{3b9}"), + (0x1F87, "\u{1f07}\u{3b9}"), + (0x1F88, "\u{1f00}\u{3b9}"), + (0x1F89, "\u{1f01}\u{3b9}"), + (0x1F8A, "\u{1f02}\u{3b9}"), + (0x1F8B, "\u{1f03}\u{3b9}"), + (0x1F8C, "\u{1f04}\u{3b9}"), + (0x1F8D, "\u{1f05}\u{3b9}"), + (0x1F8E, "\u{1f06}\u{3b9}"), + (0x1F8F, "\u{1f07}\u{3b9}"), + (0x1F90, "\u{1f20}\u{3b9}"), + (0x1F91, "\u{1f21}\u{3b9}"), + (0x1F92, "\u{1f22}\u{3b9}"), + (0x1F93, "\u{1f23}\u{3b9}"), + (0x1F94, "\u{1f24}\u{3b9}"), + (0x1F95, "\u{1f25}\u{3b9}"), + (0x1F96, "\u{1f26}\u{3b9}"), + (0x1F97, "\u{1f27}\u{3b9}"), + (0x1F98, "\u{1f20}\u{3b9}"), + (0x1F99, "\u{1f21}\u{3b9}"), + (0x1F9A, "\u{1f22}\u{3b9}"), + (0x1F9B, "\u{1f23}\u{3b9}"), + (0x1F9C, "\u{1f24}\u{3b9}"), + (0x1F9D, "\u{1f25}\u{3b9}"), + (0x1F9E, "\u{1f26}\u{3b9}"), + (0x1F9F, "\u{1f27}\u{3b9}"), + (0x1FA0, "\u{1f60}\u{3b9}"), + (0x1FA1, "\u{1f61}\u{3b9}"), + (0x1FA2, "\u{1f62}\u{3b9}"), + (0x1FA3, "\u{1f63}\u{3b9}"), + (0x1FA4, "\u{1f64}\u{3b9}"), + (0x1FA5, "\u{1f65}\u{3b9}"), + (0x1FA6, "\u{1f66}\u{3b9}"), + (0x1FA7, "\u{1f67}\u{3b9}"), + (0x1FA8, "\u{1f60}\u{3b9}"), + (0x1FA9, "\u{1f61}\u{3b9}"), + (0x1FAA, "\u{1f62}\u{3b9}"), + (0x1FAB, "\u{1f63}\u{3b9}"), + (0x1FAC, "\u{1f64}\u{3b9}"), + (0x1FAD, "\u{1f65}\u{3b9}"), + (0x1FAE, "\u{1f66}\u{3b9}"), + (0x1FAF, "\u{1f67}\u{3b9}"), + (0x1FB2, "\u{1f70}\u{3b9}"), + (0x1FB3, "\u{3b1}\u{3b9}"), + (0x1FB4, "\u{3ac}\u{3b9}"), + (0x1FB6, "\u{3b1}\u{342}"), + (0x1FB7, "\u{3b1}\u{342}\u{3b9}"), + (0x1FB8, "\u{1fb0}"), + (0x1FB9, "\u{1fb1}"), + (0x1FBA, "\u{1f70}"), + (0x1FBB, "\u{1f71}"), + (0x1FBC, "\u{3b1}\u{3b9}"), + (0x1FBE, "\u{3b9}"), + (0x1FC2, "\u{1f74}\u{3b9}"), + (0x1FC3, "\u{3b7}\u{3b9}"), + (0x1FC4, "\u{3ae}\u{3b9}"), + (0x1FC6, "\u{3b7}\u{342}"), + (0x1FC7, "\u{3b7}\u{342}\u{3b9}"), + (0x1FC8, "\u{1f72}"), + (0x1FC9, "\u{1f73}"), + (0x1FCA, "\u{1f74}"), + (0x1FCB, "\u{1f75}"), + (0x1FCC, "\u{3b7}\u{3b9}"), + (0x1FD2, "\u{3b9}\u{308}\u{300}"), + (0x1FD3, "\u{3b9}\u{308}\u{301}"), + (0x1FD6, "\u{3b9}\u{342}"), + (0x1FD7, "\u{3b9}\u{308}\u{342}"), + (0x1FD8, "\u{1fd0}"), + (0x1FD9, "\u{1fd1}"), + (0x1FDA, "\u{1f76}"), + (0x1FDB, "\u{1f77}"), + (0x1FE2, "\u{3c5}\u{308}\u{300}"), + (0x1FE3, "\u{3c5}\u{308}\u{301}"), + (0x1FE4, "\u{3c1}\u{313}"), + (0x1FE6, "\u{3c5}\u{342}"), + (0x1FE7, "\u{3c5}\u{308}\u{342}"), + (0x1FE8, "\u{1fe0}"), + (0x1FE9, "\u{1fe1}"), + (0x1FEA, "\u{1f7a}"), + (0x1FEB, "\u{1f7b}"), + (0x1FEC, "\u{1fe5}"), + (0x1FF2, "\u{1f7c}\u{3b9}"), + (0x1FF3, "\u{3c9}\u{3b9}"), + (0x1FF4, "\u{3ce}\u{3b9}"), + (0x1FF6, "\u{3c9}\u{342}"), + (0x1FF7, "\u{3c9}\u{342}\u{3b9}"), + (0x1FF8, "\u{1f78}"), + (0x1FF9, "\u{1f79}"), + (0x1FFA, "\u{1f7c}"), + (0x1FFB, "\u{1f7d}"), + (0x1FFC, "\u{3c9}\u{3b9}"), + (0x2126, "\u{3c9}"), + (0x212A, "\u{6b}"), + (0x212B, "\u{e5}"), + (0x2132, "\u{214e}"), + (0x2160, "\u{2170}"), + (0x2161, "\u{2171}"), + (0x2162, "\u{2172}"), + (0x2163, "\u{2173}"), + (0x2164, "\u{2174}"), + (0x2165, "\u{2175}"), + (0x2166, "\u{2176}"), + (0x2167, "\u{2177}"), + (0x2168, "\u{2178}"), + (0x2169, "\u{2179}"), + (0x216A, "\u{217a}"), + (0x216B, "\u{217b}"), + (0x216C, "\u{217c}"), + (0x216D, "\u{217d}"), + (0x216E, "\u{217e}"), + (0x216F, "\u{217f}"), + (0x2183, "\u{2184}"), + (0x24B6, "\u{24d0}"), + (0x24B7, "\u{24d1}"), + (0x24B8, "\u{24d2}"), + (0x24B9, "\u{24d3}"), + (0x24BA, "\u{24d4}"), + (0x24BB, "\u{24d5}"), + (0x24BC, "\u{24d6}"), + (0x24BD, "\u{24d7}"), + (0x24BE, "\u{24d8}"), + (0x24BF, "\u{24d9}"), + (0x24C0, "\u{24da}"), + (0x24C1, "\u{24db}"), + (0x24C2, "\u{24dc}"), + (0x24C3, "\u{24dd}"), + (0x24C4, "\u{24de}"), + (0x24C5, "\u{24df}"), + (0x24C6, "\u{24e0}"), + (0x24C7, "\u{24e1}"), + (0x24C8, "\u{24e2}"), + (0x24C9, "\u{24e3}"), + (0x24CA, "\u{24e4}"), + (0x24CB, "\u{24e5}"), + (0x24CC, "\u{24e6}"), + (0x24CD, "\u{24e7}"), + (0x24CE, "\u{24e8}"), + (0x24CF, "\u{24e9}"), + (0x2C00, "\u{2c30}"), + (0x2C01, "\u{2c31}"), + (0x2C02, "\u{2c32}"), + (0x2C03, "\u{2c33}"), + (0x2C04, "\u{2c34}"), + (0x2C05, "\u{2c35}"), + (0x2C06, "\u{2c36}"), + (0x2C07, "\u{2c37}"), + (0x2C08, "\u{2c38}"), + (0x2C09, "\u{2c39}"), + (0x2C0A, "\u{2c3a}"), + (0x2C0B, "\u{2c3b}"), + (0x2C0C, "\u{2c3c}"), + (0x2C0D, "\u{2c3d}"), + (0x2C0E, "\u{2c3e}"), + (0x2C0F, "\u{2c3f}"), + (0x2C10, "\u{2c40}"), + (0x2C11, "\u{2c41}"), + (0x2C12, "\u{2c42}"), + (0x2C13, "\u{2c43}"), + (0x2C14, "\u{2c44}"), + (0x2C15, "\u{2c45}"), + (0x2C16, "\u{2c46}"), + (0x2C17, "\u{2c47}"), + (0x2C18, "\u{2c48}"), + (0x2C19, "\u{2c49}"), + (0x2C1A, "\u{2c4a}"), + (0x2C1B, "\u{2c4b}"), + (0x2C1C, "\u{2c4c}"), + (0x2C1D, "\u{2c4d}"), + (0x2C1E, "\u{2c4e}"), + (0x2C1F, "\u{2c4f}"), + (0x2C20, "\u{2c50}"), + (0x2C21, "\u{2c51}"), + (0x2C22, "\u{2c52}"), + (0x2C23, "\u{2c53}"), + (0x2C24, "\u{2c54}"), + (0x2C25, "\u{2c55}"), + (0x2C26, "\u{2c56}"), + (0x2C27, "\u{2c57}"), + (0x2C28, "\u{2c58}"), + (0x2C29, "\u{2c59}"), + (0x2C2A, "\u{2c5a}"), + (0x2C2B, "\u{2c5b}"), + (0x2C2C, "\u{2c5c}"), + (0x2C2D, "\u{2c5d}"), + (0x2C2E, "\u{2c5e}"), + (0x2C2F, "\u{2c5f}"), + (0x2C60, "\u{2c61}"), + (0x2C62, "\u{26b}"), + (0x2C63, "\u{1d7d}"), + (0x2C64, "\u{27d}"), + (0x2C67, "\u{2c68}"), + (0x2C69, "\u{2c6a}"), + (0x2C6B, "\u{2c6c}"), + (0x2C6D, "\u{251}"), + (0x2C6E, "\u{271}"), + (0x2C6F, "\u{250}"), + (0x2C70, "\u{252}"), + (0x2C72, "\u{2c73}"), + (0x2C75, "\u{2c76}"), + (0x2C7E, "\u{23f}"), + (0x2C7F, "\u{240}"), + (0x2C80, "\u{2c81}"), + (0x2C82, "\u{2c83}"), + (0x2C84, "\u{2c85}"), + (0x2C86, "\u{2c87}"), + (0x2C88, "\u{2c89}"), + (0x2C8A, "\u{2c8b}"), + (0x2C8C, "\u{2c8d}"), + (0x2C8E, "\u{2c8f}"), + (0x2C90, "\u{2c91}"), + (0x2C92, "\u{2c93}"), + (0x2C94, "\u{2c95}"), + (0x2C96, "\u{2c97}"), + (0x2C98, "\u{2c99}"), + (0x2C9A, "\u{2c9b}"), + (0x2C9C, "\u{2c9d}"), + (0x2C9E, "\u{2c9f}"), + (0x2CA0, "\u{2ca1}"), + (0x2CA2, "\u{2ca3}"), + (0x2CA4, "\u{2ca5}"), + (0x2CA6, "\u{2ca7}"), + (0x2CA8, "\u{2ca9}"), + (0x2CAA, "\u{2cab}"), + (0x2CAC, "\u{2cad}"), + (0x2CAE, "\u{2caf}"), + (0x2CB0, "\u{2cb1}"), + (0x2CB2, "\u{2cb3}"), + (0x2CB4, "\u{2cb5}"), + (0x2CB6, "\u{2cb7}"), + (0x2CB8, "\u{2cb9}"), + (0x2CBA, "\u{2cbb}"), + (0x2CBC, "\u{2cbd}"), + (0x2CBE, "\u{2cbf}"), + (0x2CC0, "\u{2cc1}"), + (0x2CC2, "\u{2cc3}"), + (0x2CC4, "\u{2cc5}"), + (0x2CC6, "\u{2cc7}"), + (0x2CC8, "\u{2cc9}"), + (0x2CCA, "\u{2ccb}"), + (0x2CCC, "\u{2ccd}"), + (0x2CCE, "\u{2ccf}"), + (0x2CD0, "\u{2cd1}"), + (0x2CD2, "\u{2cd3}"), + (0x2CD4, "\u{2cd5}"), + (0x2CD6, "\u{2cd7}"), + (0x2CD8, "\u{2cd9}"), + (0x2CDA, "\u{2cdb}"), + (0x2CDC, "\u{2cdd}"), + (0x2CDE, "\u{2cdf}"), + (0x2CE0, "\u{2ce1}"), + (0x2CE2, "\u{2ce3}"), + (0x2CEB, "\u{2cec}"), + (0x2CED, "\u{2cee}"), + (0x2CF2, "\u{2cf3}"), + (0xA640, "\u{a641}"), + (0xA642, "\u{a643}"), + (0xA644, "\u{a645}"), + (0xA646, "\u{a647}"), + (0xA648, "\u{a649}"), + (0xA64A, "\u{a64b}"), + (0xA64C, "\u{a64d}"), + (0xA64E, "\u{a64f}"), + (0xA650, "\u{a651}"), + (0xA652, "\u{a653}"), + (0xA654, "\u{a655}"), + (0xA656, "\u{a657}"), + (0xA658, "\u{a659}"), + (0xA65A, "\u{a65b}"), + (0xA65C, "\u{a65d}"), + (0xA65E, "\u{a65f}"), + (0xA660, "\u{a661}"), + (0xA662, "\u{a663}"), + (0xA664, "\u{a665}"), + (0xA666, "\u{a667}"), + (0xA668, "\u{a669}"), + (0xA66A, "\u{a66b}"), + (0xA66C, "\u{a66d}"), + (0xA680, "\u{a681}"), + (0xA682, "\u{a683}"), + (0xA684, "\u{a685}"), + (0xA686, "\u{a687}"), + (0xA688, "\u{a689}"), + (0xA68A, "\u{a68b}"), + (0xA68C, "\u{a68d}"), + (0xA68E, "\u{a68f}"), + (0xA690, "\u{a691}"), + (0xA692, "\u{a693}"), + (0xA694, "\u{a695}"), + (0xA696, "\u{a697}"), + (0xA698, "\u{a699}"), + (0xA69A, "\u{a69b}"), + (0xA722, "\u{a723}"), + (0xA724, "\u{a725}"), + (0xA726, "\u{a727}"), + (0xA728, "\u{a729}"), + (0xA72A, "\u{a72b}"), + (0xA72C, "\u{a72d}"), + (0xA72E, "\u{a72f}"), + (0xA732, "\u{a733}"), + (0xA734, "\u{a735}"), + (0xA736, "\u{a737}"), + (0xA738, "\u{a739}"), + (0xA73A, "\u{a73b}"), + (0xA73C, "\u{a73d}"), + (0xA73E, "\u{a73f}"), + (0xA740, "\u{a741}"), + (0xA742, "\u{a743}"), + (0xA744, "\u{a745}"), + (0xA746, "\u{a747}"), + (0xA748, "\u{a749}"), + (0xA74A, "\u{a74b}"), + (0xA74C, "\u{a74d}"), + (0xA74E, "\u{a74f}"), + (0xA750, "\u{a751}"), + (0xA752, "\u{a753}"), + (0xA754, "\u{a755}"), + (0xA756, "\u{a757}"), + (0xA758, "\u{a759}"), + (0xA75A, "\u{a75b}"), + (0xA75C, "\u{a75d}"), + (0xA75E, "\u{a75f}"), + (0xA760, "\u{a761}"), + (0xA762, "\u{a763}"), + (0xA764, "\u{a765}"), + (0xA766, "\u{a767}"), + (0xA768, "\u{a769}"), + (0xA76A, "\u{a76b}"), + (0xA76C, "\u{a76d}"), + (0xA76E, "\u{a76f}"), + (0xA779, "\u{a77a}"), + (0xA77B, "\u{a77c}"), + (0xA77D, "\u{1d79}"), + (0xA77E, "\u{a77f}"), + (0xA780, "\u{a781}"), + (0xA782, "\u{a783}"), + (0xA784, "\u{a785}"), + (0xA786, "\u{a787}"), + (0xA78B, "\u{a78c}"), + (0xA78D, "\u{265}"), + (0xA790, "\u{a791}"), + (0xA792, "\u{a793}"), + (0xA796, "\u{a797}"), + (0xA798, "\u{a799}"), + (0xA79A, "\u{a79b}"), + (0xA79C, "\u{a79d}"), + (0xA79E, "\u{a79f}"), + (0xA7A0, "\u{a7a1}"), + (0xA7A2, "\u{a7a3}"), + (0xA7A4, "\u{a7a5}"), + (0xA7A6, "\u{a7a7}"), + (0xA7A8, "\u{a7a9}"), + (0xA7AA, "\u{266}"), + (0xA7AB, "\u{25c}"), + (0xA7AC, "\u{261}"), + (0xA7AD, "\u{26c}"), + (0xA7AE, "\u{26a}"), + (0xA7B0, "\u{29e}"), + (0xA7B1, "\u{287}"), + (0xA7B2, "\u{29d}"), + (0xA7B3, "\u{ab53}"), + (0xA7B4, "\u{a7b5}"), + (0xA7B6, "\u{a7b7}"), + (0xA7B8, "\u{a7b9}"), + (0xA7BA, "\u{a7bb}"), + (0xA7BC, "\u{a7bd}"), + (0xA7BE, "\u{a7bf}"), + (0xA7C0, "\u{a7c1}"), + (0xA7C2, "\u{a7c3}"), + (0xA7C4, "\u{a794}"), + (0xA7C5, "\u{282}"), + (0xA7C6, "\u{1d8e}"), + (0xA7C7, "\u{a7c8}"), + (0xA7C9, "\u{a7ca}"), + (0xA7D0, "\u{a7d1}"), + (0xA7D6, "\u{a7d7}"), + (0xA7D8, "\u{a7d9}"), + (0xA7F5, "\u{a7f6}"), + (0xAB70, "\u{13a0}"), + (0xAB71, "\u{13a1}"), + (0xAB72, "\u{13a2}"), + (0xAB73, "\u{13a3}"), + (0xAB74, "\u{13a4}"), + (0xAB75, "\u{13a5}"), + (0xAB76, "\u{13a6}"), + (0xAB77, "\u{13a7}"), + (0xAB78, "\u{13a8}"), + (0xAB79, "\u{13a9}"), + (0xAB7A, "\u{13aa}"), + (0xAB7B, "\u{13ab}"), + (0xAB7C, "\u{13ac}"), + (0xAB7D, "\u{13ad}"), + (0xAB7E, "\u{13ae}"), + (0xAB7F, "\u{13af}"), + (0xAB80, "\u{13b0}"), + (0xAB81, "\u{13b1}"), + (0xAB82, "\u{13b2}"), + (0xAB83, "\u{13b3}"), + (0xAB84, "\u{13b4}"), + (0xAB85, "\u{13b5}"), + (0xAB86, "\u{13b6}"), + (0xAB87, "\u{13b7}"), + (0xAB88, "\u{13b8}"), + (0xAB89, "\u{13b9}"), + (0xAB8A, "\u{13ba}"), + (0xAB8B, "\u{13bb}"), + (0xAB8C, "\u{13bc}"), + (0xAB8D, "\u{13bd}"), + (0xAB8E, "\u{13be}"), + (0xAB8F, "\u{13bf}"), + (0xAB90, "\u{13c0}"), + (0xAB91, "\u{13c1}"), + (0xAB92, "\u{13c2}"), + (0xAB93, "\u{13c3}"), + (0xAB94, "\u{13c4}"), + (0xAB95, "\u{13c5}"), + (0xAB96, "\u{13c6}"), + (0xAB97, "\u{13c7}"), + (0xAB98, "\u{13c8}"), + (0xAB99, "\u{13c9}"), + (0xAB9A, "\u{13ca}"), + (0xAB9B, "\u{13cb}"), + (0xAB9C, "\u{13cc}"), + (0xAB9D, "\u{13cd}"), + (0xAB9E, "\u{13ce}"), + (0xAB9F, "\u{13cf}"), + (0xABA0, "\u{13d0}"), + (0xABA1, "\u{13d1}"), + (0xABA2, "\u{13d2}"), + (0xABA3, "\u{13d3}"), + (0xABA4, "\u{13d4}"), + (0xABA5, "\u{13d5}"), + (0xABA6, "\u{13d6}"), + (0xABA7, "\u{13d7}"), + (0xABA8, "\u{13d8}"), + (0xABA9, "\u{13d9}"), + (0xABAA, "\u{13da}"), + (0xABAB, "\u{13db}"), + (0xABAC, "\u{13dc}"), + (0xABAD, "\u{13dd}"), + (0xABAE, "\u{13de}"), + (0xABAF, "\u{13df}"), + (0xABB0, "\u{13e0}"), + (0xABB1, "\u{13e1}"), + (0xABB2, "\u{13e2}"), + (0xABB3, "\u{13e3}"), + (0xABB4, "\u{13e4}"), + (0xABB5, "\u{13e5}"), + (0xABB6, "\u{13e6}"), + (0xABB7, "\u{13e7}"), + (0xABB8, "\u{13e8}"), + (0xABB9, "\u{13e9}"), + (0xABBA, "\u{13ea}"), + (0xABBB, "\u{13eb}"), + (0xABBC, "\u{13ec}"), + (0xABBD, "\u{13ed}"), + (0xABBE, "\u{13ee}"), + (0xABBF, "\u{13ef}"), + (0xFB00, "\u{66}\u{66}"), + (0xFB01, "\u{66}\u{69}"), + (0xFB02, "\u{66}\u{6c}"), + (0xFB03, "\u{66}\u{66}\u{69}"), + (0xFB04, "\u{66}\u{66}\u{6c}"), + (0xFB05, "\u{73}\u{74}"), + (0xFB06, "\u{73}\u{74}"), + (0xFB13, "\u{574}\u{576}"), + (0xFB14, "\u{574}\u{565}"), + (0xFB15, "\u{574}\u{56b}"), + (0xFB16, "\u{57e}\u{576}"), + (0xFB17, "\u{574}\u{56d}"), + (0xFF21, "\u{ff41}"), + (0xFF22, "\u{ff42}"), + (0xFF23, "\u{ff43}"), + (0xFF24, "\u{ff44}"), + (0xFF25, "\u{ff45}"), + (0xFF26, "\u{ff46}"), + (0xFF27, "\u{ff47}"), + (0xFF28, "\u{ff48}"), + (0xFF29, "\u{ff49}"), + (0xFF2A, "\u{ff4a}"), + (0xFF2B, "\u{ff4b}"), + (0xFF2C, "\u{ff4c}"), + (0xFF2D, "\u{ff4d}"), + (0xFF2E, "\u{ff4e}"), + (0xFF2F, "\u{ff4f}"), + (0xFF30, "\u{ff50}"), + (0xFF31, "\u{ff51}"), + (0xFF32, "\u{ff52}"), + (0xFF33, "\u{ff53}"), + (0xFF34, "\u{ff54}"), + (0xFF35, "\u{ff55}"), + (0xFF36, "\u{ff56}"), + (0xFF37, "\u{ff57}"), + (0xFF38, "\u{ff58}"), + (0xFF39, "\u{ff59}"), + (0xFF3A, "\u{ff5a}"), + (0x10400, "\u{10428}"), + (0x10401, "\u{10429}"), + (0x10402, "\u{1042a}"), + (0x10403, "\u{1042b}"), + (0x10404, "\u{1042c}"), + (0x10405, "\u{1042d}"), + (0x10406, "\u{1042e}"), + (0x10407, "\u{1042f}"), + (0x10408, "\u{10430}"), + (0x10409, "\u{10431}"), + (0x1040A, "\u{10432}"), + (0x1040B, "\u{10433}"), + (0x1040C, "\u{10434}"), + (0x1040D, "\u{10435}"), + (0x1040E, "\u{10436}"), + (0x1040F, "\u{10437}"), + (0x10410, "\u{10438}"), + (0x10411, "\u{10439}"), + (0x10412, "\u{1043a}"), + (0x10413, "\u{1043b}"), + (0x10414, "\u{1043c}"), + (0x10415, "\u{1043d}"), + (0x10416, "\u{1043e}"), + (0x10417, "\u{1043f}"), + (0x10418, "\u{10440}"), + (0x10419, "\u{10441}"), + (0x1041A, "\u{10442}"), + (0x1041B, "\u{10443}"), + (0x1041C, "\u{10444}"), + (0x1041D, "\u{10445}"), + (0x1041E, "\u{10446}"), + (0x1041F, "\u{10447}"), + (0x10420, "\u{10448}"), + (0x10421, "\u{10449}"), + (0x10422, "\u{1044a}"), + (0x10423, "\u{1044b}"), + (0x10424, "\u{1044c}"), + (0x10425, "\u{1044d}"), + (0x10426, "\u{1044e}"), + (0x10427, "\u{1044f}"), + (0x104B0, "\u{104d8}"), + (0x104B1, "\u{104d9}"), + (0x104B2, "\u{104da}"), + (0x104B3, "\u{104db}"), + (0x104B4, "\u{104dc}"), + (0x104B5, "\u{104dd}"), + (0x104B6, "\u{104de}"), + (0x104B7, "\u{104df}"), + (0x104B8, "\u{104e0}"), + (0x104B9, "\u{104e1}"), + (0x104BA, "\u{104e2}"), + (0x104BB, "\u{104e3}"), + (0x104BC, "\u{104e4}"), + (0x104BD, "\u{104e5}"), + (0x104BE, "\u{104e6}"), + (0x104BF, "\u{104e7}"), + (0x104C0, "\u{104e8}"), + (0x104C1, "\u{104e9}"), + (0x104C2, "\u{104ea}"), + (0x104C3, "\u{104eb}"), + (0x104C4, "\u{104ec}"), + (0x104C5, "\u{104ed}"), + (0x104C6, "\u{104ee}"), + (0x104C7, "\u{104ef}"), + (0x104C8, "\u{104f0}"), + (0x104C9, "\u{104f1}"), + (0x104CA, "\u{104f2}"), + (0x104CB, "\u{104f3}"), + (0x104CC, "\u{104f4}"), + (0x104CD, "\u{104f5}"), + (0x104CE, "\u{104f6}"), + (0x104CF, "\u{104f7}"), + (0x104D0, "\u{104f8}"), + (0x104D1, "\u{104f9}"), + (0x104D2, "\u{104fa}"), + (0x104D3, "\u{104fb}"), + (0x10570, "\u{10597}"), + (0x10571, "\u{10598}"), + (0x10572, "\u{10599}"), + (0x10573, "\u{1059a}"), + (0x10574, "\u{1059b}"), + (0x10575, "\u{1059c}"), + (0x10576, "\u{1059d}"), + (0x10577, "\u{1059e}"), + (0x10578, "\u{1059f}"), + (0x10579, "\u{105a0}"), + (0x1057A, "\u{105a1}"), + (0x1057C, "\u{105a3}"), + (0x1057D, "\u{105a4}"), + (0x1057E, "\u{105a5}"), + (0x1057F, "\u{105a6}"), + (0x10580, "\u{105a7}"), + (0x10581, "\u{105a8}"), + (0x10582, "\u{105a9}"), + (0x10583, "\u{105aa}"), + (0x10584, "\u{105ab}"), + (0x10585, "\u{105ac}"), + (0x10586, "\u{105ad}"), + (0x10587, "\u{105ae}"), + (0x10588, "\u{105af}"), + (0x10589, "\u{105b0}"), + (0x1058A, "\u{105b1}"), + (0x1058C, "\u{105b3}"), + (0x1058D, "\u{105b4}"), + (0x1058E, "\u{105b5}"), + (0x1058F, "\u{105b6}"), + (0x10590, "\u{105b7}"), + (0x10591, "\u{105b8}"), + (0x10592, "\u{105b9}"), + (0x10594, "\u{105bb}"), + (0x10595, "\u{105bc}"), + (0x10C80, "\u{10cc0}"), + (0x10C81, "\u{10cc1}"), + (0x10C82, "\u{10cc2}"), + (0x10C83, "\u{10cc3}"), + (0x10C84, "\u{10cc4}"), + (0x10C85, "\u{10cc5}"), + (0x10C86, "\u{10cc6}"), + (0x10C87, "\u{10cc7}"), + (0x10C88, "\u{10cc8}"), + (0x10C89, "\u{10cc9}"), + (0x10C8A, "\u{10cca}"), + (0x10C8B, "\u{10ccb}"), + (0x10C8C, "\u{10ccc}"), + (0x10C8D, "\u{10ccd}"), + (0x10C8E, "\u{10cce}"), + (0x10C8F, "\u{10ccf}"), + (0x10C90, "\u{10cd0}"), + (0x10C91, "\u{10cd1}"), + (0x10C92, "\u{10cd2}"), + (0x10C93, "\u{10cd3}"), + (0x10C94, "\u{10cd4}"), + (0x10C95, "\u{10cd5}"), + (0x10C96, "\u{10cd6}"), + (0x10C97, "\u{10cd7}"), + (0x10C98, "\u{10cd8}"), + (0x10C99, "\u{10cd9}"), + (0x10C9A, "\u{10cda}"), + (0x10C9B, "\u{10cdb}"), + (0x10C9C, "\u{10cdc}"), + (0x10C9D, "\u{10cdd}"), + (0x10C9E, "\u{10cde}"), + (0x10C9F, "\u{10cdf}"), + (0x10CA0, "\u{10ce0}"), + (0x10CA1, "\u{10ce1}"), + (0x10CA2, "\u{10ce2}"), + (0x10CA3, "\u{10ce3}"), + (0x10CA4, "\u{10ce4}"), + (0x10CA5, "\u{10ce5}"), + (0x10CA6, "\u{10ce6}"), + (0x10CA7, "\u{10ce7}"), + (0x10CA8, "\u{10ce8}"), + (0x10CA9, "\u{10ce9}"), + (0x10CAA, "\u{10cea}"), + (0x10CAB, "\u{10ceb}"), + (0x10CAC, "\u{10cec}"), + (0x10CAD, "\u{10ced}"), + (0x10CAE, "\u{10cee}"), + (0x10CAF, "\u{10cef}"), + (0x10CB0, "\u{10cf0}"), + (0x10CB1, "\u{10cf1}"), + (0x10CB2, "\u{10cf2}"), + (0x118A0, "\u{118c0}"), + (0x118A1, "\u{118c1}"), + (0x118A2, "\u{118c2}"), + (0x118A3, "\u{118c3}"), + (0x118A4, "\u{118c4}"), + (0x118A5, "\u{118c5}"), + (0x118A6, "\u{118c6}"), + (0x118A7, "\u{118c7}"), + (0x118A8, "\u{118c8}"), + (0x118A9, "\u{118c9}"), + (0x118AA, "\u{118ca}"), + (0x118AB, "\u{118cb}"), + (0x118AC, "\u{118cc}"), + (0x118AD, "\u{118cd}"), + (0x118AE, "\u{118ce}"), + (0x118AF, "\u{118cf}"), + (0x118B0, "\u{118d0}"), + (0x118B1, "\u{118d1}"), + (0x118B2, "\u{118d2}"), + (0x118B3, "\u{118d3}"), + (0x118B4, "\u{118d4}"), + (0x118B5, "\u{118d5}"), + (0x118B6, "\u{118d6}"), + (0x118B7, "\u{118d7}"), + (0x118B8, "\u{118d8}"), + (0x118B9, "\u{118d9}"), + (0x118BA, "\u{118da}"), + (0x118BB, "\u{118db}"), + (0x118BC, "\u{118dc}"), + (0x118BD, "\u{118dd}"), + (0x118BE, "\u{118de}"), + (0x118BF, "\u{118df}"), + (0x16E40, "\u{16e60}"), + (0x16E41, "\u{16e61}"), + (0x16E42, "\u{16e62}"), + (0x16E43, "\u{16e63}"), + (0x16E44, "\u{16e64}"), + (0x16E45, "\u{16e65}"), + (0x16E46, "\u{16e66}"), + (0x16E47, "\u{16e67}"), + (0x16E48, "\u{16e68}"), + (0x16E49, "\u{16e69}"), + (0x16E4A, "\u{16e6a}"), + (0x16E4B, "\u{16e6b}"), + (0x16E4C, "\u{16e6c}"), + (0x16E4D, "\u{16e6d}"), + (0x16E4E, "\u{16e6e}"), + (0x16E4F, "\u{16e6f}"), + (0x16E50, "\u{16e70}"), + (0x16E51, "\u{16e71}"), + (0x16E52, "\u{16e72}"), + (0x16E53, "\u{16e73}"), + (0x16E54, "\u{16e74}"), + (0x16E55, "\u{16e75}"), + (0x16E56, "\u{16e76}"), + (0x16E57, "\u{16e77}"), + (0x16E58, "\u{16e78}"), + (0x16E59, "\u{16e79}"), + (0x16E5A, "\u{16e7a}"), + (0x16E5B, "\u{16e7b}"), + (0x16E5C, "\u{16e7c}"), + (0x16E5D, "\u{16e7d}"), + (0x16E5E, "\u{16e7e}"), + (0x16E5F, "\u{16e7f}"), + (0x1E900, "\u{1e922}"), + (0x1E901, "\u{1e923}"), + (0x1E902, "\u{1e924}"), + (0x1E903, "\u{1e925}"), + (0x1E904, "\u{1e926}"), + (0x1E905, "\u{1e927}"), + (0x1E906, "\u{1e928}"), + (0x1E907, "\u{1e929}"), + (0x1E908, "\u{1e92a}"), + (0x1E909, "\u{1e92b}"), + (0x1E90A, "\u{1e92c}"), + (0x1E90B, "\u{1e92d}"), + (0x1E90C, "\u{1e92e}"), + (0x1E90D, "\u{1e92f}"), + (0x1E90E, "\u{1e930}"), + (0x1E90F, "\u{1e931}"), + (0x1E910, "\u{1e932}"), + (0x1E911, "\u{1e933}"), + (0x1E912, "\u{1e934}"), + (0x1E913, "\u{1e935}"), + (0x1E914, "\u{1e936}"), + (0x1E915, "\u{1e937}"), + (0x1E916, "\u{1e938}"), + (0x1E917, "\u{1e939}"), + (0x1E918, "\u{1e93a}"), + (0x1E919, "\u{1e93b}"), + (0x1E91A, "\u{1e93c}"), + (0x1E91B, "\u{1e93d}"), + (0x1E91C, "\u{1e93e}"), + (0x1E91D, "\u{1e93f}"), + (0x1E91E, "\u{1e940}"), + (0x1E91F, "\u{1e941}"), + (0x1E920, "\u{1e942}"), + (0x1E921, "\u{1e943}"), +] diff --git a/crates/sqlbuild-core/src/text/casefold_mappings/unicode_15_1_0.in b/crates/sqlbuild-core/src/text/casefold_mappings/unicode_15_1_0.in new file mode 100644 index 0000000000..8e038fdd13 --- /dev/null +++ b/crates/sqlbuild-core/src/text/casefold_mappings/unicode_15_1_0.in @@ -0,0 +1,1534 @@ +// Generated by `scripts/generate_python_char_table.py`; do not edit. +// Every character `str.casefold()` changes in Unicode 15.1.0, in code point order. +&[ + (0x0041, "\u{61}"), + (0x0042, "\u{62}"), + (0x0043, "\u{63}"), + (0x0044, "\u{64}"), + (0x0045, "\u{65}"), + (0x0046, "\u{66}"), + (0x0047, "\u{67}"), + (0x0048, "\u{68}"), + (0x0049, "\u{69}"), + (0x004A, "\u{6a}"), + (0x004B, "\u{6b}"), + (0x004C, "\u{6c}"), + (0x004D, "\u{6d}"), + (0x004E, "\u{6e}"), + (0x004F, "\u{6f}"), + (0x0050, "\u{70}"), + (0x0051, "\u{71}"), + (0x0052, "\u{72}"), + (0x0053, "\u{73}"), + (0x0054, "\u{74}"), + (0x0055, "\u{75}"), + (0x0056, "\u{76}"), + (0x0057, "\u{77}"), + (0x0058, "\u{78}"), + (0x0059, "\u{79}"), + (0x005A, "\u{7a}"), + (0x00B5, "\u{3bc}"), + (0x00C0, "\u{e0}"), + (0x00C1, "\u{e1}"), + (0x00C2, "\u{e2}"), + (0x00C3, "\u{e3}"), + (0x00C4, "\u{e4}"), + (0x00C5, "\u{e5}"), + (0x00C6, "\u{e6}"), + (0x00C7, "\u{e7}"), + (0x00C8, "\u{e8}"), + (0x00C9, "\u{e9}"), + (0x00CA, "\u{ea}"), + (0x00CB, "\u{eb}"), + (0x00CC, "\u{ec}"), + (0x00CD, "\u{ed}"), + (0x00CE, "\u{ee}"), + (0x00CF, "\u{ef}"), + (0x00D0, "\u{f0}"), + (0x00D1, "\u{f1}"), + (0x00D2, "\u{f2}"), + (0x00D3, "\u{f3}"), + (0x00D4, "\u{f4}"), + (0x00D5, "\u{f5}"), + (0x00D6, "\u{f6}"), + (0x00D8, "\u{f8}"), + (0x00D9, "\u{f9}"), + (0x00DA, "\u{fa}"), + (0x00DB, "\u{fb}"), + (0x00DC, "\u{fc}"), + (0x00DD, "\u{fd}"), + (0x00DE, "\u{fe}"), + (0x00DF, "\u{73}\u{73}"), + (0x0100, "\u{101}"), + (0x0102, "\u{103}"), + (0x0104, "\u{105}"), + (0x0106, "\u{107}"), + (0x0108, "\u{109}"), + (0x010A, "\u{10b}"), + (0x010C, "\u{10d}"), + (0x010E, "\u{10f}"), + (0x0110, "\u{111}"), + (0x0112, "\u{113}"), + (0x0114, "\u{115}"), + (0x0116, "\u{117}"), + (0x0118, "\u{119}"), + (0x011A, "\u{11b}"), + (0x011C, "\u{11d}"), + (0x011E, "\u{11f}"), + (0x0120, "\u{121}"), + (0x0122, "\u{123}"), + (0x0124, "\u{125}"), + (0x0126, "\u{127}"), + (0x0128, "\u{129}"), + (0x012A, "\u{12b}"), + (0x012C, "\u{12d}"), + (0x012E, "\u{12f}"), + (0x0130, "\u{69}\u{307}"), + (0x0132, "\u{133}"), + (0x0134, "\u{135}"), + (0x0136, "\u{137}"), + (0x0139, "\u{13a}"), + (0x013B, "\u{13c}"), + (0x013D, "\u{13e}"), + (0x013F, "\u{140}"), + (0x0141, "\u{142}"), + (0x0143, "\u{144}"), + (0x0145, "\u{146}"), + (0x0147, "\u{148}"), + (0x0149, "\u{2bc}\u{6e}"), + (0x014A, "\u{14b}"), + (0x014C, "\u{14d}"), + (0x014E, "\u{14f}"), + (0x0150, "\u{151}"), + (0x0152, "\u{153}"), + (0x0154, "\u{155}"), + (0x0156, "\u{157}"), + (0x0158, "\u{159}"), + (0x015A, "\u{15b}"), + (0x015C, "\u{15d}"), + (0x015E, "\u{15f}"), + (0x0160, "\u{161}"), + (0x0162, "\u{163}"), + (0x0164, "\u{165}"), + (0x0166, "\u{167}"), + (0x0168, "\u{169}"), + (0x016A, "\u{16b}"), + (0x016C, "\u{16d}"), + (0x016E, "\u{16f}"), + (0x0170, "\u{171}"), + (0x0172, "\u{173}"), + (0x0174, "\u{175}"), + (0x0176, "\u{177}"), + (0x0178, "\u{ff}"), + (0x0179, "\u{17a}"), + (0x017B, "\u{17c}"), + (0x017D, "\u{17e}"), + (0x017F, "\u{73}"), + (0x0181, "\u{253}"), + (0x0182, "\u{183}"), + (0x0184, "\u{185}"), + (0x0186, "\u{254}"), + (0x0187, "\u{188}"), + (0x0189, "\u{256}"), + (0x018A, "\u{257}"), + (0x018B, "\u{18c}"), + (0x018E, "\u{1dd}"), + (0x018F, "\u{259}"), + (0x0190, "\u{25b}"), + (0x0191, "\u{192}"), + (0x0193, "\u{260}"), + (0x0194, "\u{263}"), + (0x0196, "\u{269}"), + (0x0197, "\u{268}"), + (0x0198, "\u{199}"), + (0x019C, "\u{26f}"), + (0x019D, "\u{272}"), + (0x019F, "\u{275}"), + (0x01A0, "\u{1a1}"), + (0x01A2, "\u{1a3}"), + (0x01A4, "\u{1a5}"), + (0x01A6, "\u{280}"), + (0x01A7, "\u{1a8}"), + (0x01A9, "\u{283}"), + (0x01AC, "\u{1ad}"), + (0x01AE, "\u{288}"), + (0x01AF, "\u{1b0}"), + (0x01B1, "\u{28a}"), + (0x01B2, "\u{28b}"), + (0x01B3, "\u{1b4}"), + (0x01B5, "\u{1b6}"), + (0x01B7, "\u{292}"), + (0x01B8, "\u{1b9}"), + (0x01BC, "\u{1bd}"), + (0x01C4, "\u{1c6}"), + (0x01C5, "\u{1c6}"), + (0x01C7, "\u{1c9}"), + (0x01C8, "\u{1c9}"), + (0x01CA, "\u{1cc}"), + (0x01CB, "\u{1cc}"), + (0x01CD, "\u{1ce}"), + (0x01CF, "\u{1d0}"), + (0x01D1, "\u{1d2}"), + (0x01D3, "\u{1d4}"), + (0x01D5, "\u{1d6}"), + (0x01D7, "\u{1d8}"), + (0x01D9, "\u{1da}"), + (0x01DB, "\u{1dc}"), + (0x01DE, "\u{1df}"), + (0x01E0, "\u{1e1}"), + (0x01E2, "\u{1e3}"), + (0x01E4, "\u{1e5}"), + (0x01E6, "\u{1e7}"), + (0x01E8, "\u{1e9}"), + (0x01EA, "\u{1eb}"), + (0x01EC, "\u{1ed}"), + (0x01EE, "\u{1ef}"), + (0x01F0, "\u{6a}\u{30c}"), + (0x01F1, "\u{1f3}"), + (0x01F2, "\u{1f3}"), + (0x01F4, "\u{1f5}"), + (0x01F6, "\u{195}"), + (0x01F7, "\u{1bf}"), + (0x01F8, "\u{1f9}"), + (0x01FA, "\u{1fb}"), + (0x01FC, "\u{1fd}"), + (0x01FE, "\u{1ff}"), + (0x0200, "\u{201}"), + (0x0202, "\u{203}"), + (0x0204, "\u{205}"), + (0x0206, "\u{207}"), + (0x0208, "\u{209}"), + (0x020A, "\u{20b}"), + (0x020C, "\u{20d}"), + (0x020E, "\u{20f}"), + (0x0210, "\u{211}"), + (0x0212, "\u{213}"), + (0x0214, "\u{215}"), + (0x0216, "\u{217}"), + (0x0218, "\u{219}"), + (0x021A, "\u{21b}"), + (0x021C, "\u{21d}"), + (0x021E, "\u{21f}"), + (0x0220, "\u{19e}"), + (0x0222, "\u{223}"), + (0x0224, "\u{225}"), + (0x0226, "\u{227}"), + (0x0228, "\u{229}"), + (0x022A, "\u{22b}"), + (0x022C, "\u{22d}"), + (0x022E, "\u{22f}"), + (0x0230, "\u{231}"), + (0x0232, "\u{233}"), + (0x023A, "\u{2c65}"), + (0x023B, "\u{23c}"), + (0x023D, "\u{19a}"), + (0x023E, "\u{2c66}"), + (0x0241, "\u{242}"), + (0x0243, "\u{180}"), + (0x0244, "\u{289}"), + (0x0245, "\u{28c}"), + (0x0246, "\u{247}"), + (0x0248, "\u{249}"), + (0x024A, "\u{24b}"), + (0x024C, "\u{24d}"), + (0x024E, "\u{24f}"), + (0x0345, "\u{3b9}"), + (0x0370, "\u{371}"), + (0x0372, "\u{373}"), + (0x0376, "\u{377}"), + (0x037F, "\u{3f3}"), + (0x0386, "\u{3ac}"), + (0x0388, "\u{3ad}"), + (0x0389, "\u{3ae}"), + (0x038A, "\u{3af}"), + (0x038C, "\u{3cc}"), + (0x038E, "\u{3cd}"), + (0x038F, "\u{3ce}"), + (0x0390, "\u{3b9}\u{308}\u{301}"), + (0x0391, "\u{3b1}"), + (0x0392, "\u{3b2}"), + (0x0393, "\u{3b3}"), + (0x0394, "\u{3b4}"), + (0x0395, "\u{3b5}"), + (0x0396, "\u{3b6}"), + (0x0397, "\u{3b7}"), + (0x0398, "\u{3b8}"), + (0x0399, "\u{3b9}"), + (0x039A, "\u{3ba}"), + (0x039B, "\u{3bb}"), + (0x039C, "\u{3bc}"), + (0x039D, "\u{3bd}"), + (0x039E, "\u{3be}"), + (0x039F, "\u{3bf}"), + (0x03A0, "\u{3c0}"), + (0x03A1, "\u{3c1}"), + (0x03A3, "\u{3c3}"), + (0x03A4, "\u{3c4}"), + (0x03A5, "\u{3c5}"), + (0x03A6, "\u{3c6}"), + (0x03A7, "\u{3c7}"), + (0x03A8, "\u{3c8}"), + (0x03A9, "\u{3c9}"), + (0x03AA, "\u{3ca}"), + (0x03AB, "\u{3cb}"), + (0x03B0, "\u{3c5}\u{308}\u{301}"), + (0x03C2, "\u{3c3}"), + (0x03CF, "\u{3d7}"), + (0x03D0, "\u{3b2}"), + (0x03D1, "\u{3b8}"), + (0x03D5, "\u{3c6}"), + (0x03D6, "\u{3c0}"), + (0x03D8, "\u{3d9}"), + (0x03DA, "\u{3db}"), + (0x03DC, "\u{3dd}"), + (0x03DE, "\u{3df}"), + (0x03E0, "\u{3e1}"), + (0x03E2, "\u{3e3}"), + (0x03E4, "\u{3e5}"), + (0x03E6, "\u{3e7}"), + (0x03E8, "\u{3e9}"), + (0x03EA, "\u{3eb}"), + (0x03EC, "\u{3ed}"), + (0x03EE, "\u{3ef}"), + (0x03F0, "\u{3ba}"), + (0x03F1, "\u{3c1}"), + (0x03F4, "\u{3b8}"), + (0x03F5, "\u{3b5}"), + (0x03F7, "\u{3f8}"), + (0x03F9, "\u{3f2}"), + (0x03FA, "\u{3fb}"), + (0x03FD, "\u{37b}"), + (0x03FE, "\u{37c}"), + (0x03FF, "\u{37d}"), + (0x0400, "\u{450}"), + (0x0401, "\u{451}"), + (0x0402, "\u{452}"), + (0x0403, "\u{453}"), + (0x0404, "\u{454}"), + (0x0405, "\u{455}"), + (0x0406, "\u{456}"), + (0x0407, "\u{457}"), + (0x0408, "\u{458}"), + (0x0409, "\u{459}"), + (0x040A, "\u{45a}"), + (0x040B, "\u{45b}"), + (0x040C, "\u{45c}"), + (0x040D, "\u{45d}"), + (0x040E, "\u{45e}"), + (0x040F, "\u{45f}"), + (0x0410, "\u{430}"), + (0x0411, "\u{431}"), + (0x0412, "\u{432}"), + (0x0413, "\u{433}"), + (0x0414, "\u{434}"), + (0x0415, "\u{435}"), + (0x0416, "\u{436}"), + (0x0417, "\u{437}"), + (0x0418, "\u{438}"), + (0x0419, "\u{439}"), + (0x041A, "\u{43a}"), + (0x041B, "\u{43b}"), + (0x041C, "\u{43c}"), + (0x041D, "\u{43d}"), + (0x041E, "\u{43e}"), + (0x041F, "\u{43f}"), + (0x0420, "\u{440}"), + (0x0421, "\u{441}"), + (0x0422, "\u{442}"), + (0x0423, "\u{443}"), + (0x0424, "\u{444}"), + (0x0425, "\u{445}"), + (0x0426, "\u{446}"), + (0x0427, "\u{447}"), + (0x0428, "\u{448}"), + (0x0429, "\u{449}"), + (0x042A, "\u{44a}"), + (0x042B, "\u{44b}"), + (0x042C, "\u{44c}"), + (0x042D, "\u{44d}"), + (0x042E, "\u{44e}"), + (0x042F, "\u{44f}"), + (0x0460, "\u{461}"), + (0x0462, "\u{463}"), + (0x0464, "\u{465}"), + (0x0466, "\u{467}"), + (0x0468, "\u{469}"), + (0x046A, "\u{46b}"), + (0x046C, "\u{46d}"), + (0x046E, "\u{46f}"), + (0x0470, "\u{471}"), + (0x0472, "\u{473}"), + (0x0474, "\u{475}"), + (0x0476, "\u{477}"), + (0x0478, "\u{479}"), + (0x047A, "\u{47b}"), + (0x047C, "\u{47d}"), + (0x047E, "\u{47f}"), + (0x0480, "\u{481}"), + (0x048A, "\u{48b}"), + (0x048C, "\u{48d}"), + (0x048E, "\u{48f}"), + (0x0490, "\u{491}"), + (0x0492, "\u{493}"), + (0x0494, "\u{495}"), + (0x0496, "\u{497}"), + (0x0498, "\u{499}"), + (0x049A, "\u{49b}"), + (0x049C, "\u{49d}"), + (0x049E, "\u{49f}"), + (0x04A0, "\u{4a1}"), + (0x04A2, "\u{4a3}"), + (0x04A4, "\u{4a5}"), + (0x04A6, "\u{4a7}"), + (0x04A8, "\u{4a9}"), + (0x04AA, "\u{4ab}"), + (0x04AC, "\u{4ad}"), + (0x04AE, "\u{4af}"), + (0x04B0, "\u{4b1}"), + (0x04B2, "\u{4b3}"), + (0x04B4, "\u{4b5}"), + (0x04B6, "\u{4b7}"), + (0x04B8, "\u{4b9}"), + (0x04BA, "\u{4bb}"), + (0x04BC, "\u{4bd}"), + (0x04BE, "\u{4bf}"), + (0x04C0, "\u{4cf}"), + (0x04C1, "\u{4c2}"), + (0x04C3, "\u{4c4}"), + (0x04C5, "\u{4c6}"), + (0x04C7, "\u{4c8}"), + (0x04C9, "\u{4ca}"), + (0x04CB, "\u{4cc}"), + (0x04CD, "\u{4ce}"), + (0x04D0, "\u{4d1}"), + (0x04D2, "\u{4d3}"), + (0x04D4, "\u{4d5}"), + (0x04D6, "\u{4d7}"), + (0x04D8, "\u{4d9}"), + (0x04DA, "\u{4db}"), + (0x04DC, "\u{4dd}"), + (0x04DE, "\u{4df}"), + (0x04E0, "\u{4e1}"), + (0x04E2, "\u{4e3}"), + (0x04E4, "\u{4e5}"), + (0x04E6, "\u{4e7}"), + (0x04E8, "\u{4e9}"), + (0x04EA, "\u{4eb}"), + (0x04EC, "\u{4ed}"), + (0x04EE, "\u{4ef}"), + (0x04F0, "\u{4f1}"), + (0x04F2, "\u{4f3}"), + (0x04F4, "\u{4f5}"), + (0x04F6, "\u{4f7}"), + (0x04F8, "\u{4f9}"), + (0x04FA, "\u{4fb}"), + (0x04FC, "\u{4fd}"), + (0x04FE, "\u{4ff}"), + (0x0500, "\u{501}"), + (0x0502, "\u{503}"), + (0x0504, "\u{505}"), + (0x0506, "\u{507}"), + (0x0508, "\u{509}"), + (0x050A, "\u{50b}"), + (0x050C, "\u{50d}"), + (0x050E, "\u{50f}"), + (0x0510, "\u{511}"), + (0x0512, "\u{513}"), + (0x0514, "\u{515}"), + (0x0516, "\u{517}"), + (0x0518, "\u{519}"), + (0x051A, "\u{51b}"), + (0x051C, "\u{51d}"), + (0x051E, "\u{51f}"), + (0x0520, "\u{521}"), + (0x0522, "\u{523}"), + (0x0524, "\u{525}"), + (0x0526, "\u{527}"), + (0x0528, "\u{529}"), + (0x052A, "\u{52b}"), + (0x052C, "\u{52d}"), + (0x052E, "\u{52f}"), + (0x0531, "\u{561}"), + (0x0532, "\u{562}"), + (0x0533, "\u{563}"), + (0x0534, "\u{564}"), + (0x0535, "\u{565}"), + (0x0536, "\u{566}"), + (0x0537, "\u{567}"), + (0x0538, "\u{568}"), + (0x0539, "\u{569}"), + (0x053A, "\u{56a}"), + (0x053B, "\u{56b}"), + (0x053C, "\u{56c}"), + (0x053D, "\u{56d}"), + (0x053E, "\u{56e}"), + (0x053F, "\u{56f}"), + (0x0540, "\u{570}"), + (0x0541, "\u{571}"), + (0x0542, "\u{572}"), + (0x0543, "\u{573}"), + (0x0544, "\u{574}"), + (0x0545, "\u{575}"), + (0x0546, "\u{576}"), + (0x0547, "\u{577}"), + (0x0548, "\u{578}"), + (0x0549, "\u{579}"), + (0x054A, "\u{57a}"), + (0x054B, "\u{57b}"), + (0x054C, "\u{57c}"), + (0x054D, "\u{57d}"), + (0x054E, "\u{57e}"), + (0x054F, "\u{57f}"), + (0x0550, "\u{580}"), + (0x0551, "\u{581}"), + (0x0552, "\u{582}"), + (0x0553, "\u{583}"), + (0x0554, "\u{584}"), + (0x0555, "\u{585}"), + (0x0556, "\u{586}"), + (0x0587, "\u{565}\u{582}"), + (0x10A0, "\u{2d00}"), + (0x10A1, "\u{2d01}"), + (0x10A2, "\u{2d02}"), + (0x10A3, "\u{2d03}"), + (0x10A4, "\u{2d04}"), + (0x10A5, "\u{2d05}"), + (0x10A6, "\u{2d06}"), + (0x10A7, "\u{2d07}"), + (0x10A8, "\u{2d08}"), + (0x10A9, "\u{2d09}"), + (0x10AA, "\u{2d0a}"), + (0x10AB, "\u{2d0b}"), + (0x10AC, "\u{2d0c}"), + (0x10AD, "\u{2d0d}"), + (0x10AE, "\u{2d0e}"), + (0x10AF, "\u{2d0f}"), + (0x10B0, "\u{2d10}"), + (0x10B1, "\u{2d11}"), + (0x10B2, "\u{2d12}"), + (0x10B3, "\u{2d13}"), + (0x10B4, "\u{2d14}"), + (0x10B5, "\u{2d15}"), + (0x10B6, "\u{2d16}"), + (0x10B7, "\u{2d17}"), + (0x10B8, "\u{2d18}"), + (0x10B9, "\u{2d19}"), + (0x10BA, "\u{2d1a}"), + (0x10BB, "\u{2d1b}"), + (0x10BC, "\u{2d1c}"), + (0x10BD, "\u{2d1d}"), + (0x10BE, "\u{2d1e}"), + (0x10BF, "\u{2d1f}"), + (0x10C0, "\u{2d20}"), + (0x10C1, "\u{2d21}"), + (0x10C2, "\u{2d22}"), + (0x10C3, "\u{2d23}"), + (0x10C4, "\u{2d24}"), + (0x10C5, "\u{2d25}"), + (0x10C7, "\u{2d27}"), + (0x10CD, "\u{2d2d}"), + (0x13F8, "\u{13f0}"), + (0x13F9, "\u{13f1}"), + (0x13FA, "\u{13f2}"), + (0x13FB, "\u{13f3}"), + (0x13FC, "\u{13f4}"), + (0x13FD, "\u{13f5}"), + (0x1C80, "\u{432}"), + (0x1C81, "\u{434}"), + (0x1C82, "\u{43e}"), + (0x1C83, "\u{441}"), + (0x1C84, "\u{442}"), + (0x1C85, "\u{442}"), + (0x1C86, "\u{44a}"), + (0x1C87, "\u{463}"), + (0x1C88, "\u{a64b}"), + (0x1C90, "\u{10d0}"), + (0x1C91, "\u{10d1}"), + (0x1C92, "\u{10d2}"), + (0x1C93, "\u{10d3}"), + (0x1C94, "\u{10d4}"), + (0x1C95, "\u{10d5}"), + (0x1C96, "\u{10d6}"), + (0x1C97, "\u{10d7}"), + (0x1C98, "\u{10d8}"), + (0x1C99, "\u{10d9}"), + (0x1C9A, "\u{10da}"), + (0x1C9B, "\u{10db}"), + (0x1C9C, "\u{10dc}"), + (0x1C9D, "\u{10dd}"), + (0x1C9E, "\u{10de}"), + (0x1C9F, "\u{10df}"), + (0x1CA0, "\u{10e0}"), + (0x1CA1, "\u{10e1}"), + (0x1CA2, "\u{10e2}"), + (0x1CA3, "\u{10e3}"), + (0x1CA4, "\u{10e4}"), + (0x1CA5, "\u{10e5}"), + (0x1CA6, "\u{10e6}"), + (0x1CA7, "\u{10e7}"), + (0x1CA8, "\u{10e8}"), + (0x1CA9, "\u{10e9}"), + (0x1CAA, "\u{10ea}"), + (0x1CAB, "\u{10eb}"), + (0x1CAC, "\u{10ec}"), + (0x1CAD, "\u{10ed}"), + (0x1CAE, "\u{10ee}"), + (0x1CAF, "\u{10ef}"), + (0x1CB0, "\u{10f0}"), + (0x1CB1, "\u{10f1}"), + (0x1CB2, "\u{10f2}"), + (0x1CB3, "\u{10f3}"), + (0x1CB4, "\u{10f4}"), + (0x1CB5, "\u{10f5}"), + (0x1CB6, "\u{10f6}"), + (0x1CB7, "\u{10f7}"), + (0x1CB8, "\u{10f8}"), + (0x1CB9, "\u{10f9}"), + (0x1CBA, "\u{10fa}"), + (0x1CBD, "\u{10fd}"), + (0x1CBE, "\u{10fe}"), + (0x1CBF, "\u{10ff}"), + (0x1E00, "\u{1e01}"), + (0x1E02, "\u{1e03}"), + (0x1E04, "\u{1e05}"), + (0x1E06, "\u{1e07}"), + (0x1E08, "\u{1e09}"), + (0x1E0A, "\u{1e0b}"), + (0x1E0C, "\u{1e0d}"), + (0x1E0E, "\u{1e0f}"), + (0x1E10, "\u{1e11}"), + (0x1E12, "\u{1e13}"), + (0x1E14, "\u{1e15}"), + (0x1E16, "\u{1e17}"), + (0x1E18, "\u{1e19}"), + (0x1E1A, "\u{1e1b}"), + (0x1E1C, "\u{1e1d}"), + (0x1E1E, "\u{1e1f}"), + (0x1E20, "\u{1e21}"), + (0x1E22, "\u{1e23}"), + (0x1E24, "\u{1e25}"), + (0x1E26, "\u{1e27}"), + (0x1E28, "\u{1e29}"), + (0x1E2A, "\u{1e2b}"), + (0x1E2C, "\u{1e2d}"), + (0x1E2E, "\u{1e2f}"), + (0x1E30, "\u{1e31}"), + (0x1E32, "\u{1e33}"), + (0x1E34, "\u{1e35}"), + (0x1E36, "\u{1e37}"), + (0x1E38, "\u{1e39}"), + (0x1E3A, "\u{1e3b}"), + (0x1E3C, "\u{1e3d}"), + (0x1E3E, "\u{1e3f}"), + (0x1E40, "\u{1e41}"), + (0x1E42, "\u{1e43}"), + (0x1E44, "\u{1e45}"), + (0x1E46, "\u{1e47}"), + (0x1E48, "\u{1e49}"), + (0x1E4A, "\u{1e4b}"), + (0x1E4C, "\u{1e4d}"), + (0x1E4E, "\u{1e4f}"), + (0x1E50, "\u{1e51}"), + (0x1E52, "\u{1e53}"), + (0x1E54, "\u{1e55}"), + (0x1E56, "\u{1e57}"), + (0x1E58, "\u{1e59}"), + (0x1E5A, "\u{1e5b}"), + (0x1E5C, "\u{1e5d}"), + (0x1E5E, "\u{1e5f}"), + (0x1E60, "\u{1e61}"), + (0x1E62, "\u{1e63}"), + (0x1E64, "\u{1e65}"), + (0x1E66, "\u{1e67}"), + (0x1E68, "\u{1e69}"), + (0x1E6A, "\u{1e6b}"), + (0x1E6C, "\u{1e6d}"), + (0x1E6E, "\u{1e6f}"), + (0x1E70, "\u{1e71}"), + (0x1E72, "\u{1e73}"), + (0x1E74, "\u{1e75}"), + (0x1E76, "\u{1e77}"), + (0x1E78, "\u{1e79}"), + (0x1E7A, "\u{1e7b}"), + (0x1E7C, "\u{1e7d}"), + (0x1E7E, "\u{1e7f}"), + (0x1E80, "\u{1e81}"), + (0x1E82, "\u{1e83}"), + (0x1E84, "\u{1e85}"), + (0x1E86, "\u{1e87}"), + (0x1E88, "\u{1e89}"), + (0x1E8A, "\u{1e8b}"), + (0x1E8C, "\u{1e8d}"), + (0x1E8E, "\u{1e8f}"), + (0x1E90, "\u{1e91}"), + (0x1E92, "\u{1e93}"), + (0x1E94, "\u{1e95}"), + (0x1E96, "\u{68}\u{331}"), + (0x1E97, "\u{74}\u{308}"), + (0x1E98, "\u{77}\u{30a}"), + (0x1E99, "\u{79}\u{30a}"), + (0x1E9A, "\u{61}\u{2be}"), + (0x1E9B, "\u{1e61}"), + (0x1E9E, "\u{73}\u{73}"), + (0x1EA0, "\u{1ea1}"), + (0x1EA2, "\u{1ea3}"), + (0x1EA4, "\u{1ea5}"), + (0x1EA6, "\u{1ea7}"), + (0x1EA8, "\u{1ea9}"), + (0x1EAA, "\u{1eab}"), + (0x1EAC, "\u{1ead}"), + (0x1EAE, "\u{1eaf}"), + (0x1EB0, "\u{1eb1}"), + (0x1EB2, "\u{1eb3}"), + (0x1EB4, "\u{1eb5}"), + (0x1EB6, "\u{1eb7}"), + (0x1EB8, "\u{1eb9}"), + (0x1EBA, "\u{1ebb}"), + (0x1EBC, "\u{1ebd}"), + (0x1EBE, "\u{1ebf}"), + (0x1EC0, "\u{1ec1}"), + (0x1EC2, "\u{1ec3}"), + (0x1EC4, "\u{1ec5}"), + (0x1EC6, "\u{1ec7}"), + (0x1EC8, "\u{1ec9}"), + (0x1ECA, "\u{1ecb}"), + (0x1ECC, "\u{1ecd}"), + (0x1ECE, "\u{1ecf}"), + (0x1ED0, "\u{1ed1}"), + (0x1ED2, "\u{1ed3}"), + (0x1ED4, "\u{1ed5}"), + (0x1ED6, "\u{1ed7}"), + (0x1ED8, "\u{1ed9}"), + (0x1EDA, "\u{1edb}"), + (0x1EDC, "\u{1edd}"), + (0x1EDE, "\u{1edf}"), + (0x1EE0, "\u{1ee1}"), + (0x1EE2, "\u{1ee3}"), + (0x1EE4, "\u{1ee5}"), + (0x1EE6, "\u{1ee7}"), + (0x1EE8, "\u{1ee9}"), + (0x1EEA, "\u{1eeb}"), + (0x1EEC, "\u{1eed}"), + (0x1EEE, "\u{1eef}"), + (0x1EF0, "\u{1ef1}"), + (0x1EF2, "\u{1ef3}"), + (0x1EF4, "\u{1ef5}"), + (0x1EF6, "\u{1ef7}"), + (0x1EF8, "\u{1ef9}"), + (0x1EFA, "\u{1efb}"), + (0x1EFC, "\u{1efd}"), + (0x1EFE, "\u{1eff}"), + (0x1F08, "\u{1f00}"), + (0x1F09, "\u{1f01}"), + (0x1F0A, "\u{1f02}"), + (0x1F0B, "\u{1f03}"), + (0x1F0C, "\u{1f04}"), + (0x1F0D, "\u{1f05}"), + (0x1F0E, "\u{1f06}"), + (0x1F0F, "\u{1f07}"), + (0x1F18, "\u{1f10}"), + (0x1F19, "\u{1f11}"), + (0x1F1A, "\u{1f12}"), + (0x1F1B, "\u{1f13}"), + (0x1F1C, "\u{1f14}"), + (0x1F1D, "\u{1f15}"), + (0x1F28, "\u{1f20}"), + (0x1F29, "\u{1f21}"), + (0x1F2A, "\u{1f22}"), + (0x1F2B, "\u{1f23}"), + (0x1F2C, "\u{1f24}"), + (0x1F2D, "\u{1f25}"), + (0x1F2E, "\u{1f26}"), + (0x1F2F, "\u{1f27}"), + (0x1F38, "\u{1f30}"), + (0x1F39, "\u{1f31}"), + (0x1F3A, "\u{1f32}"), + (0x1F3B, "\u{1f33}"), + (0x1F3C, "\u{1f34}"), + (0x1F3D, "\u{1f35}"), + (0x1F3E, "\u{1f36}"), + (0x1F3F, "\u{1f37}"), + (0x1F48, "\u{1f40}"), + (0x1F49, "\u{1f41}"), + (0x1F4A, "\u{1f42}"), + (0x1F4B, "\u{1f43}"), + (0x1F4C, "\u{1f44}"), + (0x1F4D, "\u{1f45}"), + (0x1F50, "\u{3c5}\u{313}"), + (0x1F52, "\u{3c5}\u{313}\u{300}"), + (0x1F54, "\u{3c5}\u{313}\u{301}"), + (0x1F56, "\u{3c5}\u{313}\u{342}"), + (0x1F59, "\u{1f51}"), + (0x1F5B, "\u{1f53}"), + (0x1F5D, "\u{1f55}"), + (0x1F5F, "\u{1f57}"), + (0x1F68, "\u{1f60}"), + (0x1F69, "\u{1f61}"), + (0x1F6A, "\u{1f62}"), + (0x1F6B, "\u{1f63}"), + (0x1F6C, "\u{1f64}"), + (0x1F6D, "\u{1f65}"), + (0x1F6E, "\u{1f66}"), + (0x1F6F, "\u{1f67}"), + (0x1F80, "\u{1f00}\u{3b9}"), + (0x1F81, "\u{1f01}\u{3b9}"), + (0x1F82, "\u{1f02}\u{3b9}"), + (0x1F83, "\u{1f03}\u{3b9}"), + (0x1F84, "\u{1f04}\u{3b9}"), + (0x1F85, "\u{1f05}\u{3b9}"), + (0x1F86, "\u{1f06}\u{3b9}"), + (0x1F87, "\u{1f07}\u{3b9}"), + (0x1F88, "\u{1f00}\u{3b9}"), + (0x1F89, "\u{1f01}\u{3b9}"), + (0x1F8A, "\u{1f02}\u{3b9}"), + (0x1F8B, "\u{1f03}\u{3b9}"), + (0x1F8C, "\u{1f04}\u{3b9}"), + (0x1F8D, "\u{1f05}\u{3b9}"), + (0x1F8E, "\u{1f06}\u{3b9}"), + (0x1F8F, "\u{1f07}\u{3b9}"), + (0x1F90, "\u{1f20}\u{3b9}"), + (0x1F91, "\u{1f21}\u{3b9}"), + (0x1F92, "\u{1f22}\u{3b9}"), + (0x1F93, "\u{1f23}\u{3b9}"), + (0x1F94, "\u{1f24}\u{3b9}"), + (0x1F95, "\u{1f25}\u{3b9}"), + (0x1F96, "\u{1f26}\u{3b9}"), + (0x1F97, "\u{1f27}\u{3b9}"), + (0x1F98, "\u{1f20}\u{3b9}"), + (0x1F99, "\u{1f21}\u{3b9}"), + (0x1F9A, "\u{1f22}\u{3b9}"), + (0x1F9B, "\u{1f23}\u{3b9}"), + (0x1F9C, "\u{1f24}\u{3b9}"), + (0x1F9D, "\u{1f25}\u{3b9}"), + (0x1F9E, "\u{1f26}\u{3b9}"), + (0x1F9F, "\u{1f27}\u{3b9}"), + (0x1FA0, "\u{1f60}\u{3b9}"), + (0x1FA1, "\u{1f61}\u{3b9}"), + (0x1FA2, "\u{1f62}\u{3b9}"), + (0x1FA3, "\u{1f63}\u{3b9}"), + (0x1FA4, "\u{1f64}\u{3b9}"), + (0x1FA5, "\u{1f65}\u{3b9}"), + (0x1FA6, "\u{1f66}\u{3b9}"), + (0x1FA7, "\u{1f67}\u{3b9}"), + (0x1FA8, "\u{1f60}\u{3b9}"), + (0x1FA9, "\u{1f61}\u{3b9}"), + (0x1FAA, "\u{1f62}\u{3b9}"), + (0x1FAB, "\u{1f63}\u{3b9}"), + (0x1FAC, "\u{1f64}\u{3b9}"), + (0x1FAD, "\u{1f65}\u{3b9}"), + (0x1FAE, "\u{1f66}\u{3b9}"), + (0x1FAF, "\u{1f67}\u{3b9}"), + (0x1FB2, "\u{1f70}\u{3b9}"), + (0x1FB3, "\u{3b1}\u{3b9}"), + (0x1FB4, "\u{3ac}\u{3b9}"), + (0x1FB6, "\u{3b1}\u{342}"), + (0x1FB7, "\u{3b1}\u{342}\u{3b9}"), + (0x1FB8, "\u{1fb0}"), + (0x1FB9, "\u{1fb1}"), + (0x1FBA, "\u{1f70}"), + (0x1FBB, "\u{1f71}"), + (0x1FBC, "\u{3b1}\u{3b9}"), + (0x1FBE, "\u{3b9}"), + (0x1FC2, "\u{1f74}\u{3b9}"), + (0x1FC3, "\u{3b7}\u{3b9}"), + (0x1FC4, "\u{3ae}\u{3b9}"), + (0x1FC6, "\u{3b7}\u{342}"), + (0x1FC7, "\u{3b7}\u{342}\u{3b9}"), + (0x1FC8, "\u{1f72}"), + (0x1FC9, "\u{1f73}"), + (0x1FCA, "\u{1f74}"), + (0x1FCB, "\u{1f75}"), + (0x1FCC, "\u{3b7}\u{3b9}"), + (0x1FD2, "\u{3b9}\u{308}\u{300}"), + (0x1FD3, "\u{3b9}\u{308}\u{301}"), + (0x1FD6, "\u{3b9}\u{342}"), + (0x1FD7, "\u{3b9}\u{308}\u{342}"), + (0x1FD8, "\u{1fd0}"), + (0x1FD9, "\u{1fd1}"), + (0x1FDA, "\u{1f76}"), + (0x1FDB, "\u{1f77}"), + (0x1FE2, "\u{3c5}\u{308}\u{300}"), + (0x1FE3, "\u{3c5}\u{308}\u{301}"), + (0x1FE4, "\u{3c1}\u{313}"), + (0x1FE6, "\u{3c5}\u{342}"), + (0x1FE7, "\u{3c5}\u{308}\u{342}"), + (0x1FE8, "\u{1fe0}"), + (0x1FE9, "\u{1fe1}"), + (0x1FEA, "\u{1f7a}"), + (0x1FEB, "\u{1f7b}"), + (0x1FEC, "\u{1fe5}"), + (0x1FF2, "\u{1f7c}\u{3b9}"), + (0x1FF3, "\u{3c9}\u{3b9}"), + (0x1FF4, "\u{3ce}\u{3b9}"), + (0x1FF6, "\u{3c9}\u{342}"), + (0x1FF7, "\u{3c9}\u{342}\u{3b9}"), + (0x1FF8, "\u{1f78}"), + (0x1FF9, "\u{1f79}"), + (0x1FFA, "\u{1f7c}"), + (0x1FFB, "\u{1f7d}"), + (0x1FFC, "\u{3c9}\u{3b9}"), + (0x2126, "\u{3c9}"), + (0x212A, "\u{6b}"), + (0x212B, "\u{e5}"), + (0x2132, "\u{214e}"), + (0x2160, "\u{2170}"), + (0x2161, "\u{2171}"), + (0x2162, "\u{2172}"), + (0x2163, "\u{2173}"), + (0x2164, "\u{2174}"), + (0x2165, "\u{2175}"), + (0x2166, "\u{2176}"), + (0x2167, "\u{2177}"), + (0x2168, "\u{2178}"), + (0x2169, "\u{2179}"), + (0x216A, "\u{217a}"), + (0x216B, "\u{217b}"), + (0x216C, "\u{217c}"), + (0x216D, "\u{217d}"), + (0x216E, "\u{217e}"), + (0x216F, "\u{217f}"), + (0x2183, "\u{2184}"), + (0x24B6, "\u{24d0}"), + (0x24B7, "\u{24d1}"), + (0x24B8, "\u{24d2}"), + (0x24B9, "\u{24d3}"), + (0x24BA, "\u{24d4}"), + (0x24BB, "\u{24d5}"), + (0x24BC, "\u{24d6}"), + (0x24BD, "\u{24d7}"), + (0x24BE, "\u{24d8}"), + (0x24BF, "\u{24d9}"), + (0x24C0, "\u{24da}"), + (0x24C1, "\u{24db}"), + (0x24C2, "\u{24dc}"), + (0x24C3, "\u{24dd}"), + (0x24C4, "\u{24de}"), + (0x24C5, "\u{24df}"), + (0x24C6, "\u{24e0}"), + (0x24C7, "\u{24e1}"), + (0x24C8, "\u{24e2}"), + (0x24C9, "\u{24e3}"), + (0x24CA, "\u{24e4}"), + (0x24CB, "\u{24e5}"), + (0x24CC, "\u{24e6}"), + (0x24CD, "\u{24e7}"), + (0x24CE, "\u{24e8}"), + (0x24CF, "\u{24e9}"), + (0x2C00, "\u{2c30}"), + (0x2C01, "\u{2c31}"), + (0x2C02, "\u{2c32}"), + (0x2C03, "\u{2c33}"), + (0x2C04, "\u{2c34}"), + (0x2C05, "\u{2c35}"), + (0x2C06, "\u{2c36}"), + (0x2C07, "\u{2c37}"), + (0x2C08, "\u{2c38}"), + (0x2C09, "\u{2c39}"), + (0x2C0A, "\u{2c3a}"), + (0x2C0B, "\u{2c3b}"), + (0x2C0C, "\u{2c3c}"), + (0x2C0D, "\u{2c3d}"), + (0x2C0E, "\u{2c3e}"), + (0x2C0F, "\u{2c3f}"), + (0x2C10, "\u{2c40}"), + (0x2C11, "\u{2c41}"), + (0x2C12, "\u{2c42}"), + (0x2C13, "\u{2c43}"), + (0x2C14, "\u{2c44}"), + (0x2C15, "\u{2c45}"), + (0x2C16, "\u{2c46}"), + (0x2C17, "\u{2c47}"), + (0x2C18, "\u{2c48}"), + (0x2C19, "\u{2c49}"), + (0x2C1A, "\u{2c4a}"), + (0x2C1B, "\u{2c4b}"), + (0x2C1C, "\u{2c4c}"), + (0x2C1D, "\u{2c4d}"), + (0x2C1E, "\u{2c4e}"), + (0x2C1F, "\u{2c4f}"), + (0x2C20, "\u{2c50}"), + (0x2C21, "\u{2c51}"), + (0x2C22, "\u{2c52}"), + (0x2C23, "\u{2c53}"), + (0x2C24, "\u{2c54}"), + (0x2C25, "\u{2c55}"), + (0x2C26, "\u{2c56}"), + (0x2C27, "\u{2c57}"), + (0x2C28, "\u{2c58}"), + (0x2C29, "\u{2c59}"), + (0x2C2A, "\u{2c5a}"), + (0x2C2B, "\u{2c5b}"), + (0x2C2C, "\u{2c5c}"), + (0x2C2D, "\u{2c5d}"), + (0x2C2E, "\u{2c5e}"), + (0x2C2F, "\u{2c5f}"), + (0x2C60, "\u{2c61}"), + (0x2C62, "\u{26b}"), + (0x2C63, "\u{1d7d}"), + (0x2C64, "\u{27d}"), + (0x2C67, "\u{2c68}"), + (0x2C69, "\u{2c6a}"), + (0x2C6B, "\u{2c6c}"), + (0x2C6D, "\u{251}"), + (0x2C6E, "\u{271}"), + (0x2C6F, "\u{250}"), + (0x2C70, "\u{252}"), + (0x2C72, "\u{2c73}"), + (0x2C75, "\u{2c76}"), + (0x2C7E, "\u{23f}"), + (0x2C7F, "\u{240}"), + (0x2C80, "\u{2c81}"), + (0x2C82, "\u{2c83}"), + (0x2C84, "\u{2c85}"), + (0x2C86, "\u{2c87}"), + (0x2C88, "\u{2c89}"), + (0x2C8A, "\u{2c8b}"), + (0x2C8C, "\u{2c8d}"), + (0x2C8E, "\u{2c8f}"), + (0x2C90, "\u{2c91}"), + (0x2C92, "\u{2c93}"), + (0x2C94, "\u{2c95}"), + (0x2C96, "\u{2c97}"), + (0x2C98, "\u{2c99}"), + (0x2C9A, "\u{2c9b}"), + (0x2C9C, "\u{2c9d}"), + (0x2C9E, "\u{2c9f}"), + (0x2CA0, "\u{2ca1}"), + (0x2CA2, "\u{2ca3}"), + (0x2CA4, "\u{2ca5}"), + (0x2CA6, "\u{2ca7}"), + (0x2CA8, "\u{2ca9}"), + (0x2CAA, "\u{2cab}"), + (0x2CAC, "\u{2cad}"), + (0x2CAE, "\u{2caf}"), + (0x2CB0, "\u{2cb1}"), + (0x2CB2, "\u{2cb3}"), + (0x2CB4, "\u{2cb5}"), + (0x2CB6, "\u{2cb7}"), + (0x2CB8, "\u{2cb9}"), + (0x2CBA, "\u{2cbb}"), + (0x2CBC, "\u{2cbd}"), + (0x2CBE, "\u{2cbf}"), + (0x2CC0, "\u{2cc1}"), + (0x2CC2, "\u{2cc3}"), + (0x2CC4, "\u{2cc5}"), + (0x2CC6, "\u{2cc7}"), + (0x2CC8, "\u{2cc9}"), + (0x2CCA, "\u{2ccb}"), + (0x2CCC, "\u{2ccd}"), + (0x2CCE, "\u{2ccf}"), + (0x2CD0, "\u{2cd1}"), + (0x2CD2, "\u{2cd3}"), + (0x2CD4, "\u{2cd5}"), + (0x2CD6, "\u{2cd7}"), + (0x2CD8, "\u{2cd9}"), + (0x2CDA, "\u{2cdb}"), + (0x2CDC, "\u{2cdd}"), + (0x2CDE, "\u{2cdf}"), + (0x2CE0, "\u{2ce1}"), + (0x2CE2, "\u{2ce3}"), + (0x2CEB, "\u{2cec}"), + (0x2CED, "\u{2cee}"), + (0x2CF2, "\u{2cf3}"), + (0xA640, "\u{a641}"), + (0xA642, "\u{a643}"), + (0xA644, "\u{a645}"), + (0xA646, "\u{a647}"), + (0xA648, "\u{a649}"), + (0xA64A, "\u{a64b}"), + (0xA64C, "\u{a64d}"), + (0xA64E, "\u{a64f}"), + (0xA650, "\u{a651}"), + (0xA652, "\u{a653}"), + (0xA654, "\u{a655}"), + (0xA656, "\u{a657}"), + (0xA658, "\u{a659}"), + (0xA65A, "\u{a65b}"), + (0xA65C, "\u{a65d}"), + (0xA65E, "\u{a65f}"), + (0xA660, "\u{a661}"), + (0xA662, "\u{a663}"), + (0xA664, "\u{a665}"), + (0xA666, "\u{a667}"), + (0xA668, "\u{a669}"), + (0xA66A, "\u{a66b}"), + (0xA66C, "\u{a66d}"), + (0xA680, "\u{a681}"), + (0xA682, "\u{a683}"), + (0xA684, "\u{a685}"), + (0xA686, "\u{a687}"), + (0xA688, "\u{a689}"), + (0xA68A, "\u{a68b}"), + (0xA68C, "\u{a68d}"), + (0xA68E, "\u{a68f}"), + (0xA690, "\u{a691}"), + (0xA692, "\u{a693}"), + (0xA694, "\u{a695}"), + (0xA696, "\u{a697}"), + (0xA698, "\u{a699}"), + (0xA69A, "\u{a69b}"), + (0xA722, "\u{a723}"), + (0xA724, "\u{a725}"), + (0xA726, "\u{a727}"), + (0xA728, "\u{a729}"), + (0xA72A, "\u{a72b}"), + (0xA72C, "\u{a72d}"), + (0xA72E, "\u{a72f}"), + (0xA732, "\u{a733}"), + (0xA734, "\u{a735}"), + (0xA736, "\u{a737}"), + (0xA738, "\u{a739}"), + (0xA73A, "\u{a73b}"), + (0xA73C, "\u{a73d}"), + (0xA73E, "\u{a73f}"), + (0xA740, "\u{a741}"), + (0xA742, "\u{a743}"), + (0xA744, "\u{a745}"), + (0xA746, "\u{a747}"), + (0xA748, "\u{a749}"), + (0xA74A, "\u{a74b}"), + (0xA74C, "\u{a74d}"), + (0xA74E, "\u{a74f}"), + (0xA750, "\u{a751}"), + (0xA752, "\u{a753}"), + (0xA754, "\u{a755}"), + (0xA756, "\u{a757}"), + (0xA758, "\u{a759}"), + (0xA75A, "\u{a75b}"), + (0xA75C, "\u{a75d}"), + (0xA75E, "\u{a75f}"), + (0xA760, "\u{a761}"), + (0xA762, "\u{a763}"), + (0xA764, "\u{a765}"), + (0xA766, "\u{a767}"), + (0xA768, "\u{a769}"), + (0xA76A, "\u{a76b}"), + (0xA76C, "\u{a76d}"), + (0xA76E, "\u{a76f}"), + (0xA779, "\u{a77a}"), + (0xA77B, "\u{a77c}"), + (0xA77D, "\u{1d79}"), + (0xA77E, "\u{a77f}"), + (0xA780, "\u{a781}"), + (0xA782, "\u{a783}"), + (0xA784, "\u{a785}"), + (0xA786, "\u{a787}"), + (0xA78B, "\u{a78c}"), + (0xA78D, "\u{265}"), + (0xA790, "\u{a791}"), + (0xA792, "\u{a793}"), + (0xA796, "\u{a797}"), + (0xA798, "\u{a799}"), + (0xA79A, "\u{a79b}"), + (0xA79C, "\u{a79d}"), + (0xA79E, "\u{a79f}"), + (0xA7A0, "\u{a7a1}"), + (0xA7A2, "\u{a7a3}"), + (0xA7A4, "\u{a7a5}"), + (0xA7A6, "\u{a7a7}"), + (0xA7A8, "\u{a7a9}"), + (0xA7AA, "\u{266}"), + (0xA7AB, "\u{25c}"), + (0xA7AC, "\u{261}"), + (0xA7AD, "\u{26c}"), + (0xA7AE, "\u{26a}"), + (0xA7B0, "\u{29e}"), + (0xA7B1, "\u{287}"), + (0xA7B2, "\u{29d}"), + (0xA7B3, "\u{ab53}"), + (0xA7B4, "\u{a7b5}"), + (0xA7B6, "\u{a7b7}"), + (0xA7B8, "\u{a7b9}"), + (0xA7BA, "\u{a7bb}"), + (0xA7BC, "\u{a7bd}"), + (0xA7BE, "\u{a7bf}"), + (0xA7C0, "\u{a7c1}"), + (0xA7C2, "\u{a7c3}"), + (0xA7C4, "\u{a794}"), + (0xA7C5, "\u{282}"), + (0xA7C6, "\u{1d8e}"), + (0xA7C7, "\u{a7c8}"), + (0xA7C9, "\u{a7ca}"), + (0xA7D0, "\u{a7d1}"), + (0xA7D6, "\u{a7d7}"), + (0xA7D8, "\u{a7d9}"), + (0xA7F5, "\u{a7f6}"), + (0xAB70, "\u{13a0}"), + (0xAB71, "\u{13a1}"), + (0xAB72, "\u{13a2}"), + (0xAB73, "\u{13a3}"), + (0xAB74, "\u{13a4}"), + (0xAB75, "\u{13a5}"), + (0xAB76, "\u{13a6}"), + (0xAB77, "\u{13a7}"), + (0xAB78, "\u{13a8}"), + (0xAB79, "\u{13a9}"), + (0xAB7A, "\u{13aa}"), + (0xAB7B, "\u{13ab}"), + (0xAB7C, "\u{13ac}"), + (0xAB7D, "\u{13ad}"), + (0xAB7E, "\u{13ae}"), + (0xAB7F, "\u{13af}"), + (0xAB80, "\u{13b0}"), + (0xAB81, "\u{13b1}"), + (0xAB82, "\u{13b2}"), + (0xAB83, "\u{13b3}"), + (0xAB84, "\u{13b4}"), + (0xAB85, "\u{13b5}"), + (0xAB86, "\u{13b6}"), + (0xAB87, "\u{13b7}"), + (0xAB88, "\u{13b8}"), + (0xAB89, "\u{13b9}"), + (0xAB8A, "\u{13ba}"), + (0xAB8B, "\u{13bb}"), + (0xAB8C, "\u{13bc}"), + (0xAB8D, "\u{13bd}"), + (0xAB8E, "\u{13be}"), + (0xAB8F, "\u{13bf}"), + (0xAB90, "\u{13c0}"), + (0xAB91, "\u{13c1}"), + (0xAB92, "\u{13c2}"), + (0xAB93, "\u{13c3}"), + (0xAB94, "\u{13c4}"), + (0xAB95, "\u{13c5}"), + (0xAB96, "\u{13c6}"), + (0xAB97, "\u{13c7}"), + (0xAB98, "\u{13c8}"), + (0xAB99, "\u{13c9}"), + (0xAB9A, "\u{13ca}"), + (0xAB9B, "\u{13cb}"), + (0xAB9C, "\u{13cc}"), + (0xAB9D, "\u{13cd}"), + (0xAB9E, "\u{13ce}"), + (0xAB9F, "\u{13cf}"), + (0xABA0, "\u{13d0}"), + (0xABA1, "\u{13d1}"), + (0xABA2, "\u{13d2}"), + (0xABA3, "\u{13d3}"), + (0xABA4, "\u{13d4}"), + (0xABA5, "\u{13d5}"), + (0xABA6, "\u{13d6}"), + (0xABA7, "\u{13d7}"), + (0xABA8, "\u{13d8}"), + (0xABA9, "\u{13d9}"), + (0xABAA, "\u{13da}"), + (0xABAB, "\u{13db}"), + (0xABAC, "\u{13dc}"), + (0xABAD, "\u{13dd}"), + (0xABAE, "\u{13de}"), + (0xABAF, "\u{13df}"), + (0xABB0, "\u{13e0}"), + (0xABB1, "\u{13e1}"), + (0xABB2, "\u{13e2}"), + (0xABB3, "\u{13e3}"), + (0xABB4, "\u{13e4}"), + (0xABB5, "\u{13e5}"), + (0xABB6, "\u{13e6}"), + (0xABB7, "\u{13e7}"), + (0xABB8, "\u{13e8}"), + (0xABB9, "\u{13e9}"), + (0xABBA, "\u{13ea}"), + (0xABBB, "\u{13eb}"), + (0xABBC, "\u{13ec}"), + (0xABBD, "\u{13ed}"), + (0xABBE, "\u{13ee}"), + (0xABBF, "\u{13ef}"), + (0xFB00, "\u{66}\u{66}"), + (0xFB01, "\u{66}\u{69}"), + (0xFB02, "\u{66}\u{6c}"), + (0xFB03, "\u{66}\u{66}\u{69}"), + (0xFB04, "\u{66}\u{66}\u{6c}"), + (0xFB05, "\u{73}\u{74}"), + (0xFB06, "\u{73}\u{74}"), + (0xFB13, "\u{574}\u{576}"), + (0xFB14, "\u{574}\u{565}"), + (0xFB15, "\u{574}\u{56b}"), + (0xFB16, "\u{57e}\u{576}"), + (0xFB17, "\u{574}\u{56d}"), + (0xFF21, "\u{ff41}"), + (0xFF22, "\u{ff42}"), + (0xFF23, "\u{ff43}"), + (0xFF24, "\u{ff44}"), + (0xFF25, "\u{ff45}"), + (0xFF26, "\u{ff46}"), + (0xFF27, "\u{ff47}"), + (0xFF28, "\u{ff48}"), + (0xFF29, "\u{ff49}"), + (0xFF2A, "\u{ff4a}"), + (0xFF2B, "\u{ff4b}"), + (0xFF2C, "\u{ff4c}"), + (0xFF2D, "\u{ff4d}"), + (0xFF2E, "\u{ff4e}"), + (0xFF2F, "\u{ff4f}"), + (0xFF30, "\u{ff50}"), + (0xFF31, "\u{ff51}"), + (0xFF32, "\u{ff52}"), + (0xFF33, "\u{ff53}"), + (0xFF34, "\u{ff54}"), + (0xFF35, "\u{ff55}"), + (0xFF36, "\u{ff56}"), + (0xFF37, "\u{ff57}"), + (0xFF38, "\u{ff58}"), + (0xFF39, "\u{ff59}"), + (0xFF3A, "\u{ff5a}"), + (0x10400, "\u{10428}"), + (0x10401, "\u{10429}"), + (0x10402, "\u{1042a}"), + (0x10403, "\u{1042b}"), + (0x10404, "\u{1042c}"), + (0x10405, "\u{1042d}"), + (0x10406, "\u{1042e}"), + (0x10407, "\u{1042f}"), + (0x10408, "\u{10430}"), + (0x10409, "\u{10431}"), + (0x1040A, "\u{10432}"), + (0x1040B, "\u{10433}"), + (0x1040C, "\u{10434}"), + (0x1040D, "\u{10435}"), + (0x1040E, "\u{10436}"), + (0x1040F, "\u{10437}"), + (0x10410, "\u{10438}"), + (0x10411, "\u{10439}"), + (0x10412, "\u{1043a}"), + (0x10413, "\u{1043b}"), + (0x10414, "\u{1043c}"), + (0x10415, "\u{1043d}"), + (0x10416, "\u{1043e}"), + (0x10417, "\u{1043f}"), + (0x10418, "\u{10440}"), + (0x10419, "\u{10441}"), + (0x1041A, "\u{10442}"), + (0x1041B, "\u{10443}"), + (0x1041C, "\u{10444}"), + (0x1041D, "\u{10445}"), + (0x1041E, "\u{10446}"), + (0x1041F, "\u{10447}"), + (0x10420, "\u{10448}"), + (0x10421, "\u{10449}"), + (0x10422, "\u{1044a}"), + (0x10423, "\u{1044b}"), + (0x10424, "\u{1044c}"), + (0x10425, "\u{1044d}"), + (0x10426, "\u{1044e}"), + (0x10427, "\u{1044f}"), + (0x104B0, "\u{104d8}"), + (0x104B1, "\u{104d9}"), + (0x104B2, "\u{104da}"), + (0x104B3, "\u{104db}"), + (0x104B4, "\u{104dc}"), + (0x104B5, "\u{104dd}"), + (0x104B6, "\u{104de}"), + (0x104B7, "\u{104df}"), + (0x104B8, "\u{104e0}"), + (0x104B9, "\u{104e1}"), + (0x104BA, "\u{104e2}"), + (0x104BB, "\u{104e3}"), + (0x104BC, "\u{104e4}"), + (0x104BD, "\u{104e5}"), + (0x104BE, "\u{104e6}"), + (0x104BF, "\u{104e7}"), + (0x104C0, "\u{104e8}"), + (0x104C1, "\u{104e9}"), + (0x104C2, "\u{104ea}"), + (0x104C3, "\u{104eb}"), + (0x104C4, "\u{104ec}"), + (0x104C5, "\u{104ed}"), + (0x104C6, "\u{104ee}"), + (0x104C7, "\u{104ef}"), + (0x104C8, "\u{104f0}"), + (0x104C9, "\u{104f1}"), + (0x104CA, "\u{104f2}"), + (0x104CB, "\u{104f3}"), + (0x104CC, "\u{104f4}"), + (0x104CD, "\u{104f5}"), + (0x104CE, "\u{104f6}"), + (0x104CF, "\u{104f7}"), + (0x104D0, "\u{104f8}"), + (0x104D1, "\u{104f9}"), + (0x104D2, "\u{104fa}"), + (0x104D3, "\u{104fb}"), + (0x10570, "\u{10597}"), + (0x10571, "\u{10598}"), + (0x10572, "\u{10599}"), + (0x10573, "\u{1059a}"), + (0x10574, "\u{1059b}"), + (0x10575, "\u{1059c}"), + (0x10576, "\u{1059d}"), + (0x10577, "\u{1059e}"), + (0x10578, "\u{1059f}"), + (0x10579, "\u{105a0}"), + (0x1057A, "\u{105a1}"), + (0x1057C, "\u{105a3}"), + (0x1057D, "\u{105a4}"), + (0x1057E, "\u{105a5}"), + (0x1057F, "\u{105a6}"), + (0x10580, "\u{105a7}"), + (0x10581, "\u{105a8}"), + (0x10582, "\u{105a9}"), + (0x10583, "\u{105aa}"), + (0x10584, "\u{105ab}"), + (0x10585, "\u{105ac}"), + (0x10586, "\u{105ad}"), + (0x10587, "\u{105ae}"), + (0x10588, "\u{105af}"), + (0x10589, "\u{105b0}"), + (0x1058A, "\u{105b1}"), + (0x1058C, "\u{105b3}"), + (0x1058D, "\u{105b4}"), + (0x1058E, "\u{105b5}"), + (0x1058F, "\u{105b6}"), + (0x10590, "\u{105b7}"), + (0x10591, "\u{105b8}"), + (0x10592, "\u{105b9}"), + (0x10594, "\u{105bb}"), + (0x10595, "\u{105bc}"), + (0x10C80, "\u{10cc0}"), + (0x10C81, "\u{10cc1}"), + (0x10C82, "\u{10cc2}"), + (0x10C83, "\u{10cc3}"), + (0x10C84, "\u{10cc4}"), + (0x10C85, "\u{10cc5}"), + (0x10C86, "\u{10cc6}"), + (0x10C87, "\u{10cc7}"), + (0x10C88, "\u{10cc8}"), + (0x10C89, "\u{10cc9}"), + (0x10C8A, "\u{10cca}"), + (0x10C8B, "\u{10ccb}"), + (0x10C8C, "\u{10ccc}"), + (0x10C8D, "\u{10ccd}"), + (0x10C8E, "\u{10cce}"), + (0x10C8F, "\u{10ccf}"), + (0x10C90, "\u{10cd0}"), + (0x10C91, "\u{10cd1}"), + (0x10C92, "\u{10cd2}"), + (0x10C93, "\u{10cd3}"), + (0x10C94, "\u{10cd4}"), + (0x10C95, "\u{10cd5}"), + (0x10C96, "\u{10cd6}"), + (0x10C97, "\u{10cd7}"), + (0x10C98, "\u{10cd8}"), + (0x10C99, "\u{10cd9}"), + (0x10C9A, "\u{10cda}"), + (0x10C9B, "\u{10cdb}"), + (0x10C9C, "\u{10cdc}"), + (0x10C9D, "\u{10cdd}"), + (0x10C9E, "\u{10cde}"), + (0x10C9F, "\u{10cdf}"), + (0x10CA0, "\u{10ce0}"), + (0x10CA1, "\u{10ce1}"), + (0x10CA2, "\u{10ce2}"), + (0x10CA3, "\u{10ce3}"), + (0x10CA4, "\u{10ce4}"), + (0x10CA5, "\u{10ce5}"), + (0x10CA6, "\u{10ce6}"), + (0x10CA7, "\u{10ce7}"), + (0x10CA8, "\u{10ce8}"), + (0x10CA9, "\u{10ce9}"), + (0x10CAA, "\u{10cea}"), + (0x10CAB, "\u{10ceb}"), + (0x10CAC, "\u{10cec}"), + (0x10CAD, "\u{10ced}"), + (0x10CAE, "\u{10cee}"), + (0x10CAF, "\u{10cef}"), + (0x10CB0, "\u{10cf0}"), + (0x10CB1, "\u{10cf1}"), + (0x10CB2, "\u{10cf2}"), + (0x118A0, "\u{118c0}"), + (0x118A1, "\u{118c1}"), + (0x118A2, "\u{118c2}"), + (0x118A3, "\u{118c3}"), + (0x118A4, "\u{118c4}"), + (0x118A5, "\u{118c5}"), + (0x118A6, "\u{118c6}"), + (0x118A7, "\u{118c7}"), + (0x118A8, "\u{118c8}"), + (0x118A9, "\u{118c9}"), + (0x118AA, "\u{118ca}"), + (0x118AB, "\u{118cb}"), + (0x118AC, "\u{118cc}"), + (0x118AD, "\u{118cd}"), + (0x118AE, "\u{118ce}"), + (0x118AF, "\u{118cf}"), + (0x118B0, "\u{118d0}"), + (0x118B1, "\u{118d1}"), + (0x118B2, "\u{118d2}"), + (0x118B3, "\u{118d3}"), + (0x118B4, "\u{118d4}"), + (0x118B5, "\u{118d5}"), + (0x118B6, "\u{118d6}"), + (0x118B7, "\u{118d7}"), + (0x118B8, "\u{118d8}"), + (0x118B9, "\u{118d9}"), + (0x118BA, "\u{118da}"), + (0x118BB, "\u{118db}"), + (0x118BC, "\u{118dc}"), + (0x118BD, "\u{118dd}"), + (0x118BE, "\u{118de}"), + (0x118BF, "\u{118df}"), + (0x16E40, "\u{16e60}"), + (0x16E41, "\u{16e61}"), + (0x16E42, "\u{16e62}"), + (0x16E43, "\u{16e63}"), + (0x16E44, "\u{16e64}"), + (0x16E45, "\u{16e65}"), + (0x16E46, "\u{16e66}"), + (0x16E47, "\u{16e67}"), + (0x16E48, "\u{16e68}"), + (0x16E49, "\u{16e69}"), + (0x16E4A, "\u{16e6a}"), + (0x16E4B, "\u{16e6b}"), + (0x16E4C, "\u{16e6c}"), + (0x16E4D, "\u{16e6d}"), + (0x16E4E, "\u{16e6e}"), + (0x16E4F, "\u{16e6f}"), + (0x16E50, "\u{16e70}"), + (0x16E51, "\u{16e71}"), + (0x16E52, "\u{16e72}"), + (0x16E53, "\u{16e73}"), + (0x16E54, "\u{16e74}"), + (0x16E55, "\u{16e75}"), + (0x16E56, "\u{16e76}"), + (0x16E57, "\u{16e77}"), + (0x16E58, "\u{16e78}"), + (0x16E59, "\u{16e79}"), + (0x16E5A, "\u{16e7a}"), + (0x16E5B, "\u{16e7b}"), + (0x16E5C, "\u{16e7c}"), + (0x16E5D, "\u{16e7d}"), + (0x16E5E, "\u{16e7e}"), + (0x16E5F, "\u{16e7f}"), + (0x1E900, "\u{1e922}"), + (0x1E901, "\u{1e923}"), + (0x1E902, "\u{1e924}"), + (0x1E903, "\u{1e925}"), + (0x1E904, "\u{1e926}"), + (0x1E905, "\u{1e927}"), + (0x1E906, "\u{1e928}"), + (0x1E907, "\u{1e929}"), + (0x1E908, "\u{1e92a}"), + (0x1E909, "\u{1e92b}"), + (0x1E90A, "\u{1e92c}"), + (0x1E90B, "\u{1e92d}"), + (0x1E90C, "\u{1e92e}"), + (0x1E90D, "\u{1e92f}"), + (0x1E90E, "\u{1e930}"), + (0x1E90F, "\u{1e931}"), + (0x1E910, "\u{1e932}"), + (0x1E911, "\u{1e933}"), + (0x1E912, "\u{1e934}"), + (0x1E913, "\u{1e935}"), + (0x1E914, "\u{1e936}"), + (0x1E915, "\u{1e937}"), + (0x1E916, "\u{1e938}"), + (0x1E917, "\u{1e939}"), + (0x1E918, "\u{1e93a}"), + (0x1E919, "\u{1e93b}"), + (0x1E91A, "\u{1e93c}"), + (0x1E91B, "\u{1e93d}"), + (0x1E91C, "\u{1e93e}"), + (0x1E91D, "\u{1e93f}"), + (0x1E91E, "\u{1e940}"), + (0x1E91F, "\u{1e941}"), + (0x1E920, "\u{1e942}"), + (0x1E921, "\u{1e943}"), +] diff --git a/crates/sqlbuild-core/src/text/casefold_mappings/unicode_16_0_0.in b/crates/sqlbuild-core/src/text/casefold_mappings/unicode_16_0_0.in new file mode 100644 index 0000000000..281e3028bd --- /dev/null +++ b/crates/sqlbuild-core/src/text/casefold_mappings/unicode_16_0_0.in @@ -0,0 +1,1561 @@ +// Generated by `scripts/generate_python_char_table.py`; do not edit. +// Every character `str.casefold()` changes in Unicode 16.0.0, in code point order. +&[ + (0x0041, "\u{61}"), + (0x0042, "\u{62}"), + (0x0043, "\u{63}"), + (0x0044, "\u{64}"), + (0x0045, "\u{65}"), + (0x0046, "\u{66}"), + (0x0047, "\u{67}"), + (0x0048, "\u{68}"), + (0x0049, "\u{69}"), + (0x004A, "\u{6a}"), + (0x004B, "\u{6b}"), + (0x004C, "\u{6c}"), + (0x004D, "\u{6d}"), + (0x004E, "\u{6e}"), + (0x004F, "\u{6f}"), + (0x0050, "\u{70}"), + (0x0051, "\u{71}"), + (0x0052, "\u{72}"), + (0x0053, "\u{73}"), + (0x0054, "\u{74}"), + (0x0055, "\u{75}"), + (0x0056, "\u{76}"), + (0x0057, "\u{77}"), + (0x0058, "\u{78}"), + (0x0059, "\u{79}"), + (0x005A, "\u{7a}"), + (0x00B5, "\u{3bc}"), + (0x00C0, "\u{e0}"), + (0x00C1, "\u{e1}"), + (0x00C2, "\u{e2}"), + (0x00C3, "\u{e3}"), + (0x00C4, "\u{e4}"), + (0x00C5, "\u{e5}"), + (0x00C6, "\u{e6}"), + (0x00C7, "\u{e7}"), + (0x00C8, "\u{e8}"), + (0x00C9, "\u{e9}"), + (0x00CA, "\u{ea}"), + (0x00CB, "\u{eb}"), + (0x00CC, "\u{ec}"), + (0x00CD, "\u{ed}"), + (0x00CE, "\u{ee}"), + (0x00CF, "\u{ef}"), + (0x00D0, "\u{f0}"), + (0x00D1, "\u{f1}"), + (0x00D2, "\u{f2}"), + (0x00D3, "\u{f3}"), + (0x00D4, "\u{f4}"), + (0x00D5, "\u{f5}"), + (0x00D6, "\u{f6}"), + (0x00D8, "\u{f8}"), + (0x00D9, "\u{f9}"), + (0x00DA, "\u{fa}"), + (0x00DB, "\u{fb}"), + (0x00DC, "\u{fc}"), + (0x00DD, "\u{fd}"), + (0x00DE, "\u{fe}"), + (0x00DF, "\u{73}\u{73}"), + (0x0100, "\u{101}"), + (0x0102, "\u{103}"), + (0x0104, "\u{105}"), + (0x0106, "\u{107}"), + (0x0108, "\u{109}"), + (0x010A, "\u{10b}"), + (0x010C, "\u{10d}"), + (0x010E, "\u{10f}"), + (0x0110, "\u{111}"), + (0x0112, "\u{113}"), + (0x0114, "\u{115}"), + (0x0116, "\u{117}"), + (0x0118, "\u{119}"), + (0x011A, "\u{11b}"), + (0x011C, "\u{11d}"), + (0x011E, "\u{11f}"), + (0x0120, "\u{121}"), + (0x0122, "\u{123}"), + (0x0124, "\u{125}"), + (0x0126, "\u{127}"), + (0x0128, "\u{129}"), + (0x012A, "\u{12b}"), + (0x012C, "\u{12d}"), + (0x012E, "\u{12f}"), + (0x0130, "\u{69}\u{307}"), + (0x0132, "\u{133}"), + (0x0134, "\u{135}"), + (0x0136, "\u{137}"), + (0x0139, "\u{13a}"), + (0x013B, "\u{13c}"), + (0x013D, "\u{13e}"), + (0x013F, "\u{140}"), + (0x0141, "\u{142}"), + (0x0143, "\u{144}"), + (0x0145, "\u{146}"), + (0x0147, "\u{148}"), + (0x0149, "\u{2bc}\u{6e}"), + (0x014A, "\u{14b}"), + (0x014C, "\u{14d}"), + (0x014E, "\u{14f}"), + (0x0150, "\u{151}"), + (0x0152, "\u{153}"), + (0x0154, "\u{155}"), + (0x0156, "\u{157}"), + (0x0158, "\u{159}"), + (0x015A, "\u{15b}"), + (0x015C, "\u{15d}"), + (0x015E, "\u{15f}"), + (0x0160, "\u{161}"), + (0x0162, "\u{163}"), + (0x0164, "\u{165}"), + (0x0166, "\u{167}"), + (0x0168, "\u{169}"), + (0x016A, "\u{16b}"), + (0x016C, "\u{16d}"), + (0x016E, "\u{16f}"), + (0x0170, "\u{171}"), + (0x0172, "\u{173}"), + (0x0174, "\u{175}"), + (0x0176, "\u{177}"), + (0x0178, "\u{ff}"), + (0x0179, "\u{17a}"), + (0x017B, "\u{17c}"), + (0x017D, "\u{17e}"), + (0x017F, "\u{73}"), + (0x0181, "\u{253}"), + (0x0182, "\u{183}"), + (0x0184, "\u{185}"), + (0x0186, "\u{254}"), + (0x0187, "\u{188}"), + (0x0189, "\u{256}"), + (0x018A, "\u{257}"), + (0x018B, "\u{18c}"), + (0x018E, "\u{1dd}"), + (0x018F, "\u{259}"), + (0x0190, "\u{25b}"), + (0x0191, "\u{192}"), + (0x0193, "\u{260}"), + (0x0194, "\u{263}"), + (0x0196, "\u{269}"), + (0x0197, "\u{268}"), + (0x0198, "\u{199}"), + (0x019C, "\u{26f}"), + (0x019D, "\u{272}"), + (0x019F, "\u{275}"), + (0x01A0, "\u{1a1}"), + (0x01A2, "\u{1a3}"), + (0x01A4, "\u{1a5}"), + (0x01A6, "\u{280}"), + (0x01A7, "\u{1a8}"), + (0x01A9, "\u{283}"), + (0x01AC, "\u{1ad}"), + (0x01AE, "\u{288}"), + (0x01AF, "\u{1b0}"), + (0x01B1, "\u{28a}"), + (0x01B2, "\u{28b}"), + (0x01B3, "\u{1b4}"), + (0x01B5, "\u{1b6}"), + (0x01B7, "\u{292}"), + (0x01B8, "\u{1b9}"), + (0x01BC, "\u{1bd}"), + (0x01C4, "\u{1c6}"), + (0x01C5, "\u{1c6}"), + (0x01C7, "\u{1c9}"), + (0x01C8, "\u{1c9}"), + (0x01CA, "\u{1cc}"), + (0x01CB, "\u{1cc}"), + (0x01CD, "\u{1ce}"), + (0x01CF, "\u{1d0}"), + (0x01D1, "\u{1d2}"), + (0x01D3, "\u{1d4}"), + (0x01D5, "\u{1d6}"), + (0x01D7, "\u{1d8}"), + (0x01D9, "\u{1da}"), + (0x01DB, "\u{1dc}"), + (0x01DE, "\u{1df}"), + (0x01E0, "\u{1e1}"), + (0x01E2, "\u{1e3}"), + (0x01E4, "\u{1e5}"), + (0x01E6, "\u{1e7}"), + (0x01E8, "\u{1e9}"), + (0x01EA, "\u{1eb}"), + (0x01EC, "\u{1ed}"), + (0x01EE, "\u{1ef}"), + (0x01F0, "\u{6a}\u{30c}"), + (0x01F1, "\u{1f3}"), + (0x01F2, "\u{1f3}"), + (0x01F4, "\u{1f5}"), + (0x01F6, "\u{195}"), + (0x01F7, "\u{1bf}"), + (0x01F8, "\u{1f9}"), + (0x01FA, "\u{1fb}"), + (0x01FC, "\u{1fd}"), + (0x01FE, "\u{1ff}"), + (0x0200, "\u{201}"), + (0x0202, "\u{203}"), + (0x0204, "\u{205}"), + (0x0206, "\u{207}"), + (0x0208, "\u{209}"), + (0x020A, "\u{20b}"), + (0x020C, "\u{20d}"), + (0x020E, "\u{20f}"), + (0x0210, "\u{211}"), + (0x0212, "\u{213}"), + (0x0214, "\u{215}"), + (0x0216, "\u{217}"), + (0x0218, "\u{219}"), + (0x021A, "\u{21b}"), + (0x021C, "\u{21d}"), + (0x021E, "\u{21f}"), + (0x0220, "\u{19e}"), + (0x0222, "\u{223}"), + (0x0224, "\u{225}"), + (0x0226, "\u{227}"), + (0x0228, "\u{229}"), + (0x022A, "\u{22b}"), + (0x022C, "\u{22d}"), + (0x022E, "\u{22f}"), + (0x0230, "\u{231}"), + (0x0232, "\u{233}"), + (0x023A, "\u{2c65}"), + (0x023B, "\u{23c}"), + (0x023D, "\u{19a}"), + (0x023E, "\u{2c66}"), + (0x0241, "\u{242}"), + (0x0243, "\u{180}"), + (0x0244, "\u{289}"), + (0x0245, "\u{28c}"), + (0x0246, "\u{247}"), + (0x0248, "\u{249}"), + (0x024A, "\u{24b}"), + (0x024C, "\u{24d}"), + (0x024E, "\u{24f}"), + (0x0345, "\u{3b9}"), + (0x0370, "\u{371}"), + (0x0372, "\u{373}"), + (0x0376, "\u{377}"), + (0x037F, "\u{3f3}"), + (0x0386, "\u{3ac}"), + (0x0388, "\u{3ad}"), + (0x0389, "\u{3ae}"), + (0x038A, "\u{3af}"), + (0x038C, "\u{3cc}"), + (0x038E, "\u{3cd}"), + (0x038F, "\u{3ce}"), + (0x0390, "\u{3b9}\u{308}\u{301}"), + (0x0391, "\u{3b1}"), + (0x0392, "\u{3b2}"), + (0x0393, "\u{3b3}"), + (0x0394, "\u{3b4}"), + (0x0395, "\u{3b5}"), + (0x0396, "\u{3b6}"), + (0x0397, "\u{3b7}"), + (0x0398, "\u{3b8}"), + (0x0399, "\u{3b9}"), + (0x039A, "\u{3ba}"), + (0x039B, "\u{3bb}"), + (0x039C, "\u{3bc}"), + (0x039D, "\u{3bd}"), + (0x039E, "\u{3be}"), + (0x039F, "\u{3bf}"), + (0x03A0, "\u{3c0}"), + (0x03A1, "\u{3c1}"), + (0x03A3, "\u{3c3}"), + (0x03A4, "\u{3c4}"), + (0x03A5, "\u{3c5}"), + (0x03A6, "\u{3c6}"), + (0x03A7, "\u{3c7}"), + (0x03A8, "\u{3c8}"), + (0x03A9, "\u{3c9}"), + (0x03AA, "\u{3ca}"), + (0x03AB, "\u{3cb}"), + (0x03B0, "\u{3c5}\u{308}\u{301}"), + (0x03C2, "\u{3c3}"), + (0x03CF, "\u{3d7}"), + (0x03D0, "\u{3b2}"), + (0x03D1, "\u{3b8}"), + (0x03D5, "\u{3c6}"), + (0x03D6, "\u{3c0}"), + (0x03D8, "\u{3d9}"), + (0x03DA, "\u{3db}"), + (0x03DC, "\u{3dd}"), + (0x03DE, "\u{3df}"), + (0x03E0, "\u{3e1}"), + (0x03E2, "\u{3e3}"), + (0x03E4, "\u{3e5}"), + (0x03E6, "\u{3e7}"), + (0x03E8, "\u{3e9}"), + (0x03EA, "\u{3eb}"), + (0x03EC, "\u{3ed}"), + (0x03EE, "\u{3ef}"), + (0x03F0, "\u{3ba}"), + (0x03F1, "\u{3c1}"), + (0x03F4, "\u{3b8}"), + (0x03F5, "\u{3b5}"), + (0x03F7, "\u{3f8}"), + (0x03F9, "\u{3f2}"), + (0x03FA, "\u{3fb}"), + (0x03FD, "\u{37b}"), + (0x03FE, "\u{37c}"), + (0x03FF, "\u{37d}"), + (0x0400, "\u{450}"), + (0x0401, "\u{451}"), + (0x0402, "\u{452}"), + (0x0403, "\u{453}"), + (0x0404, "\u{454}"), + (0x0405, "\u{455}"), + (0x0406, "\u{456}"), + (0x0407, "\u{457}"), + (0x0408, "\u{458}"), + (0x0409, "\u{459}"), + (0x040A, "\u{45a}"), + (0x040B, "\u{45b}"), + (0x040C, "\u{45c}"), + (0x040D, "\u{45d}"), + (0x040E, "\u{45e}"), + (0x040F, "\u{45f}"), + (0x0410, "\u{430}"), + (0x0411, "\u{431}"), + (0x0412, "\u{432}"), + (0x0413, "\u{433}"), + (0x0414, "\u{434}"), + (0x0415, "\u{435}"), + (0x0416, "\u{436}"), + (0x0417, "\u{437}"), + (0x0418, "\u{438}"), + (0x0419, "\u{439}"), + (0x041A, "\u{43a}"), + (0x041B, "\u{43b}"), + (0x041C, "\u{43c}"), + (0x041D, "\u{43d}"), + (0x041E, "\u{43e}"), + (0x041F, "\u{43f}"), + (0x0420, "\u{440}"), + (0x0421, "\u{441}"), + (0x0422, "\u{442}"), + (0x0423, "\u{443}"), + (0x0424, "\u{444}"), + (0x0425, "\u{445}"), + (0x0426, "\u{446}"), + (0x0427, "\u{447}"), + (0x0428, "\u{448}"), + (0x0429, "\u{449}"), + (0x042A, "\u{44a}"), + (0x042B, "\u{44b}"), + (0x042C, "\u{44c}"), + (0x042D, "\u{44d}"), + (0x042E, "\u{44e}"), + (0x042F, "\u{44f}"), + (0x0460, "\u{461}"), + (0x0462, "\u{463}"), + (0x0464, "\u{465}"), + (0x0466, "\u{467}"), + (0x0468, "\u{469}"), + (0x046A, "\u{46b}"), + (0x046C, "\u{46d}"), + (0x046E, "\u{46f}"), + (0x0470, "\u{471}"), + (0x0472, "\u{473}"), + (0x0474, "\u{475}"), + (0x0476, "\u{477}"), + (0x0478, "\u{479}"), + (0x047A, "\u{47b}"), + (0x047C, "\u{47d}"), + (0x047E, "\u{47f}"), + (0x0480, "\u{481}"), + (0x048A, "\u{48b}"), + (0x048C, "\u{48d}"), + (0x048E, "\u{48f}"), + (0x0490, "\u{491}"), + (0x0492, "\u{493}"), + (0x0494, "\u{495}"), + (0x0496, "\u{497}"), + (0x0498, "\u{499}"), + (0x049A, "\u{49b}"), + (0x049C, "\u{49d}"), + (0x049E, "\u{49f}"), + (0x04A0, "\u{4a1}"), + (0x04A2, "\u{4a3}"), + (0x04A4, "\u{4a5}"), + (0x04A6, "\u{4a7}"), + (0x04A8, "\u{4a9}"), + (0x04AA, "\u{4ab}"), + (0x04AC, "\u{4ad}"), + (0x04AE, "\u{4af}"), + (0x04B0, "\u{4b1}"), + (0x04B2, "\u{4b3}"), + (0x04B4, "\u{4b5}"), + (0x04B6, "\u{4b7}"), + (0x04B8, "\u{4b9}"), + (0x04BA, "\u{4bb}"), + (0x04BC, "\u{4bd}"), + (0x04BE, "\u{4bf}"), + (0x04C0, "\u{4cf}"), + (0x04C1, "\u{4c2}"), + (0x04C3, "\u{4c4}"), + (0x04C5, "\u{4c6}"), + (0x04C7, "\u{4c8}"), + (0x04C9, "\u{4ca}"), + (0x04CB, "\u{4cc}"), + (0x04CD, "\u{4ce}"), + (0x04D0, "\u{4d1}"), + (0x04D2, "\u{4d3}"), + (0x04D4, "\u{4d5}"), + (0x04D6, "\u{4d7}"), + (0x04D8, "\u{4d9}"), + (0x04DA, "\u{4db}"), + (0x04DC, "\u{4dd}"), + (0x04DE, "\u{4df}"), + (0x04E0, "\u{4e1}"), + (0x04E2, "\u{4e3}"), + (0x04E4, "\u{4e5}"), + (0x04E6, "\u{4e7}"), + (0x04E8, "\u{4e9}"), + (0x04EA, "\u{4eb}"), + (0x04EC, "\u{4ed}"), + (0x04EE, "\u{4ef}"), + (0x04F0, "\u{4f1}"), + (0x04F2, "\u{4f3}"), + (0x04F4, "\u{4f5}"), + (0x04F6, "\u{4f7}"), + (0x04F8, "\u{4f9}"), + (0x04FA, "\u{4fb}"), + (0x04FC, "\u{4fd}"), + (0x04FE, "\u{4ff}"), + (0x0500, "\u{501}"), + (0x0502, "\u{503}"), + (0x0504, "\u{505}"), + (0x0506, "\u{507}"), + (0x0508, "\u{509}"), + (0x050A, "\u{50b}"), + (0x050C, "\u{50d}"), + (0x050E, "\u{50f}"), + (0x0510, "\u{511}"), + (0x0512, "\u{513}"), + (0x0514, "\u{515}"), + (0x0516, "\u{517}"), + (0x0518, "\u{519}"), + (0x051A, "\u{51b}"), + (0x051C, "\u{51d}"), + (0x051E, "\u{51f}"), + (0x0520, "\u{521}"), + (0x0522, "\u{523}"), + (0x0524, "\u{525}"), + (0x0526, "\u{527}"), + (0x0528, "\u{529}"), + (0x052A, "\u{52b}"), + (0x052C, "\u{52d}"), + (0x052E, "\u{52f}"), + (0x0531, "\u{561}"), + (0x0532, "\u{562}"), + (0x0533, "\u{563}"), + (0x0534, "\u{564}"), + (0x0535, "\u{565}"), + (0x0536, "\u{566}"), + (0x0537, "\u{567}"), + (0x0538, "\u{568}"), + (0x0539, "\u{569}"), + (0x053A, "\u{56a}"), + (0x053B, "\u{56b}"), + (0x053C, "\u{56c}"), + (0x053D, "\u{56d}"), + (0x053E, "\u{56e}"), + (0x053F, "\u{56f}"), + (0x0540, "\u{570}"), + (0x0541, "\u{571}"), + (0x0542, "\u{572}"), + (0x0543, "\u{573}"), + (0x0544, "\u{574}"), + (0x0545, "\u{575}"), + (0x0546, "\u{576}"), + (0x0547, "\u{577}"), + (0x0548, "\u{578}"), + (0x0549, "\u{579}"), + (0x054A, "\u{57a}"), + (0x054B, "\u{57b}"), + (0x054C, "\u{57c}"), + (0x054D, "\u{57d}"), + (0x054E, "\u{57e}"), + (0x054F, "\u{57f}"), + (0x0550, "\u{580}"), + (0x0551, "\u{581}"), + (0x0552, "\u{582}"), + (0x0553, "\u{583}"), + (0x0554, "\u{584}"), + (0x0555, "\u{585}"), + (0x0556, "\u{586}"), + (0x0587, "\u{565}\u{582}"), + (0x10A0, "\u{2d00}"), + (0x10A1, "\u{2d01}"), + (0x10A2, "\u{2d02}"), + (0x10A3, "\u{2d03}"), + (0x10A4, "\u{2d04}"), + (0x10A5, "\u{2d05}"), + (0x10A6, "\u{2d06}"), + (0x10A7, "\u{2d07}"), + (0x10A8, "\u{2d08}"), + (0x10A9, "\u{2d09}"), + (0x10AA, "\u{2d0a}"), + (0x10AB, "\u{2d0b}"), + (0x10AC, "\u{2d0c}"), + (0x10AD, "\u{2d0d}"), + (0x10AE, "\u{2d0e}"), + (0x10AF, "\u{2d0f}"), + (0x10B0, "\u{2d10}"), + (0x10B1, "\u{2d11}"), + (0x10B2, "\u{2d12}"), + (0x10B3, "\u{2d13}"), + (0x10B4, "\u{2d14}"), + (0x10B5, "\u{2d15}"), + (0x10B6, "\u{2d16}"), + (0x10B7, "\u{2d17}"), + (0x10B8, "\u{2d18}"), + (0x10B9, "\u{2d19}"), + (0x10BA, "\u{2d1a}"), + (0x10BB, "\u{2d1b}"), + (0x10BC, "\u{2d1c}"), + (0x10BD, "\u{2d1d}"), + (0x10BE, "\u{2d1e}"), + (0x10BF, "\u{2d1f}"), + (0x10C0, "\u{2d20}"), + (0x10C1, "\u{2d21}"), + (0x10C2, "\u{2d22}"), + (0x10C3, "\u{2d23}"), + (0x10C4, "\u{2d24}"), + (0x10C5, "\u{2d25}"), + (0x10C7, "\u{2d27}"), + (0x10CD, "\u{2d2d}"), + (0x13F8, "\u{13f0}"), + (0x13F9, "\u{13f1}"), + (0x13FA, "\u{13f2}"), + (0x13FB, "\u{13f3}"), + (0x13FC, "\u{13f4}"), + (0x13FD, "\u{13f5}"), + (0x1C80, "\u{432}"), + (0x1C81, "\u{434}"), + (0x1C82, "\u{43e}"), + (0x1C83, "\u{441}"), + (0x1C84, "\u{442}"), + (0x1C85, "\u{442}"), + (0x1C86, "\u{44a}"), + (0x1C87, "\u{463}"), + (0x1C88, "\u{a64b}"), + (0x1C89, "\u{1c8a}"), + (0x1C90, "\u{10d0}"), + (0x1C91, "\u{10d1}"), + (0x1C92, "\u{10d2}"), + (0x1C93, "\u{10d3}"), + (0x1C94, "\u{10d4}"), + (0x1C95, "\u{10d5}"), + (0x1C96, "\u{10d6}"), + (0x1C97, "\u{10d7}"), + (0x1C98, "\u{10d8}"), + (0x1C99, "\u{10d9}"), + (0x1C9A, "\u{10da}"), + (0x1C9B, "\u{10db}"), + (0x1C9C, "\u{10dc}"), + (0x1C9D, "\u{10dd}"), + (0x1C9E, "\u{10de}"), + (0x1C9F, "\u{10df}"), + (0x1CA0, "\u{10e0}"), + (0x1CA1, "\u{10e1}"), + (0x1CA2, "\u{10e2}"), + (0x1CA3, "\u{10e3}"), + (0x1CA4, "\u{10e4}"), + (0x1CA5, "\u{10e5}"), + (0x1CA6, "\u{10e6}"), + (0x1CA7, "\u{10e7}"), + (0x1CA8, "\u{10e8}"), + (0x1CA9, "\u{10e9}"), + (0x1CAA, "\u{10ea}"), + (0x1CAB, "\u{10eb}"), + (0x1CAC, "\u{10ec}"), + (0x1CAD, "\u{10ed}"), + (0x1CAE, "\u{10ee}"), + (0x1CAF, "\u{10ef}"), + (0x1CB0, "\u{10f0}"), + (0x1CB1, "\u{10f1}"), + (0x1CB2, "\u{10f2}"), + (0x1CB3, "\u{10f3}"), + (0x1CB4, "\u{10f4}"), + (0x1CB5, "\u{10f5}"), + (0x1CB6, "\u{10f6}"), + (0x1CB7, "\u{10f7}"), + (0x1CB8, "\u{10f8}"), + (0x1CB9, "\u{10f9}"), + (0x1CBA, "\u{10fa}"), + (0x1CBD, "\u{10fd}"), + (0x1CBE, "\u{10fe}"), + (0x1CBF, "\u{10ff}"), + (0x1E00, "\u{1e01}"), + (0x1E02, "\u{1e03}"), + (0x1E04, "\u{1e05}"), + (0x1E06, "\u{1e07}"), + (0x1E08, "\u{1e09}"), + (0x1E0A, "\u{1e0b}"), + (0x1E0C, "\u{1e0d}"), + (0x1E0E, "\u{1e0f}"), + (0x1E10, "\u{1e11}"), + (0x1E12, "\u{1e13}"), + (0x1E14, "\u{1e15}"), + (0x1E16, "\u{1e17}"), + (0x1E18, "\u{1e19}"), + (0x1E1A, "\u{1e1b}"), + (0x1E1C, "\u{1e1d}"), + (0x1E1E, "\u{1e1f}"), + (0x1E20, "\u{1e21}"), + (0x1E22, "\u{1e23}"), + (0x1E24, "\u{1e25}"), + (0x1E26, "\u{1e27}"), + (0x1E28, "\u{1e29}"), + (0x1E2A, "\u{1e2b}"), + (0x1E2C, "\u{1e2d}"), + (0x1E2E, "\u{1e2f}"), + (0x1E30, "\u{1e31}"), + (0x1E32, "\u{1e33}"), + (0x1E34, "\u{1e35}"), + (0x1E36, "\u{1e37}"), + (0x1E38, "\u{1e39}"), + (0x1E3A, "\u{1e3b}"), + (0x1E3C, "\u{1e3d}"), + (0x1E3E, "\u{1e3f}"), + (0x1E40, "\u{1e41}"), + (0x1E42, "\u{1e43}"), + (0x1E44, "\u{1e45}"), + (0x1E46, "\u{1e47}"), + (0x1E48, "\u{1e49}"), + (0x1E4A, "\u{1e4b}"), + (0x1E4C, "\u{1e4d}"), + (0x1E4E, "\u{1e4f}"), + (0x1E50, "\u{1e51}"), + (0x1E52, "\u{1e53}"), + (0x1E54, "\u{1e55}"), + (0x1E56, "\u{1e57}"), + (0x1E58, "\u{1e59}"), + (0x1E5A, "\u{1e5b}"), + (0x1E5C, "\u{1e5d}"), + (0x1E5E, "\u{1e5f}"), + (0x1E60, "\u{1e61}"), + (0x1E62, "\u{1e63}"), + (0x1E64, "\u{1e65}"), + (0x1E66, "\u{1e67}"), + (0x1E68, "\u{1e69}"), + (0x1E6A, "\u{1e6b}"), + (0x1E6C, "\u{1e6d}"), + (0x1E6E, "\u{1e6f}"), + (0x1E70, "\u{1e71}"), + (0x1E72, "\u{1e73}"), + (0x1E74, "\u{1e75}"), + (0x1E76, "\u{1e77}"), + (0x1E78, "\u{1e79}"), + (0x1E7A, "\u{1e7b}"), + (0x1E7C, "\u{1e7d}"), + (0x1E7E, "\u{1e7f}"), + (0x1E80, "\u{1e81}"), + (0x1E82, "\u{1e83}"), + (0x1E84, "\u{1e85}"), + (0x1E86, "\u{1e87}"), + (0x1E88, "\u{1e89}"), + (0x1E8A, "\u{1e8b}"), + (0x1E8C, "\u{1e8d}"), + (0x1E8E, "\u{1e8f}"), + (0x1E90, "\u{1e91}"), + (0x1E92, "\u{1e93}"), + (0x1E94, "\u{1e95}"), + (0x1E96, "\u{68}\u{331}"), + (0x1E97, "\u{74}\u{308}"), + (0x1E98, "\u{77}\u{30a}"), + (0x1E99, "\u{79}\u{30a}"), + (0x1E9A, "\u{61}\u{2be}"), + (0x1E9B, "\u{1e61}"), + (0x1E9E, "\u{73}\u{73}"), + (0x1EA0, "\u{1ea1}"), + (0x1EA2, "\u{1ea3}"), + (0x1EA4, "\u{1ea5}"), + (0x1EA6, "\u{1ea7}"), + (0x1EA8, "\u{1ea9}"), + (0x1EAA, "\u{1eab}"), + (0x1EAC, "\u{1ead}"), + (0x1EAE, "\u{1eaf}"), + (0x1EB0, "\u{1eb1}"), + (0x1EB2, "\u{1eb3}"), + (0x1EB4, "\u{1eb5}"), + (0x1EB6, "\u{1eb7}"), + (0x1EB8, "\u{1eb9}"), + (0x1EBA, "\u{1ebb}"), + (0x1EBC, "\u{1ebd}"), + (0x1EBE, "\u{1ebf}"), + (0x1EC0, "\u{1ec1}"), + (0x1EC2, "\u{1ec3}"), + (0x1EC4, "\u{1ec5}"), + (0x1EC6, "\u{1ec7}"), + (0x1EC8, "\u{1ec9}"), + (0x1ECA, "\u{1ecb}"), + (0x1ECC, "\u{1ecd}"), + (0x1ECE, "\u{1ecf}"), + (0x1ED0, "\u{1ed1}"), + (0x1ED2, "\u{1ed3}"), + (0x1ED4, "\u{1ed5}"), + (0x1ED6, "\u{1ed7}"), + (0x1ED8, "\u{1ed9}"), + (0x1EDA, "\u{1edb}"), + (0x1EDC, "\u{1edd}"), + (0x1EDE, "\u{1edf}"), + (0x1EE0, "\u{1ee1}"), + (0x1EE2, "\u{1ee3}"), + (0x1EE4, "\u{1ee5}"), + (0x1EE6, "\u{1ee7}"), + (0x1EE8, "\u{1ee9}"), + (0x1EEA, "\u{1eeb}"), + (0x1EEC, "\u{1eed}"), + (0x1EEE, "\u{1eef}"), + (0x1EF0, "\u{1ef1}"), + (0x1EF2, "\u{1ef3}"), + (0x1EF4, "\u{1ef5}"), + (0x1EF6, "\u{1ef7}"), + (0x1EF8, "\u{1ef9}"), + (0x1EFA, "\u{1efb}"), + (0x1EFC, "\u{1efd}"), + (0x1EFE, "\u{1eff}"), + (0x1F08, "\u{1f00}"), + (0x1F09, "\u{1f01}"), + (0x1F0A, "\u{1f02}"), + (0x1F0B, "\u{1f03}"), + (0x1F0C, "\u{1f04}"), + (0x1F0D, "\u{1f05}"), + (0x1F0E, "\u{1f06}"), + (0x1F0F, "\u{1f07}"), + (0x1F18, "\u{1f10}"), + (0x1F19, "\u{1f11}"), + (0x1F1A, "\u{1f12}"), + (0x1F1B, "\u{1f13}"), + (0x1F1C, "\u{1f14}"), + (0x1F1D, "\u{1f15}"), + (0x1F28, "\u{1f20}"), + (0x1F29, "\u{1f21}"), + (0x1F2A, "\u{1f22}"), + (0x1F2B, "\u{1f23}"), + (0x1F2C, "\u{1f24}"), + (0x1F2D, "\u{1f25}"), + (0x1F2E, "\u{1f26}"), + (0x1F2F, "\u{1f27}"), + (0x1F38, "\u{1f30}"), + (0x1F39, "\u{1f31}"), + (0x1F3A, "\u{1f32}"), + (0x1F3B, "\u{1f33}"), + (0x1F3C, "\u{1f34}"), + (0x1F3D, "\u{1f35}"), + (0x1F3E, "\u{1f36}"), + (0x1F3F, "\u{1f37}"), + (0x1F48, "\u{1f40}"), + (0x1F49, "\u{1f41}"), + (0x1F4A, "\u{1f42}"), + (0x1F4B, "\u{1f43}"), + (0x1F4C, "\u{1f44}"), + (0x1F4D, "\u{1f45}"), + (0x1F50, "\u{3c5}\u{313}"), + (0x1F52, "\u{3c5}\u{313}\u{300}"), + (0x1F54, "\u{3c5}\u{313}\u{301}"), + (0x1F56, "\u{3c5}\u{313}\u{342}"), + (0x1F59, "\u{1f51}"), + (0x1F5B, "\u{1f53}"), + (0x1F5D, "\u{1f55}"), + (0x1F5F, "\u{1f57}"), + (0x1F68, "\u{1f60}"), + (0x1F69, "\u{1f61}"), + (0x1F6A, "\u{1f62}"), + (0x1F6B, "\u{1f63}"), + (0x1F6C, "\u{1f64}"), + (0x1F6D, "\u{1f65}"), + (0x1F6E, "\u{1f66}"), + (0x1F6F, "\u{1f67}"), + (0x1F80, "\u{1f00}\u{3b9}"), + (0x1F81, "\u{1f01}\u{3b9}"), + (0x1F82, "\u{1f02}\u{3b9}"), + (0x1F83, "\u{1f03}\u{3b9}"), + (0x1F84, "\u{1f04}\u{3b9}"), + (0x1F85, "\u{1f05}\u{3b9}"), + (0x1F86, "\u{1f06}\u{3b9}"), + (0x1F87, "\u{1f07}\u{3b9}"), + (0x1F88, "\u{1f00}\u{3b9}"), + (0x1F89, "\u{1f01}\u{3b9}"), + (0x1F8A, "\u{1f02}\u{3b9}"), + (0x1F8B, "\u{1f03}\u{3b9}"), + (0x1F8C, "\u{1f04}\u{3b9}"), + (0x1F8D, "\u{1f05}\u{3b9}"), + (0x1F8E, "\u{1f06}\u{3b9}"), + (0x1F8F, "\u{1f07}\u{3b9}"), + (0x1F90, "\u{1f20}\u{3b9}"), + (0x1F91, "\u{1f21}\u{3b9}"), + (0x1F92, "\u{1f22}\u{3b9}"), + (0x1F93, "\u{1f23}\u{3b9}"), + (0x1F94, "\u{1f24}\u{3b9}"), + (0x1F95, "\u{1f25}\u{3b9}"), + (0x1F96, "\u{1f26}\u{3b9}"), + (0x1F97, "\u{1f27}\u{3b9}"), + (0x1F98, "\u{1f20}\u{3b9}"), + (0x1F99, "\u{1f21}\u{3b9}"), + (0x1F9A, "\u{1f22}\u{3b9}"), + (0x1F9B, "\u{1f23}\u{3b9}"), + (0x1F9C, "\u{1f24}\u{3b9}"), + (0x1F9D, "\u{1f25}\u{3b9}"), + (0x1F9E, "\u{1f26}\u{3b9}"), + (0x1F9F, "\u{1f27}\u{3b9}"), + (0x1FA0, "\u{1f60}\u{3b9}"), + (0x1FA1, "\u{1f61}\u{3b9}"), + (0x1FA2, "\u{1f62}\u{3b9}"), + (0x1FA3, "\u{1f63}\u{3b9}"), + (0x1FA4, "\u{1f64}\u{3b9}"), + (0x1FA5, "\u{1f65}\u{3b9}"), + (0x1FA6, "\u{1f66}\u{3b9}"), + (0x1FA7, "\u{1f67}\u{3b9}"), + (0x1FA8, "\u{1f60}\u{3b9}"), + (0x1FA9, "\u{1f61}\u{3b9}"), + (0x1FAA, "\u{1f62}\u{3b9}"), + (0x1FAB, "\u{1f63}\u{3b9}"), + (0x1FAC, "\u{1f64}\u{3b9}"), + (0x1FAD, "\u{1f65}\u{3b9}"), + (0x1FAE, "\u{1f66}\u{3b9}"), + (0x1FAF, "\u{1f67}\u{3b9}"), + (0x1FB2, "\u{1f70}\u{3b9}"), + (0x1FB3, "\u{3b1}\u{3b9}"), + (0x1FB4, "\u{3ac}\u{3b9}"), + (0x1FB6, "\u{3b1}\u{342}"), + (0x1FB7, "\u{3b1}\u{342}\u{3b9}"), + (0x1FB8, "\u{1fb0}"), + (0x1FB9, "\u{1fb1}"), + (0x1FBA, "\u{1f70}"), + (0x1FBB, "\u{1f71}"), + (0x1FBC, "\u{3b1}\u{3b9}"), + (0x1FBE, "\u{3b9}"), + (0x1FC2, "\u{1f74}\u{3b9}"), + (0x1FC3, "\u{3b7}\u{3b9}"), + (0x1FC4, "\u{3ae}\u{3b9}"), + (0x1FC6, "\u{3b7}\u{342}"), + (0x1FC7, "\u{3b7}\u{342}\u{3b9}"), + (0x1FC8, "\u{1f72}"), + (0x1FC9, "\u{1f73}"), + (0x1FCA, "\u{1f74}"), + (0x1FCB, "\u{1f75}"), + (0x1FCC, "\u{3b7}\u{3b9}"), + (0x1FD2, "\u{3b9}\u{308}\u{300}"), + (0x1FD3, "\u{3b9}\u{308}\u{301}"), + (0x1FD6, "\u{3b9}\u{342}"), + (0x1FD7, "\u{3b9}\u{308}\u{342}"), + (0x1FD8, "\u{1fd0}"), + (0x1FD9, "\u{1fd1}"), + (0x1FDA, "\u{1f76}"), + (0x1FDB, "\u{1f77}"), + (0x1FE2, "\u{3c5}\u{308}\u{300}"), + (0x1FE3, "\u{3c5}\u{308}\u{301}"), + (0x1FE4, "\u{3c1}\u{313}"), + (0x1FE6, "\u{3c5}\u{342}"), + (0x1FE7, "\u{3c5}\u{308}\u{342}"), + (0x1FE8, "\u{1fe0}"), + (0x1FE9, "\u{1fe1}"), + (0x1FEA, "\u{1f7a}"), + (0x1FEB, "\u{1f7b}"), + (0x1FEC, "\u{1fe5}"), + (0x1FF2, "\u{1f7c}\u{3b9}"), + (0x1FF3, "\u{3c9}\u{3b9}"), + (0x1FF4, "\u{3ce}\u{3b9}"), + (0x1FF6, "\u{3c9}\u{342}"), + (0x1FF7, "\u{3c9}\u{342}\u{3b9}"), + (0x1FF8, "\u{1f78}"), + (0x1FF9, "\u{1f79}"), + (0x1FFA, "\u{1f7c}"), + (0x1FFB, "\u{1f7d}"), + (0x1FFC, "\u{3c9}\u{3b9}"), + (0x2126, "\u{3c9}"), + (0x212A, "\u{6b}"), + (0x212B, "\u{e5}"), + (0x2132, "\u{214e}"), + (0x2160, "\u{2170}"), + (0x2161, "\u{2171}"), + (0x2162, "\u{2172}"), + (0x2163, "\u{2173}"), + (0x2164, "\u{2174}"), + (0x2165, "\u{2175}"), + (0x2166, "\u{2176}"), + (0x2167, "\u{2177}"), + (0x2168, "\u{2178}"), + (0x2169, "\u{2179}"), + (0x216A, "\u{217a}"), + (0x216B, "\u{217b}"), + (0x216C, "\u{217c}"), + (0x216D, "\u{217d}"), + (0x216E, "\u{217e}"), + (0x216F, "\u{217f}"), + (0x2183, "\u{2184}"), + (0x24B6, "\u{24d0}"), + (0x24B7, "\u{24d1}"), + (0x24B8, "\u{24d2}"), + (0x24B9, "\u{24d3}"), + (0x24BA, "\u{24d4}"), + (0x24BB, "\u{24d5}"), + (0x24BC, "\u{24d6}"), + (0x24BD, "\u{24d7}"), + (0x24BE, "\u{24d8}"), + (0x24BF, "\u{24d9}"), + (0x24C0, "\u{24da}"), + (0x24C1, "\u{24db}"), + (0x24C2, "\u{24dc}"), + (0x24C3, "\u{24dd}"), + (0x24C4, "\u{24de}"), + (0x24C5, "\u{24df}"), + (0x24C6, "\u{24e0}"), + (0x24C7, "\u{24e1}"), + (0x24C8, "\u{24e2}"), + (0x24C9, "\u{24e3}"), + (0x24CA, "\u{24e4}"), + (0x24CB, "\u{24e5}"), + (0x24CC, "\u{24e6}"), + (0x24CD, "\u{24e7}"), + (0x24CE, "\u{24e8}"), + (0x24CF, "\u{24e9}"), + (0x2C00, "\u{2c30}"), + (0x2C01, "\u{2c31}"), + (0x2C02, "\u{2c32}"), + (0x2C03, "\u{2c33}"), + (0x2C04, "\u{2c34}"), + (0x2C05, "\u{2c35}"), + (0x2C06, "\u{2c36}"), + (0x2C07, "\u{2c37}"), + (0x2C08, "\u{2c38}"), + (0x2C09, "\u{2c39}"), + (0x2C0A, "\u{2c3a}"), + (0x2C0B, "\u{2c3b}"), + (0x2C0C, "\u{2c3c}"), + (0x2C0D, "\u{2c3d}"), + (0x2C0E, "\u{2c3e}"), + (0x2C0F, "\u{2c3f}"), + (0x2C10, "\u{2c40}"), + (0x2C11, "\u{2c41}"), + (0x2C12, "\u{2c42}"), + (0x2C13, "\u{2c43}"), + (0x2C14, "\u{2c44}"), + (0x2C15, "\u{2c45}"), + (0x2C16, "\u{2c46}"), + (0x2C17, "\u{2c47}"), + (0x2C18, "\u{2c48}"), + (0x2C19, "\u{2c49}"), + (0x2C1A, "\u{2c4a}"), + (0x2C1B, "\u{2c4b}"), + (0x2C1C, "\u{2c4c}"), + (0x2C1D, "\u{2c4d}"), + (0x2C1E, "\u{2c4e}"), + (0x2C1F, "\u{2c4f}"), + (0x2C20, "\u{2c50}"), + (0x2C21, "\u{2c51}"), + (0x2C22, "\u{2c52}"), + (0x2C23, "\u{2c53}"), + (0x2C24, "\u{2c54}"), + (0x2C25, "\u{2c55}"), + (0x2C26, "\u{2c56}"), + (0x2C27, "\u{2c57}"), + (0x2C28, "\u{2c58}"), + (0x2C29, "\u{2c59}"), + (0x2C2A, "\u{2c5a}"), + (0x2C2B, "\u{2c5b}"), + (0x2C2C, "\u{2c5c}"), + (0x2C2D, "\u{2c5d}"), + (0x2C2E, "\u{2c5e}"), + (0x2C2F, "\u{2c5f}"), + (0x2C60, "\u{2c61}"), + (0x2C62, "\u{26b}"), + (0x2C63, "\u{1d7d}"), + (0x2C64, "\u{27d}"), + (0x2C67, "\u{2c68}"), + (0x2C69, "\u{2c6a}"), + (0x2C6B, "\u{2c6c}"), + (0x2C6D, "\u{251}"), + (0x2C6E, "\u{271}"), + (0x2C6F, "\u{250}"), + (0x2C70, "\u{252}"), + (0x2C72, "\u{2c73}"), + (0x2C75, "\u{2c76}"), + (0x2C7E, "\u{23f}"), + (0x2C7F, "\u{240}"), + (0x2C80, "\u{2c81}"), + (0x2C82, "\u{2c83}"), + (0x2C84, "\u{2c85}"), + (0x2C86, "\u{2c87}"), + (0x2C88, "\u{2c89}"), + (0x2C8A, "\u{2c8b}"), + (0x2C8C, "\u{2c8d}"), + (0x2C8E, "\u{2c8f}"), + (0x2C90, "\u{2c91}"), + (0x2C92, "\u{2c93}"), + (0x2C94, "\u{2c95}"), + (0x2C96, "\u{2c97}"), + (0x2C98, "\u{2c99}"), + (0x2C9A, "\u{2c9b}"), + (0x2C9C, "\u{2c9d}"), + (0x2C9E, "\u{2c9f}"), + (0x2CA0, "\u{2ca1}"), + (0x2CA2, "\u{2ca3}"), + (0x2CA4, "\u{2ca5}"), + (0x2CA6, "\u{2ca7}"), + (0x2CA8, "\u{2ca9}"), + (0x2CAA, "\u{2cab}"), + (0x2CAC, "\u{2cad}"), + (0x2CAE, "\u{2caf}"), + (0x2CB0, "\u{2cb1}"), + (0x2CB2, "\u{2cb3}"), + (0x2CB4, "\u{2cb5}"), + (0x2CB6, "\u{2cb7}"), + (0x2CB8, "\u{2cb9}"), + (0x2CBA, "\u{2cbb}"), + (0x2CBC, "\u{2cbd}"), + (0x2CBE, "\u{2cbf}"), + (0x2CC0, "\u{2cc1}"), + (0x2CC2, "\u{2cc3}"), + (0x2CC4, "\u{2cc5}"), + (0x2CC6, "\u{2cc7}"), + (0x2CC8, "\u{2cc9}"), + (0x2CCA, "\u{2ccb}"), + (0x2CCC, "\u{2ccd}"), + (0x2CCE, "\u{2ccf}"), + (0x2CD0, "\u{2cd1}"), + (0x2CD2, "\u{2cd3}"), + (0x2CD4, "\u{2cd5}"), + (0x2CD6, "\u{2cd7}"), + (0x2CD8, "\u{2cd9}"), + (0x2CDA, "\u{2cdb}"), + (0x2CDC, "\u{2cdd}"), + (0x2CDE, "\u{2cdf}"), + (0x2CE0, "\u{2ce1}"), + (0x2CE2, "\u{2ce3}"), + (0x2CEB, "\u{2cec}"), + (0x2CED, "\u{2cee}"), + (0x2CF2, "\u{2cf3}"), + (0xA640, "\u{a641}"), + (0xA642, "\u{a643}"), + (0xA644, "\u{a645}"), + (0xA646, "\u{a647}"), + (0xA648, "\u{a649}"), + (0xA64A, "\u{a64b}"), + (0xA64C, "\u{a64d}"), + (0xA64E, "\u{a64f}"), + (0xA650, "\u{a651}"), + (0xA652, "\u{a653}"), + (0xA654, "\u{a655}"), + (0xA656, "\u{a657}"), + (0xA658, "\u{a659}"), + (0xA65A, "\u{a65b}"), + (0xA65C, "\u{a65d}"), + (0xA65E, "\u{a65f}"), + (0xA660, "\u{a661}"), + (0xA662, "\u{a663}"), + (0xA664, "\u{a665}"), + (0xA666, "\u{a667}"), + (0xA668, "\u{a669}"), + (0xA66A, "\u{a66b}"), + (0xA66C, "\u{a66d}"), + (0xA680, "\u{a681}"), + (0xA682, "\u{a683}"), + (0xA684, "\u{a685}"), + (0xA686, "\u{a687}"), + (0xA688, "\u{a689}"), + (0xA68A, "\u{a68b}"), + (0xA68C, "\u{a68d}"), + (0xA68E, "\u{a68f}"), + (0xA690, "\u{a691}"), + (0xA692, "\u{a693}"), + (0xA694, "\u{a695}"), + (0xA696, "\u{a697}"), + (0xA698, "\u{a699}"), + (0xA69A, "\u{a69b}"), + (0xA722, "\u{a723}"), + (0xA724, "\u{a725}"), + (0xA726, "\u{a727}"), + (0xA728, "\u{a729}"), + (0xA72A, "\u{a72b}"), + (0xA72C, "\u{a72d}"), + (0xA72E, "\u{a72f}"), + (0xA732, "\u{a733}"), + (0xA734, "\u{a735}"), + (0xA736, "\u{a737}"), + (0xA738, "\u{a739}"), + (0xA73A, "\u{a73b}"), + (0xA73C, "\u{a73d}"), + (0xA73E, "\u{a73f}"), + (0xA740, "\u{a741}"), + (0xA742, "\u{a743}"), + (0xA744, "\u{a745}"), + (0xA746, "\u{a747}"), + (0xA748, "\u{a749}"), + (0xA74A, "\u{a74b}"), + (0xA74C, "\u{a74d}"), + (0xA74E, "\u{a74f}"), + (0xA750, "\u{a751}"), + (0xA752, "\u{a753}"), + (0xA754, "\u{a755}"), + (0xA756, "\u{a757}"), + (0xA758, "\u{a759}"), + (0xA75A, "\u{a75b}"), + (0xA75C, "\u{a75d}"), + (0xA75E, "\u{a75f}"), + (0xA760, "\u{a761}"), + (0xA762, "\u{a763}"), + (0xA764, "\u{a765}"), + (0xA766, "\u{a767}"), + (0xA768, "\u{a769}"), + (0xA76A, "\u{a76b}"), + (0xA76C, "\u{a76d}"), + (0xA76E, "\u{a76f}"), + (0xA779, "\u{a77a}"), + (0xA77B, "\u{a77c}"), + (0xA77D, "\u{1d79}"), + (0xA77E, "\u{a77f}"), + (0xA780, "\u{a781}"), + (0xA782, "\u{a783}"), + (0xA784, "\u{a785}"), + (0xA786, "\u{a787}"), + (0xA78B, "\u{a78c}"), + (0xA78D, "\u{265}"), + (0xA790, "\u{a791}"), + (0xA792, "\u{a793}"), + (0xA796, "\u{a797}"), + (0xA798, "\u{a799}"), + (0xA79A, "\u{a79b}"), + (0xA79C, "\u{a79d}"), + (0xA79E, "\u{a79f}"), + (0xA7A0, "\u{a7a1}"), + (0xA7A2, "\u{a7a3}"), + (0xA7A4, "\u{a7a5}"), + (0xA7A6, "\u{a7a7}"), + (0xA7A8, "\u{a7a9}"), + (0xA7AA, "\u{266}"), + (0xA7AB, "\u{25c}"), + (0xA7AC, "\u{261}"), + (0xA7AD, "\u{26c}"), + (0xA7AE, "\u{26a}"), + (0xA7B0, "\u{29e}"), + (0xA7B1, "\u{287}"), + (0xA7B2, "\u{29d}"), + (0xA7B3, "\u{ab53}"), + (0xA7B4, "\u{a7b5}"), + (0xA7B6, "\u{a7b7}"), + (0xA7B8, "\u{a7b9}"), + (0xA7BA, "\u{a7bb}"), + (0xA7BC, "\u{a7bd}"), + (0xA7BE, "\u{a7bf}"), + (0xA7C0, "\u{a7c1}"), + (0xA7C2, "\u{a7c3}"), + (0xA7C4, "\u{a794}"), + (0xA7C5, "\u{282}"), + (0xA7C6, "\u{1d8e}"), + (0xA7C7, "\u{a7c8}"), + (0xA7C9, "\u{a7ca}"), + (0xA7CB, "\u{264}"), + (0xA7CC, "\u{a7cd}"), + (0xA7D0, "\u{a7d1}"), + (0xA7D6, "\u{a7d7}"), + (0xA7D8, "\u{a7d9}"), + (0xA7DA, "\u{a7db}"), + (0xA7DC, "\u{19b}"), + (0xA7F5, "\u{a7f6}"), + (0xAB70, "\u{13a0}"), + (0xAB71, "\u{13a1}"), + (0xAB72, "\u{13a2}"), + (0xAB73, "\u{13a3}"), + (0xAB74, "\u{13a4}"), + (0xAB75, "\u{13a5}"), + (0xAB76, "\u{13a6}"), + (0xAB77, "\u{13a7}"), + (0xAB78, "\u{13a8}"), + (0xAB79, "\u{13a9}"), + (0xAB7A, "\u{13aa}"), + (0xAB7B, "\u{13ab}"), + (0xAB7C, "\u{13ac}"), + (0xAB7D, "\u{13ad}"), + (0xAB7E, "\u{13ae}"), + (0xAB7F, "\u{13af}"), + (0xAB80, "\u{13b0}"), + (0xAB81, "\u{13b1}"), + (0xAB82, "\u{13b2}"), + (0xAB83, "\u{13b3}"), + (0xAB84, "\u{13b4}"), + (0xAB85, "\u{13b5}"), + (0xAB86, "\u{13b6}"), + (0xAB87, "\u{13b7}"), + (0xAB88, "\u{13b8}"), + (0xAB89, "\u{13b9}"), + (0xAB8A, "\u{13ba}"), + (0xAB8B, "\u{13bb}"), + (0xAB8C, "\u{13bc}"), + (0xAB8D, "\u{13bd}"), + (0xAB8E, "\u{13be}"), + (0xAB8F, "\u{13bf}"), + (0xAB90, "\u{13c0}"), + (0xAB91, "\u{13c1}"), + (0xAB92, "\u{13c2}"), + (0xAB93, "\u{13c3}"), + (0xAB94, "\u{13c4}"), + (0xAB95, "\u{13c5}"), + (0xAB96, "\u{13c6}"), + (0xAB97, "\u{13c7}"), + (0xAB98, "\u{13c8}"), + (0xAB99, "\u{13c9}"), + (0xAB9A, "\u{13ca}"), + (0xAB9B, "\u{13cb}"), + (0xAB9C, "\u{13cc}"), + (0xAB9D, "\u{13cd}"), + (0xAB9E, "\u{13ce}"), + (0xAB9F, "\u{13cf}"), + (0xABA0, "\u{13d0}"), + (0xABA1, "\u{13d1}"), + (0xABA2, "\u{13d2}"), + (0xABA3, "\u{13d3}"), + (0xABA4, "\u{13d4}"), + (0xABA5, "\u{13d5}"), + (0xABA6, "\u{13d6}"), + (0xABA7, "\u{13d7}"), + (0xABA8, "\u{13d8}"), + (0xABA9, "\u{13d9}"), + (0xABAA, "\u{13da}"), + (0xABAB, "\u{13db}"), + (0xABAC, "\u{13dc}"), + (0xABAD, "\u{13dd}"), + (0xABAE, "\u{13de}"), + (0xABAF, "\u{13df}"), + (0xABB0, "\u{13e0}"), + (0xABB1, "\u{13e1}"), + (0xABB2, "\u{13e2}"), + (0xABB3, "\u{13e3}"), + (0xABB4, "\u{13e4}"), + (0xABB5, "\u{13e5}"), + (0xABB6, "\u{13e6}"), + (0xABB7, "\u{13e7}"), + (0xABB8, "\u{13e8}"), + (0xABB9, "\u{13e9}"), + (0xABBA, "\u{13ea}"), + (0xABBB, "\u{13eb}"), + (0xABBC, "\u{13ec}"), + (0xABBD, "\u{13ed}"), + (0xABBE, "\u{13ee}"), + (0xABBF, "\u{13ef}"), + (0xFB00, "\u{66}\u{66}"), + (0xFB01, "\u{66}\u{69}"), + (0xFB02, "\u{66}\u{6c}"), + (0xFB03, "\u{66}\u{66}\u{69}"), + (0xFB04, "\u{66}\u{66}\u{6c}"), + (0xFB05, "\u{73}\u{74}"), + (0xFB06, "\u{73}\u{74}"), + (0xFB13, "\u{574}\u{576}"), + (0xFB14, "\u{574}\u{565}"), + (0xFB15, "\u{574}\u{56b}"), + (0xFB16, "\u{57e}\u{576}"), + (0xFB17, "\u{574}\u{56d}"), + (0xFF21, "\u{ff41}"), + (0xFF22, "\u{ff42}"), + (0xFF23, "\u{ff43}"), + (0xFF24, "\u{ff44}"), + (0xFF25, "\u{ff45}"), + (0xFF26, "\u{ff46}"), + (0xFF27, "\u{ff47}"), + (0xFF28, "\u{ff48}"), + (0xFF29, "\u{ff49}"), + (0xFF2A, "\u{ff4a}"), + (0xFF2B, "\u{ff4b}"), + (0xFF2C, "\u{ff4c}"), + (0xFF2D, "\u{ff4d}"), + (0xFF2E, "\u{ff4e}"), + (0xFF2F, "\u{ff4f}"), + (0xFF30, "\u{ff50}"), + (0xFF31, "\u{ff51}"), + (0xFF32, "\u{ff52}"), + (0xFF33, "\u{ff53}"), + (0xFF34, "\u{ff54}"), + (0xFF35, "\u{ff55}"), + (0xFF36, "\u{ff56}"), + (0xFF37, "\u{ff57}"), + (0xFF38, "\u{ff58}"), + (0xFF39, "\u{ff59}"), + (0xFF3A, "\u{ff5a}"), + (0x10400, "\u{10428}"), + (0x10401, "\u{10429}"), + (0x10402, "\u{1042a}"), + (0x10403, "\u{1042b}"), + (0x10404, "\u{1042c}"), + (0x10405, "\u{1042d}"), + (0x10406, "\u{1042e}"), + (0x10407, "\u{1042f}"), + (0x10408, "\u{10430}"), + (0x10409, "\u{10431}"), + (0x1040A, "\u{10432}"), + (0x1040B, "\u{10433}"), + (0x1040C, "\u{10434}"), + (0x1040D, "\u{10435}"), + (0x1040E, "\u{10436}"), + (0x1040F, "\u{10437}"), + (0x10410, "\u{10438}"), + (0x10411, "\u{10439}"), + (0x10412, "\u{1043a}"), + (0x10413, "\u{1043b}"), + (0x10414, "\u{1043c}"), + (0x10415, "\u{1043d}"), + (0x10416, "\u{1043e}"), + (0x10417, "\u{1043f}"), + (0x10418, "\u{10440}"), + (0x10419, "\u{10441}"), + (0x1041A, "\u{10442}"), + (0x1041B, "\u{10443}"), + (0x1041C, "\u{10444}"), + (0x1041D, "\u{10445}"), + (0x1041E, "\u{10446}"), + (0x1041F, "\u{10447}"), + (0x10420, "\u{10448}"), + (0x10421, "\u{10449}"), + (0x10422, "\u{1044a}"), + (0x10423, "\u{1044b}"), + (0x10424, "\u{1044c}"), + (0x10425, "\u{1044d}"), + (0x10426, "\u{1044e}"), + (0x10427, "\u{1044f}"), + (0x104B0, "\u{104d8}"), + (0x104B1, "\u{104d9}"), + (0x104B2, "\u{104da}"), + (0x104B3, "\u{104db}"), + (0x104B4, "\u{104dc}"), + (0x104B5, "\u{104dd}"), + (0x104B6, "\u{104de}"), + (0x104B7, "\u{104df}"), + (0x104B8, "\u{104e0}"), + (0x104B9, "\u{104e1}"), + (0x104BA, "\u{104e2}"), + (0x104BB, "\u{104e3}"), + (0x104BC, "\u{104e4}"), + (0x104BD, "\u{104e5}"), + (0x104BE, "\u{104e6}"), + (0x104BF, "\u{104e7}"), + (0x104C0, "\u{104e8}"), + (0x104C1, "\u{104e9}"), + (0x104C2, "\u{104ea}"), + (0x104C3, "\u{104eb}"), + (0x104C4, "\u{104ec}"), + (0x104C5, "\u{104ed}"), + (0x104C6, "\u{104ee}"), + (0x104C7, "\u{104ef}"), + (0x104C8, "\u{104f0}"), + (0x104C9, "\u{104f1}"), + (0x104CA, "\u{104f2}"), + (0x104CB, "\u{104f3}"), + (0x104CC, "\u{104f4}"), + (0x104CD, "\u{104f5}"), + (0x104CE, "\u{104f6}"), + (0x104CF, "\u{104f7}"), + (0x104D0, "\u{104f8}"), + (0x104D1, "\u{104f9}"), + (0x104D2, "\u{104fa}"), + (0x104D3, "\u{104fb}"), + (0x10570, "\u{10597}"), + (0x10571, "\u{10598}"), + (0x10572, "\u{10599}"), + (0x10573, "\u{1059a}"), + (0x10574, "\u{1059b}"), + (0x10575, "\u{1059c}"), + (0x10576, "\u{1059d}"), + (0x10577, "\u{1059e}"), + (0x10578, "\u{1059f}"), + (0x10579, "\u{105a0}"), + (0x1057A, "\u{105a1}"), + (0x1057C, "\u{105a3}"), + (0x1057D, "\u{105a4}"), + (0x1057E, "\u{105a5}"), + (0x1057F, "\u{105a6}"), + (0x10580, "\u{105a7}"), + (0x10581, "\u{105a8}"), + (0x10582, "\u{105a9}"), + (0x10583, "\u{105aa}"), + (0x10584, "\u{105ab}"), + (0x10585, "\u{105ac}"), + (0x10586, "\u{105ad}"), + (0x10587, "\u{105ae}"), + (0x10588, "\u{105af}"), + (0x10589, "\u{105b0}"), + (0x1058A, "\u{105b1}"), + (0x1058C, "\u{105b3}"), + (0x1058D, "\u{105b4}"), + (0x1058E, "\u{105b5}"), + (0x1058F, "\u{105b6}"), + (0x10590, "\u{105b7}"), + (0x10591, "\u{105b8}"), + (0x10592, "\u{105b9}"), + (0x10594, "\u{105bb}"), + (0x10595, "\u{105bc}"), + (0x10C80, "\u{10cc0}"), + (0x10C81, "\u{10cc1}"), + (0x10C82, "\u{10cc2}"), + (0x10C83, "\u{10cc3}"), + (0x10C84, "\u{10cc4}"), + (0x10C85, "\u{10cc5}"), + (0x10C86, "\u{10cc6}"), + (0x10C87, "\u{10cc7}"), + (0x10C88, "\u{10cc8}"), + (0x10C89, "\u{10cc9}"), + (0x10C8A, "\u{10cca}"), + (0x10C8B, "\u{10ccb}"), + (0x10C8C, "\u{10ccc}"), + (0x10C8D, "\u{10ccd}"), + (0x10C8E, "\u{10cce}"), + (0x10C8F, "\u{10ccf}"), + (0x10C90, "\u{10cd0}"), + (0x10C91, "\u{10cd1}"), + (0x10C92, "\u{10cd2}"), + (0x10C93, "\u{10cd3}"), + (0x10C94, "\u{10cd4}"), + (0x10C95, "\u{10cd5}"), + (0x10C96, "\u{10cd6}"), + (0x10C97, "\u{10cd7}"), + (0x10C98, "\u{10cd8}"), + (0x10C99, "\u{10cd9}"), + (0x10C9A, "\u{10cda}"), + (0x10C9B, "\u{10cdb}"), + (0x10C9C, "\u{10cdc}"), + (0x10C9D, "\u{10cdd}"), + (0x10C9E, "\u{10cde}"), + (0x10C9F, "\u{10cdf}"), + (0x10CA0, "\u{10ce0}"), + (0x10CA1, "\u{10ce1}"), + (0x10CA2, "\u{10ce2}"), + (0x10CA3, "\u{10ce3}"), + (0x10CA4, "\u{10ce4}"), + (0x10CA5, "\u{10ce5}"), + (0x10CA6, "\u{10ce6}"), + (0x10CA7, "\u{10ce7}"), + (0x10CA8, "\u{10ce8}"), + (0x10CA9, "\u{10ce9}"), + (0x10CAA, "\u{10cea}"), + (0x10CAB, "\u{10ceb}"), + (0x10CAC, "\u{10cec}"), + (0x10CAD, "\u{10ced}"), + (0x10CAE, "\u{10cee}"), + (0x10CAF, "\u{10cef}"), + (0x10CB0, "\u{10cf0}"), + (0x10CB1, "\u{10cf1}"), + (0x10CB2, "\u{10cf2}"), + (0x10D50, "\u{10d70}"), + (0x10D51, "\u{10d71}"), + (0x10D52, "\u{10d72}"), + (0x10D53, "\u{10d73}"), + (0x10D54, "\u{10d74}"), + (0x10D55, "\u{10d75}"), + (0x10D56, "\u{10d76}"), + (0x10D57, "\u{10d77}"), + (0x10D58, "\u{10d78}"), + (0x10D59, "\u{10d79}"), + (0x10D5A, "\u{10d7a}"), + (0x10D5B, "\u{10d7b}"), + (0x10D5C, "\u{10d7c}"), + (0x10D5D, "\u{10d7d}"), + (0x10D5E, "\u{10d7e}"), + (0x10D5F, "\u{10d7f}"), + (0x10D60, "\u{10d80}"), + (0x10D61, "\u{10d81}"), + (0x10D62, "\u{10d82}"), + (0x10D63, "\u{10d83}"), + (0x10D64, "\u{10d84}"), + (0x10D65, "\u{10d85}"), + (0x118A0, "\u{118c0}"), + (0x118A1, "\u{118c1}"), + (0x118A2, "\u{118c2}"), + (0x118A3, "\u{118c3}"), + (0x118A4, "\u{118c4}"), + (0x118A5, "\u{118c5}"), + (0x118A6, "\u{118c6}"), + (0x118A7, "\u{118c7}"), + (0x118A8, "\u{118c8}"), + (0x118A9, "\u{118c9}"), + (0x118AA, "\u{118ca}"), + (0x118AB, "\u{118cb}"), + (0x118AC, "\u{118cc}"), + (0x118AD, "\u{118cd}"), + (0x118AE, "\u{118ce}"), + (0x118AF, "\u{118cf}"), + (0x118B0, "\u{118d0}"), + (0x118B1, "\u{118d1}"), + (0x118B2, "\u{118d2}"), + (0x118B3, "\u{118d3}"), + (0x118B4, "\u{118d4}"), + (0x118B5, "\u{118d5}"), + (0x118B6, "\u{118d6}"), + (0x118B7, "\u{118d7}"), + (0x118B8, "\u{118d8}"), + (0x118B9, "\u{118d9}"), + (0x118BA, "\u{118da}"), + (0x118BB, "\u{118db}"), + (0x118BC, "\u{118dc}"), + (0x118BD, "\u{118dd}"), + (0x118BE, "\u{118de}"), + (0x118BF, "\u{118df}"), + (0x16E40, "\u{16e60}"), + (0x16E41, "\u{16e61}"), + (0x16E42, "\u{16e62}"), + (0x16E43, "\u{16e63}"), + (0x16E44, "\u{16e64}"), + (0x16E45, "\u{16e65}"), + (0x16E46, "\u{16e66}"), + (0x16E47, "\u{16e67}"), + (0x16E48, "\u{16e68}"), + (0x16E49, "\u{16e69}"), + (0x16E4A, "\u{16e6a}"), + (0x16E4B, "\u{16e6b}"), + (0x16E4C, "\u{16e6c}"), + (0x16E4D, "\u{16e6d}"), + (0x16E4E, "\u{16e6e}"), + (0x16E4F, "\u{16e6f}"), + (0x16E50, "\u{16e70}"), + (0x16E51, "\u{16e71}"), + (0x16E52, "\u{16e72}"), + (0x16E53, "\u{16e73}"), + (0x16E54, "\u{16e74}"), + (0x16E55, "\u{16e75}"), + (0x16E56, "\u{16e76}"), + (0x16E57, "\u{16e77}"), + (0x16E58, "\u{16e78}"), + (0x16E59, "\u{16e79}"), + (0x16E5A, "\u{16e7a}"), + (0x16E5B, "\u{16e7b}"), + (0x16E5C, "\u{16e7c}"), + (0x16E5D, "\u{16e7d}"), + (0x16E5E, "\u{16e7e}"), + (0x16E5F, "\u{16e7f}"), + (0x1E900, "\u{1e922}"), + (0x1E901, "\u{1e923}"), + (0x1E902, "\u{1e924}"), + (0x1E903, "\u{1e925}"), + (0x1E904, "\u{1e926}"), + (0x1E905, "\u{1e927}"), + (0x1E906, "\u{1e928}"), + (0x1E907, "\u{1e929}"), + (0x1E908, "\u{1e92a}"), + (0x1E909, "\u{1e92b}"), + (0x1E90A, "\u{1e92c}"), + (0x1E90B, "\u{1e92d}"), + (0x1E90C, "\u{1e92e}"), + (0x1E90D, "\u{1e92f}"), + (0x1E90E, "\u{1e930}"), + (0x1E90F, "\u{1e931}"), + (0x1E910, "\u{1e932}"), + (0x1E911, "\u{1e933}"), + (0x1E912, "\u{1e934}"), + (0x1E913, "\u{1e935}"), + (0x1E914, "\u{1e936}"), + (0x1E915, "\u{1e937}"), + (0x1E916, "\u{1e938}"), + (0x1E917, "\u{1e939}"), + (0x1E918, "\u{1e93a}"), + (0x1E919, "\u{1e93b}"), + (0x1E91A, "\u{1e93c}"), + (0x1E91B, "\u{1e93d}"), + (0x1E91C, "\u{1e93e}"), + (0x1E91D, "\u{1e93f}"), + (0x1E91E, "\u{1e940}"), + (0x1E91F, "\u{1e941}"), + (0x1E920, "\u{1e942}"), + (0x1E921, "\u{1e943}"), +] diff --git a/crates/sqlbuild-core/src/text/main/active_python_text.rs b/crates/sqlbuild-core/src/text/main/active_python_text.rs new file mode 100644 index 0000000000..827faa985a --- /dev/null +++ b/crates/sqlbuild-core/src/text/main/active_python_text.rs @@ -0,0 +1,9 @@ +//! The running Python's string semantics, set once by the extension module. + +use crate::text::_helpers::active_text; +use crate::text::models::PythonText; + +/// The running Python's semantics; Rust-only callers that never set them get Python 3.12's. +pub fn active_python_text() -> PythonText { + active_text::active() +} diff --git a/crates/sqlbuild-core/src/text/main/mod.rs b/crates/sqlbuild-core/src/text/main/mod.rs index 2b20809e36..94aabc44f6 100644 --- a/crates/sqlbuild-core/src/text/main/mod.rs +++ b/crates/sqlbuild-core/src/text/main/mod.rs @@ -1,3 +1,4 @@ +pub mod active_python_text; pub mod close_matches; pub mod decode_python_text; pub mod is_python_alnum; @@ -5,6 +6,12 @@ pub mod is_python_alpha; pub mod is_python_decimal; pub mod is_python_space; pub mod is_python_word; +pub mod python_casefold; pub mod python_cleandoc; +pub mod python_decimal_value; +pub mod python_ignorecase_key; +pub mod python_str_repr; pub mod python_strip; pub mod python_text; +pub mod python_upper; +pub mod set_active_python_text; diff --git a/crates/sqlbuild-core/src/text/main/python_casefold.rs b/crates/sqlbuild-core/src/text/main/python_casefold.rs new file mode 100644 index 0000000000..7e014666dc --- /dev/null +++ b/crates/sqlbuild-core/src/text/main/python_casefold.rs @@ -0,0 +1,12 @@ +//! Python's `str.casefold()`, from a table generated by Python. + +use crate::text::_helpers::case_tables::mapped; +use crate::text::models::PythonText; + +/// Python's `text.casefold()`. +pub fn python_casefold(python: PythonText, text: &str) -> String { + if text.is_ascii() { + return text.to_ascii_lowercase(); + } + mapped(python.casefold_mappings, text) +} diff --git a/crates/sqlbuild-core/src/text/main/python_decimal_value.rs b/crates/sqlbuild-core/src/text/main/python_decimal_value.rs new file mode 100644 index 0000000000..fd866a4d92 --- /dev/null +++ b/crates/sqlbuild-core/src/text/main/python_decimal_value.rs @@ -0,0 +1,19 @@ +//! Python's `unicodedata.decimal` for the characters `str.isdecimal()` accepts. + +use crate::text::models::PythonText; + +/// The digit value Python's `int()` reads from one character, if `str.isdecimal()` is true. +pub fn python_decimal_value(python: PythonText, character: char) -> Option { + if character.is_ascii() { + return character.to_digit(10); + } + let code_point: u32 = u32::from(character); + let index: usize = python + .decimal_ranges + .partition_point(|(_, end)| *end < code_point); + let (start, _) = python + .decimal_ranges + .get(index) + .filter(|(start, _)| *start <= code_point)?; + Some((code_point - start) % 10) +} diff --git a/crates/sqlbuild-core/src/text/main/python_ignorecase_key.rs b/crates/sqlbuild-core/src/text/main/python_ignorecase_key.rs new file mode 100644 index 0000000000..9e0540fadb --- /dev/null +++ b/crates/sqlbuild-core/src/text/main/python_ignorecase_key.rs @@ -0,0 +1,18 @@ +//! Python's `re.IGNORECASE` character matching, from a table generated by Python. + +use crate::text::models::PythonText; + +/// The key under which `re.IGNORECASE` matches `character`. +pub fn python_ignorecase_key(python: PythonText, character: char) -> char { + if character.is_ascii() { + return character.to_ascii_lowercase(); + } + let code_point: u32 = u32::from(character); + match python + .ignorecase_keys + .binary_search_by_key(&code_point, |(key, _)| *key) + { + Ok(index) => char::from_u32(python.ignorecase_keys[index].1).unwrap_or(character), + Err(_not_in_table) => character, + } +} diff --git a/crates/sqlbuild-core/src/text/main/python_str_repr.rs b/crates/sqlbuild-core/src/text/main/python_str_repr.rs new file mode 100644 index 0000000000..092f9de9ed --- /dev/null +++ b/crates/sqlbuild-core/src/text/main/python_str_repr.rs @@ -0,0 +1,33 @@ +//! Python's `repr` of a `str`. + +/// Python's `repr` of a string, or `None` when it holds text whose escaping needs Unicode tables. +pub fn python_str_repr(value: &str) -> Option { + if !value.is_ascii() { + return None; + } + let quote: char = if value.contains('\'') && !value.contains('"') { + '"' + } else { + '\'' + }; + let mut text: String = String::with_capacity(value.len() + 2); + text.push(quote); + for character in value.chars() { + match character { + '\\' => text.push_str("\\\\"), + '\t' => text.push_str("\\t"), + '\n' => text.push_str("\\n"), + '\r' => text.push_str("\\r"), + _ if character == quote => { + text.push('\\'); + text.push(character); + } + _ if character < ' ' || character == '\x7f' => { + text.push_str(&format!("\\x{:02x}", u32::from(character))); + } + _ => text.push(character), + } + } + text.push(quote); + Some(text) +} diff --git a/crates/sqlbuild-core/src/text/main/python_text.rs b/crates/sqlbuild-core/src/text/main/python_text.rs index f8d2bcfcdf..2850a6d757 100644 --- a/crates/sqlbuild-core/src/text/main/python_text.rs +++ b/crates/sqlbuild-core/src/text/main/python_text.rs @@ -1,6 +1,7 @@ //! Select the Python string semantics of one CPython release. use crate::text::_helpers::alnum_tables::{ALNUM_TABLES, ALPHA_TABLES, DECIMAL_TABLES}; +use crate::text::_helpers::case_tables::{CASEFOLD_TABLES, IGNORECASE_KEY_TABLES, UPPER_TABLES}; use crate::text::models::{CleandocMargin, PythonText}; /// The semantics of one Python and its `unicodedata.unidata_version`, or `None` if unknown. @@ -22,8 +23,23 @@ pub fn python_text(python_version: (u8, u8), unicode_version: &str) -> Option String { + if text.is_ascii() { + return text.to_ascii_uppercase(); + } + mapped(python.upper_mappings, text) +} diff --git a/crates/sqlbuild-core/src/text/main/set_active_python_text.rs b/crates/sqlbuild-core/src/text/main/set_active_python_text.rs new file mode 100644 index 0000000000..efc48dce16 --- /dev/null +++ b/crates/sqlbuild-core/src/text/main/set_active_python_text.rs @@ -0,0 +1,9 @@ +//! Record the running Python's string semantics for native text helpers. + +use crate::text::_helpers::active_text; +use crate::text::models::PythonText; + +/// Record the running Python's semantics; later calls keep the first value. +pub fn set_active_python_text(python: PythonText) { + active_text::record(python); +} diff --git a/crates/sqlbuild-core/src/text/models.rs b/crates/sqlbuild-core/src/text/models.rs index 037d0c7657..1ed8cc3fa1 100644 --- a/crates/sqlbuild-core/src/text/models.rs +++ b/crates/sqlbuild-core/src/text/models.rs @@ -109,6 +109,12 @@ pub struct PythonText { pub(crate) alpha_ranges: &'static [(u32, u32)], /// Inclusive code point ranges where `str.isdecimal()` (regex `\d`) is true, in order. pub(crate) decimal_ranges: &'static [(u32, u32)], + /// Every character `str.casefold()` changes, with its folding, in code point order. + pub(crate) casefold_mappings: &'static [(u32, &'static str)], + /// Every character `str.upper()` changes, with its upper case, in code point order. + pub(crate) upper_mappings: &'static [(u32, &'static str)], + /// Every character whose `re.IGNORECASE` match key is not itself, with its key, in order. + pub(crate) ignorecase_keys: &'static [(u32, u32)], pub(crate) cleandoc_margin: CleandocMargin, /// The CPython minor version, for library behaviour that changed between 3.x releases. pub(crate) minor_version: u8, @@ -119,6 +125,16 @@ impl PythonText { pub fn minor_version(&self) -> u8 { self.minor_version } + + /// Inclusive code point ranges where `str.isalnum()` is true, in order. + pub fn alnum_ranges(&self) -> &'static [(u32, u32)] { + self.alnum_ranges + } + + /// Inclusive code point ranges where `str.isdecimal()` (regex `\d`) is true, in order. + pub fn decimal_ranges(&self) -> &'static [(u32, u32)] { + self.decimal_ranges + } } /// The characters `inspect.cleandoc` strips from line starts. diff --git a/crates/sqlbuild-core/src/text/re_ignorecase_keys/unicode_15_0_0.in b/crates/sqlbuild-core/src/text/re_ignorecase_keys/unicode_15_0_0.in new file mode 100644 index 0000000000..83b9fb76d1 --- /dev/null +++ b/crates/sqlbuild-core/src/text/re_ignorecase_keys/unicode_15_0_0.in @@ -0,0 +1,1463 @@ +// Generated by `scripts/generate_python_char_table.py`; do not edit. +// Every character whose `re.IGNORECASE` match key is not itself in Unicode 15.0.0, in code point order. +&[ + (0x0041, 0x0061), + (0x0042, 0x0062), + (0x0043, 0x0063), + (0x0044, 0x0064), + (0x0045, 0x0065), + (0x0046, 0x0066), + (0x0047, 0x0067), + (0x0048, 0x0068), + (0x0049, 0x0069), + (0x004A, 0x006A), + (0x004B, 0x006B), + (0x004C, 0x006C), + (0x004D, 0x006D), + (0x004E, 0x006E), + (0x004F, 0x006F), + (0x0050, 0x0070), + (0x0051, 0x0071), + (0x0052, 0x0072), + (0x0053, 0x0073), + (0x0054, 0x0074), + (0x0055, 0x0075), + (0x0056, 0x0076), + (0x0057, 0x0077), + (0x0058, 0x0078), + (0x0059, 0x0079), + (0x005A, 0x007A), + (0x00C0, 0x00E0), + (0x00C1, 0x00E1), + (0x00C2, 0x00E2), + (0x00C3, 0x00E3), + (0x00C4, 0x00E4), + (0x00C5, 0x00E5), + (0x00C6, 0x00E6), + (0x00C7, 0x00E7), + (0x00C8, 0x00E8), + (0x00C9, 0x00E9), + (0x00CA, 0x00EA), + (0x00CB, 0x00EB), + (0x00CC, 0x00EC), + (0x00CD, 0x00ED), + (0x00CE, 0x00EE), + (0x00CF, 0x00EF), + (0x00D0, 0x00F0), + (0x00D1, 0x00F1), + (0x00D2, 0x00F2), + (0x00D3, 0x00F3), + (0x00D4, 0x00F4), + (0x00D5, 0x00F5), + (0x00D6, 0x00F6), + (0x00D8, 0x00F8), + (0x00D9, 0x00F9), + (0x00DA, 0x00FA), + (0x00DB, 0x00FB), + (0x00DC, 0x00FC), + (0x00DD, 0x00FD), + (0x00DE, 0x00FE), + (0x0100, 0x0101), + (0x0102, 0x0103), + (0x0104, 0x0105), + (0x0106, 0x0107), + (0x0108, 0x0109), + (0x010A, 0x010B), + (0x010C, 0x010D), + (0x010E, 0x010F), + (0x0110, 0x0111), + (0x0112, 0x0113), + (0x0114, 0x0115), + (0x0116, 0x0117), + (0x0118, 0x0119), + (0x011A, 0x011B), + (0x011C, 0x011D), + (0x011E, 0x011F), + (0x0120, 0x0121), + (0x0122, 0x0123), + (0x0124, 0x0125), + (0x0126, 0x0127), + (0x0128, 0x0129), + (0x012A, 0x012B), + (0x012C, 0x012D), + (0x012E, 0x012F), + (0x0130, 0x0069), + (0x0131, 0x0069), + (0x0132, 0x0133), + (0x0134, 0x0135), + (0x0136, 0x0137), + (0x0139, 0x013A), + (0x013B, 0x013C), + (0x013D, 0x013E), + (0x013F, 0x0140), + (0x0141, 0x0142), + (0x0143, 0x0144), + (0x0145, 0x0146), + (0x0147, 0x0148), + (0x014A, 0x014B), + (0x014C, 0x014D), + (0x014E, 0x014F), + (0x0150, 0x0151), + (0x0152, 0x0153), + (0x0154, 0x0155), + (0x0156, 0x0157), + (0x0158, 0x0159), + (0x015A, 0x015B), + (0x015C, 0x015D), + (0x015E, 0x015F), + (0x0160, 0x0161), + (0x0162, 0x0163), + (0x0164, 0x0165), + (0x0166, 0x0167), + (0x0168, 0x0169), + (0x016A, 0x016B), + (0x016C, 0x016D), + (0x016E, 0x016F), + (0x0170, 0x0171), + (0x0172, 0x0173), + (0x0174, 0x0175), + (0x0176, 0x0177), + (0x0178, 0x00FF), + (0x0179, 0x017A), + (0x017B, 0x017C), + (0x017D, 0x017E), + (0x017F, 0x0073), + (0x0181, 0x0253), + (0x0182, 0x0183), + (0x0184, 0x0185), + (0x0186, 0x0254), + (0x0187, 0x0188), + (0x0189, 0x0256), + (0x018A, 0x0257), + (0x018B, 0x018C), + (0x018E, 0x01DD), + (0x018F, 0x0259), + (0x0190, 0x025B), + (0x0191, 0x0192), + (0x0193, 0x0260), + (0x0194, 0x0263), + (0x0196, 0x0269), + (0x0197, 0x0268), + (0x0198, 0x0199), + (0x019C, 0x026F), + (0x019D, 0x0272), + (0x019F, 0x0275), + (0x01A0, 0x01A1), + (0x01A2, 0x01A3), + (0x01A4, 0x01A5), + (0x01A6, 0x0280), + (0x01A7, 0x01A8), + (0x01A9, 0x0283), + (0x01AC, 0x01AD), + (0x01AE, 0x0288), + (0x01AF, 0x01B0), + (0x01B1, 0x028A), + (0x01B2, 0x028B), + (0x01B3, 0x01B4), + (0x01B5, 0x01B6), + (0x01B7, 0x0292), + (0x01B8, 0x01B9), + (0x01BC, 0x01BD), + (0x01C4, 0x01C6), + (0x01C5, 0x01C6), + (0x01C7, 0x01C9), + (0x01C8, 0x01C9), + (0x01CA, 0x01CC), + (0x01CB, 0x01CC), + (0x01CD, 0x01CE), + (0x01CF, 0x01D0), + (0x01D1, 0x01D2), + (0x01D3, 0x01D4), + (0x01D5, 0x01D6), + (0x01D7, 0x01D8), + (0x01D9, 0x01DA), + (0x01DB, 0x01DC), + (0x01DE, 0x01DF), + (0x01E0, 0x01E1), + (0x01E2, 0x01E3), + (0x01E4, 0x01E5), + (0x01E6, 0x01E7), + (0x01E8, 0x01E9), + (0x01EA, 0x01EB), + (0x01EC, 0x01ED), + (0x01EE, 0x01EF), + (0x01F1, 0x01F3), + (0x01F2, 0x01F3), + (0x01F4, 0x01F5), + (0x01F6, 0x0195), + (0x01F7, 0x01BF), + (0x01F8, 0x01F9), + (0x01FA, 0x01FB), + (0x01FC, 0x01FD), + (0x01FE, 0x01FF), + (0x0200, 0x0201), + (0x0202, 0x0203), + (0x0204, 0x0205), + (0x0206, 0x0207), + (0x0208, 0x0209), + (0x020A, 0x020B), + (0x020C, 0x020D), + (0x020E, 0x020F), + (0x0210, 0x0211), + (0x0212, 0x0213), + (0x0214, 0x0215), + (0x0216, 0x0217), + (0x0218, 0x0219), + (0x021A, 0x021B), + (0x021C, 0x021D), + (0x021E, 0x021F), + (0x0220, 0x019E), + (0x0222, 0x0223), + (0x0224, 0x0225), + (0x0226, 0x0227), + (0x0228, 0x0229), + (0x022A, 0x022B), + (0x022C, 0x022D), + (0x022E, 0x022F), + (0x0230, 0x0231), + (0x0232, 0x0233), + (0x023A, 0x2C65), + (0x023B, 0x023C), + (0x023D, 0x019A), + (0x023E, 0x2C66), + (0x0241, 0x0242), + (0x0243, 0x0180), + (0x0244, 0x0289), + (0x0245, 0x028C), + (0x0246, 0x0247), + (0x0248, 0x0249), + (0x024A, 0x024B), + (0x024C, 0x024D), + (0x024E, 0x024F), + (0x0370, 0x0371), + (0x0372, 0x0373), + (0x0376, 0x0377), + (0x037F, 0x03F3), + (0x0386, 0x03AC), + (0x0388, 0x03AD), + (0x0389, 0x03AE), + (0x038A, 0x03AF), + (0x038C, 0x03CC), + (0x038E, 0x03CD), + (0x038F, 0x03CE), + (0x0391, 0x03B1), + (0x0392, 0x03B2), + (0x0393, 0x03B3), + (0x0394, 0x03B4), + (0x0395, 0x03B5), + (0x0396, 0x03B6), + (0x0397, 0x03B7), + (0x0398, 0x03B8), + (0x0399, 0x0345), + (0x039A, 0x03BA), + (0x039B, 0x03BB), + (0x039C, 0x00B5), + (0x039D, 0x03BD), + (0x039E, 0x03BE), + (0x039F, 0x03BF), + (0x03A0, 0x03C0), + (0x03A1, 0x03C1), + (0x03A3, 0x03C2), + (0x03A4, 0x03C4), + (0x03A5, 0x03C5), + (0x03A6, 0x03C6), + (0x03A7, 0x03C7), + (0x03A8, 0x03C8), + (0x03A9, 0x03C9), + (0x03AA, 0x03CA), + (0x03AB, 0x03CB), + (0x03B9, 0x0345), + (0x03BC, 0x00B5), + (0x03C3, 0x03C2), + (0x03CF, 0x03D7), + (0x03D0, 0x03B2), + (0x03D1, 0x03B8), + (0x03D5, 0x03C6), + (0x03D6, 0x03C0), + (0x03D8, 0x03D9), + (0x03DA, 0x03DB), + (0x03DC, 0x03DD), + (0x03DE, 0x03DF), + (0x03E0, 0x03E1), + (0x03E2, 0x03E3), + (0x03E4, 0x03E5), + (0x03E6, 0x03E7), + (0x03E8, 0x03E9), + (0x03EA, 0x03EB), + (0x03EC, 0x03ED), + (0x03EE, 0x03EF), + (0x03F0, 0x03BA), + (0x03F1, 0x03C1), + (0x03F4, 0x03B8), + (0x03F5, 0x03B5), + (0x03F7, 0x03F8), + (0x03F9, 0x03F2), + (0x03FA, 0x03FB), + (0x03FD, 0x037B), + (0x03FE, 0x037C), + (0x03FF, 0x037D), + (0x0400, 0x0450), + (0x0401, 0x0451), + (0x0402, 0x0452), + (0x0403, 0x0453), + (0x0404, 0x0454), + (0x0405, 0x0455), + (0x0406, 0x0456), + (0x0407, 0x0457), + (0x0408, 0x0458), + (0x0409, 0x0459), + (0x040A, 0x045A), + (0x040B, 0x045B), + (0x040C, 0x045C), + (0x040D, 0x045D), + (0x040E, 0x045E), + (0x040F, 0x045F), + (0x0410, 0x0430), + (0x0411, 0x0431), + (0x0412, 0x0432), + (0x0413, 0x0433), + (0x0414, 0x0434), + (0x0415, 0x0435), + (0x0416, 0x0436), + (0x0417, 0x0437), + (0x0418, 0x0438), + (0x0419, 0x0439), + (0x041A, 0x043A), + (0x041B, 0x043B), + (0x041C, 0x043C), + (0x041D, 0x043D), + (0x041E, 0x043E), + (0x041F, 0x043F), + (0x0420, 0x0440), + (0x0421, 0x0441), + (0x0422, 0x0442), + (0x0423, 0x0443), + (0x0424, 0x0444), + (0x0425, 0x0445), + (0x0426, 0x0446), + (0x0427, 0x0447), + (0x0428, 0x0448), + (0x0429, 0x0449), + (0x042A, 0x044A), + (0x042B, 0x044B), + (0x042C, 0x044C), + (0x042D, 0x044D), + (0x042E, 0x044E), + (0x042F, 0x044F), + (0x0460, 0x0461), + (0x0462, 0x0463), + (0x0464, 0x0465), + (0x0466, 0x0467), + (0x0468, 0x0469), + (0x046A, 0x046B), + (0x046C, 0x046D), + (0x046E, 0x046F), + (0x0470, 0x0471), + (0x0472, 0x0473), + (0x0474, 0x0475), + (0x0476, 0x0477), + (0x0478, 0x0479), + (0x047A, 0x047B), + (0x047C, 0x047D), + (0x047E, 0x047F), + (0x0480, 0x0481), + (0x048A, 0x048B), + (0x048C, 0x048D), + (0x048E, 0x048F), + (0x0490, 0x0491), + (0x0492, 0x0493), + (0x0494, 0x0495), + (0x0496, 0x0497), + (0x0498, 0x0499), + (0x049A, 0x049B), + (0x049C, 0x049D), + (0x049E, 0x049F), + (0x04A0, 0x04A1), + (0x04A2, 0x04A3), + (0x04A4, 0x04A5), + (0x04A6, 0x04A7), + (0x04A8, 0x04A9), + (0x04AA, 0x04AB), + (0x04AC, 0x04AD), + (0x04AE, 0x04AF), + (0x04B0, 0x04B1), + (0x04B2, 0x04B3), + (0x04B4, 0x04B5), + (0x04B6, 0x04B7), + (0x04B8, 0x04B9), + (0x04BA, 0x04BB), + (0x04BC, 0x04BD), + (0x04BE, 0x04BF), + (0x04C0, 0x04CF), + (0x04C1, 0x04C2), + (0x04C3, 0x04C4), + (0x04C5, 0x04C6), + (0x04C7, 0x04C8), + (0x04C9, 0x04CA), + (0x04CB, 0x04CC), + (0x04CD, 0x04CE), + (0x04D0, 0x04D1), + (0x04D2, 0x04D3), + (0x04D4, 0x04D5), + (0x04D6, 0x04D7), + (0x04D8, 0x04D9), + (0x04DA, 0x04DB), + (0x04DC, 0x04DD), + (0x04DE, 0x04DF), + (0x04E0, 0x04E1), + (0x04E2, 0x04E3), + (0x04E4, 0x04E5), + (0x04E6, 0x04E7), + (0x04E8, 0x04E9), + (0x04EA, 0x04EB), + (0x04EC, 0x04ED), + (0x04EE, 0x04EF), + (0x04F0, 0x04F1), + (0x04F2, 0x04F3), + (0x04F4, 0x04F5), + (0x04F6, 0x04F7), + (0x04F8, 0x04F9), + (0x04FA, 0x04FB), + (0x04FC, 0x04FD), + (0x04FE, 0x04FF), + (0x0500, 0x0501), + (0x0502, 0x0503), + (0x0504, 0x0505), + (0x0506, 0x0507), + (0x0508, 0x0509), + (0x050A, 0x050B), + (0x050C, 0x050D), + (0x050E, 0x050F), + (0x0510, 0x0511), + (0x0512, 0x0513), + (0x0514, 0x0515), + (0x0516, 0x0517), + (0x0518, 0x0519), + (0x051A, 0x051B), + (0x051C, 0x051D), + (0x051E, 0x051F), + (0x0520, 0x0521), + (0x0522, 0x0523), + (0x0524, 0x0525), + (0x0526, 0x0527), + (0x0528, 0x0529), + (0x052A, 0x052B), + (0x052C, 0x052D), + (0x052E, 0x052F), + (0x0531, 0x0561), + (0x0532, 0x0562), + (0x0533, 0x0563), + (0x0534, 0x0564), + (0x0535, 0x0565), + (0x0536, 0x0566), + (0x0537, 0x0567), + (0x0538, 0x0568), + (0x0539, 0x0569), + (0x053A, 0x056A), + (0x053B, 0x056B), + (0x053C, 0x056C), + (0x053D, 0x056D), + (0x053E, 0x056E), + (0x053F, 0x056F), + (0x0540, 0x0570), + (0x0541, 0x0571), + (0x0542, 0x0572), + (0x0543, 0x0573), + (0x0544, 0x0574), + (0x0545, 0x0575), + (0x0546, 0x0576), + (0x0547, 0x0577), + (0x0548, 0x0578), + (0x0549, 0x0579), + (0x054A, 0x057A), + (0x054B, 0x057B), + (0x054C, 0x057C), + (0x054D, 0x057D), + (0x054E, 0x057E), + (0x054F, 0x057F), + (0x0550, 0x0580), + (0x0551, 0x0581), + (0x0552, 0x0582), + (0x0553, 0x0583), + (0x0554, 0x0584), + (0x0555, 0x0585), + (0x0556, 0x0586), + (0x10A0, 0x2D00), + (0x10A1, 0x2D01), + (0x10A2, 0x2D02), + (0x10A3, 0x2D03), + (0x10A4, 0x2D04), + (0x10A5, 0x2D05), + (0x10A6, 0x2D06), + (0x10A7, 0x2D07), + (0x10A8, 0x2D08), + (0x10A9, 0x2D09), + (0x10AA, 0x2D0A), + (0x10AB, 0x2D0B), + (0x10AC, 0x2D0C), + (0x10AD, 0x2D0D), + (0x10AE, 0x2D0E), + (0x10AF, 0x2D0F), + (0x10B0, 0x2D10), + (0x10B1, 0x2D11), + (0x10B2, 0x2D12), + (0x10B3, 0x2D13), + (0x10B4, 0x2D14), + (0x10B5, 0x2D15), + (0x10B6, 0x2D16), + (0x10B7, 0x2D17), + (0x10B8, 0x2D18), + (0x10B9, 0x2D19), + (0x10BA, 0x2D1A), + (0x10BB, 0x2D1B), + (0x10BC, 0x2D1C), + (0x10BD, 0x2D1D), + (0x10BE, 0x2D1E), + (0x10BF, 0x2D1F), + (0x10C0, 0x2D20), + (0x10C1, 0x2D21), + (0x10C2, 0x2D22), + (0x10C3, 0x2D23), + (0x10C4, 0x2D24), + (0x10C5, 0x2D25), + (0x10C7, 0x2D27), + (0x10CD, 0x2D2D), + (0x13A0, 0xAB70), + (0x13A1, 0xAB71), + (0x13A2, 0xAB72), + (0x13A3, 0xAB73), + (0x13A4, 0xAB74), + (0x13A5, 0xAB75), + (0x13A6, 0xAB76), + (0x13A7, 0xAB77), + (0x13A8, 0xAB78), + (0x13A9, 0xAB79), + (0x13AA, 0xAB7A), + (0x13AB, 0xAB7B), + (0x13AC, 0xAB7C), + (0x13AD, 0xAB7D), + (0x13AE, 0xAB7E), + (0x13AF, 0xAB7F), + (0x13B0, 0xAB80), + (0x13B1, 0xAB81), + (0x13B2, 0xAB82), + (0x13B3, 0xAB83), + (0x13B4, 0xAB84), + (0x13B5, 0xAB85), + (0x13B6, 0xAB86), + (0x13B7, 0xAB87), + (0x13B8, 0xAB88), + (0x13B9, 0xAB89), + (0x13BA, 0xAB8A), + (0x13BB, 0xAB8B), + (0x13BC, 0xAB8C), + (0x13BD, 0xAB8D), + (0x13BE, 0xAB8E), + (0x13BF, 0xAB8F), + (0x13C0, 0xAB90), + (0x13C1, 0xAB91), + (0x13C2, 0xAB92), + (0x13C3, 0xAB93), + (0x13C4, 0xAB94), + (0x13C5, 0xAB95), + (0x13C6, 0xAB96), + (0x13C7, 0xAB97), + (0x13C8, 0xAB98), + (0x13C9, 0xAB99), + (0x13CA, 0xAB9A), + (0x13CB, 0xAB9B), + (0x13CC, 0xAB9C), + (0x13CD, 0xAB9D), + (0x13CE, 0xAB9E), + (0x13CF, 0xAB9F), + (0x13D0, 0xABA0), + (0x13D1, 0xABA1), + (0x13D2, 0xABA2), + (0x13D3, 0xABA3), + (0x13D4, 0xABA4), + (0x13D5, 0xABA5), + (0x13D6, 0xABA6), + (0x13D7, 0xABA7), + (0x13D8, 0xABA8), + (0x13D9, 0xABA9), + (0x13DA, 0xABAA), + (0x13DB, 0xABAB), + (0x13DC, 0xABAC), + (0x13DD, 0xABAD), + (0x13DE, 0xABAE), + (0x13DF, 0xABAF), + (0x13E0, 0xABB0), + (0x13E1, 0xABB1), + (0x13E2, 0xABB2), + (0x13E3, 0xABB3), + (0x13E4, 0xABB4), + (0x13E5, 0xABB5), + (0x13E6, 0xABB6), + (0x13E7, 0xABB7), + (0x13E8, 0xABB8), + (0x13E9, 0xABB9), + (0x13EA, 0xABBA), + (0x13EB, 0xABBB), + (0x13EC, 0xABBC), + (0x13ED, 0xABBD), + (0x13EE, 0xABBE), + (0x13EF, 0xABBF), + (0x13F0, 0x13F8), + (0x13F1, 0x13F9), + (0x13F2, 0x13FA), + (0x13F3, 0x13FB), + (0x13F4, 0x13FC), + (0x13F5, 0x13FD), + (0x1C80, 0x0432), + (0x1C81, 0x0434), + (0x1C82, 0x043E), + (0x1C83, 0x0441), + (0x1C84, 0x0442), + (0x1C85, 0x0442), + (0x1C86, 0x044A), + (0x1C87, 0x0463), + (0x1C90, 0x10D0), + (0x1C91, 0x10D1), + (0x1C92, 0x10D2), + (0x1C93, 0x10D3), + (0x1C94, 0x10D4), + (0x1C95, 0x10D5), + (0x1C96, 0x10D6), + (0x1C97, 0x10D7), + (0x1C98, 0x10D8), + (0x1C99, 0x10D9), + (0x1C9A, 0x10DA), + (0x1C9B, 0x10DB), + (0x1C9C, 0x10DC), + (0x1C9D, 0x10DD), + (0x1C9E, 0x10DE), + (0x1C9F, 0x10DF), + (0x1CA0, 0x10E0), + (0x1CA1, 0x10E1), + (0x1CA2, 0x10E2), + (0x1CA3, 0x10E3), + (0x1CA4, 0x10E4), + (0x1CA5, 0x10E5), + (0x1CA6, 0x10E6), + (0x1CA7, 0x10E7), + (0x1CA8, 0x10E8), + (0x1CA9, 0x10E9), + (0x1CAA, 0x10EA), + (0x1CAB, 0x10EB), + (0x1CAC, 0x10EC), + (0x1CAD, 0x10ED), + (0x1CAE, 0x10EE), + (0x1CAF, 0x10EF), + (0x1CB0, 0x10F0), + (0x1CB1, 0x10F1), + (0x1CB2, 0x10F2), + (0x1CB3, 0x10F3), + (0x1CB4, 0x10F4), + (0x1CB5, 0x10F5), + (0x1CB6, 0x10F6), + (0x1CB7, 0x10F7), + (0x1CB8, 0x10F8), + (0x1CB9, 0x10F9), + (0x1CBA, 0x10FA), + (0x1CBD, 0x10FD), + (0x1CBE, 0x10FE), + (0x1CBF, 0x10FF), + (0x1E00, 0x1E01), + (0x1E02, 0x1E03), + (0x1E04, 0x1E05), + (0x1E06, 0x1E07), + (0x1E08, 0x1E09), + (0x1E0A, 0x1E0B), + (0x1E0C, 0x1E0D), + (0x1E0E, 0x1E0F), + (0x1E10, 0x1E11), + (0x1E12, 0x1E13), + (0x1E14, 0x1E15), + (0x1E16, 0x1E17), + (0x1E18, 0x1E19), + (0x1E1A, 0x1E1B), + (0x1E1C, 0x1E1D), + (0x1E1E, 0x1E1F), + (0x1E20, 0x1E21), + (0x1E22, 0x1E23), + (0x1E24, 0x1E25), + (0x1E26, 0x1E27), + (0x1E28, 0x1E29), + (0x1E2A, 0x1E2B), + (0x1E2C, 0x1E2D), + (0x1E2E, 0x1E2F), + (0x1E30, 0x1E31), + (0x1E32, 0x1E33), + (0x1E34, 0x1E35), + (0x1E36, 0x1E37), + (0x1E38, 0x1E39), + (0x1E3A, 0x1E3B), + (0x1E3C, 0x1E3D), + (0x1E3E, 0x1E3F), + (0x1E40, 0x1E41), + (0x1E42, 0x1E43), + (0x1E44, 0x1E45), + (0x1E46, 0x1E47), + (0x1E48, 0x1E49), + (0x1E4A, 0x1E4B), + (0x1E4C, 0x1E4D), + (0x1E4E, 0x1E4F), + (0x1E50, 0x1E51), + (0x1E52, 0x1E53), + (0x1E54, 0x1E55), + (0x1E56, 0x1E57), + (0x1E58, 0x1E59), + (0x1E5A, 0x1E5B), + (0x1E5C, 0x1E5D), + (0x1E5E, 0x1E5F), + (0x1E60, 0x1E61), + (0x1E62, 0x1E63), + (0x1E64, 0x1E65), + (0x1E66, 0x1E67), + (0x1E68, 0x1E69), + (0x1E6A, 0x1E6B), + (0x1E6C, 0x1E6D), + (0x1E6E, 0x1E6F), + (0x1E70, 0x1E71), + (0x1E72, 0x1E73), + (0x1E74, 0x1E75), + (0x1E76, 0x1E77), + (0x1E78, 0x1E79), + (0x1E7A, 0x1E7B), + (0x1E7C, 0x1E7D), + (0x1E7E, 0x1E7F), + (0x1E80, 0x1E81), + (0x1E82, 0x1E83), + (0x1E84, 0x1E85), + (0x1E86, 0x1E87), + (0x1E88, 0x1E89), + (0x1E8A, 0x1E8B), + (0x1E8C, 0x1E8D), + (0x1E8E, 0x1E8F), + (0x1E90, 0x1E91), + (0x1E92, 0x1E93), + (0x1E94, 0x1E95), + (0x1E9B, 0x1E61), + (0x1E9E, 0x00DF), + (0x1EA0, 0x1EA1), + (0x1EA2, 0x1EA3), + (0x1EA4, 0x1EA5), + (0x1EA6, 0x1EA7), + (0x1EA8, 0x1EA9), + (0x1EAA, 0x1EAB), + (0x1EAC, 0x1EAD), + (0x1EAE, 0x1EAF), + (0x1EB0, 0x1EB1), + (0x1EB2, 0x1EB3), + (0x1EB4, 0x1EB5), + (0x1EB6, 0x1EB7), + (0x1EB8, 0x1EB9), + (0x1EBA, 0x1EBB), + (0x1EBC, 0x1EBD), + (0x1EBE, 0x1EBF), + (0x1EC0, 0x1EC1), + (0x1EC2, 0x1EC3), + (0x1EC4, 0x1EC5), + (0x1EC6, 0x1EC7), + (0x1EC8, 0x1EC9), + (0x1ECA, 0x1ECB), + (0x1ECC, 0x1ECD), + (0x1ECE, 0x1ECF), + (0x1ED0, 0x1ED1), + (0x1ED2, 0x1ED3), + (0x1ED4, 0x1ED5), + (0x1ED6, 0x1ED7), + (0x1ED8, 0x1ED9), + (0x1EDA, 0x1EDB), + (0x1EDC, 0x1EDD), + (0x1EDE, 0x1EDF), + (0x1EE0, 0x1EE1), + (0x1EE2, 0x1EE3), + (0x1EE4, 0x1EE5), + (0x1EE6, 0x1EE7), + (0x1EE8, 0x1EE9), + (0x1EEA, 0x1EEB), + (0x1EEC, 0x1EED), + (0x1EEE, 0x1EEF), + (0x1EF0, 0x1EF1), + (0x1EF2, 0x1EF3), + (0x1EF4, 0x1EF5), + (0x1EF6, 0x1EF7), + (0x1EF8, 0x1EF9), + (0x1EFA, 0x1EFB), + (0x1EFC, 0x1EFD), + (0x1EFE, 0x1EFF), + (0x1F08, 0x1F00), + (0x1F09, 0x1F01), + (0x1F0A, 0x1F02), + (0x1F0B, 0x1F03), + (0x1F0C, 0x1F04), + (0x1F0D, 0x1F05), + (0x1F0E, 0x1F06), + (0x1F0F, 0x1F07), + (0x1F18, 0x1F10), + (0x1F19, 0x1F11), + (0x1F1A, 0x1F12), + (0x1F1B, 0x1F13), + (0x1F1C, 0x1F14), + (0x1F1D, 0x1F15), + (0x1F28, 0x1F20), + (0x1F29, 0x1F21), + (0x1F2A, 0x1F22), + (0x1F2B, 0x1F23), + (0x1F2C, 0x1F24), + (0x1F2D, 0x1F25), + (0x1F2E, 0x1F26), + (0x1F2F, 0x1F27), + (0x1F38, 0x1F30), + (0x1F39, 0x1F31), + (0x1F3A, 0x1F32), + (0x1F3B, 0x1F33), + (0x1F3C, 0x1F34), + (0x1F3D, 0x1F35), + (0x1F3E, 0x1F36), + (0x1F3F, 0x1F37), + (0x1F48, 0x1F40), + (0x1F49, 0x1F41), + (0x1F4A, 0x1F42), + (0x1F4B, 0x1F43), + (0x1F4C, 0x1F44), + (0x1F4D, 0x1F45), + (0x1F59, 0x1F51), + (0x1F5B, 0x1F53), + (0x1F5D, 0x1F55), + (0x1F5F, 0x1F57), + (0x1F68, 0x1F60), + (0x1F69, 0x1F61), + (0x1F6A, 0x1F62), + (0x1F6B, 0x1F63), + (0x1F6C, 0x1F64), + (0x1F6D, 0x1F65), + (0x1F6E, 0x1F66), + (0x1F6F, 0x1F67), + (0x1F88, 0x1F80), + (0x1F89, 0x1F81), + (0x1F8A, 0x1F82), + (0x1F8B, 0x1F83), + (0x1F8C, 0x1F84), + (0x1F8D, 0x1F85), + (0x1F8E, 0x1F86), + (0x1F8F, 0x1F87), + (0x1F98, 0x1F90), + (0x1F99, 0x1F91), + (0x1F9A, 0x1F92), + (0x1F9B, 0x1F93), + (0x1F9C, 0x1F94), + (0x1F9D, 0x1F95), + (0x1F9E, 0x1F96), + (0x1F9F, 0x1F97), + (0x1FA8, 0x1FA0), + (0x1FA9, 0x1FA1), + (0x1FAA, 0x1FA2), + (0x1FAB, 0x1FA3), + (0x1FAC, 0x1FA4), + (0x1FAD, 0x1FA5), + (0x1FAE, 0x1FA6), + (0x1FAF, 0x1FA7), + (0x1FB8, 0x1FB0), + (0x1FB9, 0x1FB1), + (0x1FBA, 0x1F70), + (0x1FBB, 0x1F71), + (0x1FBC, 0x1FB3), + (0x1FBE, 0x0345), + (0x1FC8, 0x1F72), + (0x1FC9, 0x1F73), + (0x1FCA, 0x1F74), + (0x1FCB, 0x1F75), + (0x1FCC, 0x1FC3), + (0x1FD3, 0x0390), + (0x1FD8, 0x1FD0), + (0x1FD9, 0x1FD1), + (0x1FDA, 0x1F76), + (0x1FDB, 0x1F77), + (0x1FE3, 0x03B0), + (0x1FE8, 0x1FE0), + (0x1FE9, 0x1FE1), + (0x1FEA, 0x1F7A), + (0x1FEB, 0x1F7B), + (0x1FEC, 0x1FE5), + (0x1FF8, 0x1F78), + (0x1FF9, 0x1F79), + (0x1FFA, 0x1F7C), + (0x1FFB, 0x1F7D), + (0x1FFC, 0x1FF3), + (0x2126, 0x03C9), + (0x212A, 0x006B), + (0x212B, 0x00E5), + (0x2132, 0x214E), + (0x2160, 0x2170), + (0x2161, 0x2171), + (0x2162, 0x2172), + (0x2163, 0x2173), + (0x2164, 0x2174), + (0x2165, 0x2175), + (0x2166, 0x2176), + (0x2167, 0x2177), + (0x2168, 0x2178), + (0x2169, 0x2179), + (0x216A, 0x217A), + (0x216B, 0x217B), + (0x216C, 0x217C), + (0x216D, 0x217D), + (0x216E, 0x217E), + (0x216F, 0x217F), + (0x2183, 0x2184), + (0x24B6, 0x24D0), + (0x24B7, 0x24D1), + (0x24B8, 0x24D2), + (0x24B9, 0x24D3), + (0x24BA, 0x24D4), + (0x24BB, 0x24D5), + (0x24BC, 0x24D6), + (0x24BD, 0x24D7), + (0x24BE, 0x24D8), + (0x24BF, 0x24D9), + (0x24C0, 0x24DA), + (0x24C1, 0x24DB), + (0x24C2, 0x24DC), + (0x24C3, 0x24DD), + (0x24C4, 0x24DE), + (0x24C5, 0x24DF), + (0x24C6, 0x24E0), + (0x24C7, 0x24E1), + (0x24C8, 0x24E2), + (0x24C9, 0x24E3), + (0x24CA, 0x24E4), + (0x24CB, 0x24E5), + (0x24CC, 0x24E6), + (0x24CD, 0x24E7), + (0x24CE, 0x24E8), + (0x24CF, 0x24E9), + (0x2C00, 0x2C30), + (0x2C01, 0x2C31), + (0x2C02, 0x2C32), + (0x2C03, 0x2C33), + (0x2C04, 0x2C34), + (0x2C05, 0x2C35), + (0x2C06, 0x2C36), + (0x2C07, 0x2C37), + (0x2C08, 0x2C38), + (0x2C09, 0x2C39), + (0x2C0A, 0x2C3A), + (0x2C0B, 0x2C3B), + (0x2C0C, 0x2C3C), + (0x2C0D, 0x2C3D), + (0x2C0E, 0x2C3E), + (0x2C0F, 0x2C3F), + (0x2C10, 0x2C40), + (0x2C11, 0x2C41), + (0x2C12, 0x2C42), + (0x2C13, 0x2C43), + (0x2C14, 0x2C44), + (0x2C15, 0x2C45), + (0x2C16, 0x2C46), + (0x2C17, 0x2C47), + (0x2C18, 0x2C48), + (0x2C19, 0x2C49), + (0x2C1A, 0x2C4A), + (0x2C1B, 0x2C4B), + (0x2C1C, 0x2C4C), + (0x2C1D, 0x2C4D), + (0x2C1E, 0x2C4E), + (0x2C1F, 0x2C4F), + (0x2C20, 0x2C50), + (0x2C21, 0x2C51), + (0x2C22, 0x2C52), + (0x2C23, 0x2C53), + (0x2C24, 0x2C54), + (0x2C25, 0x2C55), + (0x2C26, 0x2C56), + (0x2C27, 0x2C57), + (0x2C28, 0x2C58), + (0x2C29, 0x2C59), + (0x2C2A, 0x2C5A), + (0x2C2B, 0x2C5B), + (0x2C2C, 0x2C5C), + (0x2C2D, 0x2C5D), + (0x2C2E, 0x2C5E), + (0x2C2F, 0x2C5F), + (0x2C60, 0x2C61), + (0x2C62, 0x026B), + (0x2C63, 0x1D7D), + (0x2C64, 0x027D), + (0x2C67, 0x2C68), + (0x2C69, 0x2C6A), + (0x2C6B, 0x2C6C), + (0x2C6D, 0x0251), + (0x2C6E, 0x0271), + (0x2C6F, 0x0250), + (0x2C70, 0x0252), + (0x2C72, 0x2C73), + (0x2C75, 0x2C76), + (0x2C7E, 0x023F), + (0x2C7F, 0x0240), + (0x2C80, 0x2C81), + (0x2C82, 0x2C83), + (0x2C84, 0x2C85), + (0x2C86, 0x2C87), + (0x2C88, 0x2C89), + (0x2C8A, 0x2C8B), + (0x2C8C, 0x2C8D), + (0x2C8E, 0x2C8F), + (0x2C90, 0x2C91), + (0x2C92, 0x2C93), + (0x2C94, 0x2C95), + (0x2C96, 0x2C97), + (0x2C98, 0x2C99), + (0x2C9A, 0x2C9B), + (0x2C9C, 0x2C9D), + (0x2C9E, 0x2C9F), + (0x2CA0, 0x2CA1), + (0x2CA2, 0x2CA3), + (0x2CA4, 0x2CA5), + (0x2CA6, 0x2CA7), + (0x2CA8, 0x2CA9), + (0x2CAA, 0x2CAB), + (0x2CAC, 0x2CAD), + (0x2CAE, 0x2CAF), + (0x2CB0, 0x2CB1), + (0x2CB2, 0x2CB3), + (0x2CB4, 0x2CB5), + (0x2CB6, 0x2CB7), + (0x2CB8, 0x2CB9), + (0x2CBA, 0x2CBB), + (0x2CBC, 0x2CBD), + (0x2CBE, 0x2CBF), + (0x2CC0, 0x2CC1), + (0x2CC2, 0x2CC3), + (0x2CC4, 0x2CC5), + (0x2CC6, 0x2CC7), + (0x2CC8, 0x2CC9), + (0x2CCA, 0x2CCB), + (0x2CCC, 0x2CCD), + (0x2CCE, 0x2CCF), + (0x2CD0, 0x2CD1), + (0x2CD2, 0x2CD3), + (0x2CD4, 0x2CD5), + (0x2CD6, 0x2CD7), + (0x2CD8, 0x2CD9), + (0x2CDA, 0x2CDB), + (0x2CDC, 0x2CDD), + (0x2CDE, 0x2CDF), + (0x2CE0, 0x2CE1), + (0x2CE2, 0x2CE3), + (0x2CEB, 0x2CEC), + (0x2CED, 0x2CEE), + (0x2CF2, 0x2CF3), + (0xA640, 0xA641), + (0xA642, 0xA643), + (0xA644, 0xA645), + (0xA646, 0xA647), + (0xA648, 0xA649), + (0xA64A, 0x1C88), + (0xA64B, 0x1C88), + (0xA64C, 0xA64D), + (0xA64E, 0xA64F), + (0xA650, 0xA651), + (0xA652, 0xA653), + (0xA654, 0xA655), + (0xA656, 0xA657), + (0xA658, 0xA659), + (0xA65A, 0xA65B), + (0xA65C, 0xA65D), + (0xA65E, 0xA65F), + (0xA660, 0xA661), + (0xA662, 0xA663), + (0xA664, 0xA665), + (0xA666, 0xA667), + (0xA668, 0xA669), + (0xA66A, 0xA66B), + (0xA66C, 0xA66D), + (0xA680, 0xA681), + (0xA682, 0xA683), + (0xA684, 0xA685), + (0xA686, 0xA687), + (0xA688, 0xA689), + (0xA68A, 0xA68B), + (0xA68C, 0xA68D), + (0xA68E, 0xA68F), + (0xA690, 0xA691), + (0xA692, 0xA693), + (0xA694, 0xA695), + (0xA696, 0xA697), + (0xA698, 0xA699), + (0xA69A, 0xA69B), + (0xA722, 0xA723), + (0xA724, 0xA725), + (0xA726, 0xA727), + (0xA728, 0xA729), + (0xA72A, 0xA72B), + (0xA72C, 0xA72D), + (0xA72E, 0xA72F), + (0xA732, 0xA733), + (0xA734, 0xA735), + (0xA736, 0xA737), + (0xA738, 0xA739), + (0xA73A, 0xA73B), + (0xA73C, 0xA73D), + (0xA73E, 0xA73F), + (0xA740, 0xA741), + (0xA742, 0xA743), + (0xA744, 0xA745), + (0xA746, 0xA747), + (0xA748, 0xA749), + (0xA74A, 0xA74B), + (0xA74C, 0xA74D), + (0xA74E, 0xA74F), + (0xA750, 0xA751), + (0xA752, 0xA753), + (0xA754, 0xA755), + (0xA756, 0xA757), + (0xA758, 0xA759), + (0xA75A, 0xA75B), + (0xA75C, 0xA75D), + (0xA75E, 0xA75F), + (0xA760, 0xA761), + (0xA762, 0xA763), + (0xA764, 0xA765), + (0xA766, 0xA767), + (0xA768, 0xA769), + (0xA76A, 0xA76B), + (0xA76C, 0xA76D), + (0xA76E, 0xA76F), + (0xA779, 0xA77A), + (0xA77B, 0xA77C), + (0xA77D, 0x1D79), + (0xA77E, 0xA77F), + (0xA780, 0xA781), + (0xA782, 0xA783), + (0xA784, 0xA785), + (0xA786, 0xA787), + (0xA78B, 0xA78C), + (0xA78D, 0x0265), + (0xA790, 0xA791), + (0xA792, 0xA793), + (0xA796, 0xA797), + (0xA798, 0xA799), + (0xA79A, 0xA79B), + (0xA79C, 0xA79D), + (0xA79E, 0xA79F), + (0xA7A0, 0xA7A1), + (0xA7A2, 0xA7A3), + (0xA7A4, 0xA7A5), + (0xA7A6, 0xA7A7), + (0xA7A8, 0xA7A9), + (0xA7AA, 0x0266), + (0xA7AB, 0x025C), + (0xA7AC, 0x0261), + (0xA7AD, 0x026C), + (0xA7AE, 0x026A), + (0xA7B0, 0x029E), + (0xA7B1, 0x0287), + (0xA7B2, 0x029D), + (0xA7B3, 0xAB53), + (0xA7B4, 0xA7B5), + (0xA7B6, 0xA7B7), + (0xA7B8, 0xA7B9), + (0xA7BA, 0xA7BB), + (0xA7BC, 0xA7BD), + (0xA7BE, 0xA7BF), + (0xA7C0, 0xA7C1), + (0xA7C2, 0xA7C3), + (0xA7C4, 0xA794), + (0xA7C5, 0x0282), + (0xA7C6, 0x1D8E), + (0xA7C7, 0xA7C8), + (0xA7C9, 0xA7CA), + (0xA7D0, 0xA7D1), + (0xA7D6, 0xA7D7), + (0xA7D8, 0xA7D9), + (0xA7F5, 0xA7F6), + (0xFB06, 0xFB05), + (0xFF21, 0xFF41), + (0xFF22, 0xFF42), + (0xFF23, 0xFF43), + (0xFF24, 0xFF44), + (0xFF25, 0xFF45), + (0xFF26, 0xFF46), + (0xFF27, 0xFF47), + (0xFF28, 0xFF48), + (0xFF29, 0xFF49), + (0xFF2A, 0xFF4A), + (0xFF2B, 0xFF4B), + (0xFF2C, 0xFF4C), + (0xFF2D, 0xFF4D), + (0xFF2E, 0xFF4E), + (0xFF2F, 0xFF4F), + (0xFF30, 0xFF50), + (0xFF31, 0xFF51), + (0xFF32, 0xFF52), + (0xFF33, 0xFF53), + (0xFF34, 0xFF54), + (0xFF35, 0xFF55), + (0xFF36, 0xFF56), + (0xFF37, 0xFF57), + (0xFF38, 0xFF58), + (0xFF39, 0xFF59), + (0xFF3A, 0xFF5A), + (0x10400, 0x10428), + (0x10401, 0x10429), + (0x10402, 0x1042A), + (0x10403, 0x1042B), + (0x10404, 0x1042C), + (0x10405, 0x1042D), + (0x10406, 0x1042E), + (0x10407, 0x1042F), + (0x10408, 0x10430), + (0x10409, 0x10431), + (0x1040A, 0x10432), + (0x1040B, 0x10433), + (0x1040C, 0x10434), + (0x1040D, 0x10435), + (0x1040E, 0x10436), + (0x1040F, 0x10437), + (0x10410, 0x10438), + (0x10411, 0x10439), + (0x10412, 0x1043A), + (0x10413, 0x1043B), + (0x10414, 0x1043C), + (0x10415, 0x1043D), + (0x10416, 0x1043E), + (0x10417, 0x1043F), + (0x10418, 0x10440), + (0x10419, 0x10441), + (0x1041A, 0x10442), + (0x1041B, 0x10443), + (0x1041C, 0x10444), + (0x1041D, 0x10445), + (0x1041E, 0x10446), + (0x1041F, 0x10447), + (0x10420, 0x10448), + (0x10421, 0x10449), + (0x10422, 0x1044A), + (0x10423, 0x1044B), + (0x10424, 0x1044C), + (0x10425, 0x1044D), + (0x10426, 0x1044E), + (0x10427, 0x1044F), + (0x104B0, 0x104D8), + (0x104B1, 0x104D9), + (0x104B2, 0x104DA), + (0x104B3, 0x104DB), + (0x104B4, 0x104DC), + (0x104B5, 0x104DD), + (0x104B6, 0x104DE), + (0x104B7, 0x104DF), + (0x104B8, 0x104E0), + (0x104B9, 0x104E1), + (0x104BA, 0x104E2), + (0x104BB, 0x104E3), + (0x104BC, 0x104E4), + (0x104BD, 0x104E5), + (0x104BE, 0x104E6), + (0x104BF, 0x104E7), + (0x104C0, 0x104E8), + (0x104C1, 0x104E9), + (0x104C2, 0x104EA), + (0x104C3, 0x104EB), + (0x104C4, 0x104EC), + (0x104C5, 0x104ED), + (0x104C6, 0x104EE), + (0x104C7, 0x104EF), + (0x104C8, 0x104F0), + (0x104C9, 0x104F1), + (0x104CA, 0x104F2), + (0x104CB, 0x104F3), + (0x104CC, 0x104F4), + (0x104CD, 0x104F5), + (0x104CE, 0x104F6), + (0x104CF, 0x104F7), + (0x104D0, 0x104F8), + (0x104D1, 0x104F9), + (0x104D2, 0x104FA), + (0x104D3, 0x104FB), + (0x10570, 0x10597), + (0x10571, 0x10598), + (0x10572, 0x10599), + (0x10573, 0x1059A), + (0x10574, 0x1059B), + (0x10575, 0x1059C), + (0x10576, 0x1059D), + (0x10577, 0x1059E), + (0x10578, 0x1059F), + (0x10579, 0x105A0), + (0x1057A, 0x105A1), + (0x1057C, 0x105A3), + (0x1057D, 0x105A4), + (0x1057E, 0x105A5), + (0x1057F, 0x105A6), + (0x10580, 0x105A7), + (0x10581, 0x105A8), + (0x10582, 0x105A9), + (0x10583, 0x105AA), + (0x10584, 0x105AB), + (0x10585, 0x105AC), + (0x10586, 0x105AD), + (0x10587, 0x105AE), + (0x10588, 0x105AF), + (0x10589, 0x105B0), + (0x1058A, 0x105B1), + (0x1058C, 0x105B3), + (0x1058D, 0x105B4), + (0x1058E, 0x105B5), + (0x1058F, 0x105B6), + (0x10590, 0x105B7), + (0x10591, 0x105B8), + (0x10592, 0x105B9), + (0x10594, 0x105BB), + (0x10595, 0x105BC), + (0x10C80, 0x10CC0), + (0x10C81, 0x10CC1), + (0x10C82, 0x10CC2), + (0x10C83, 0x10CC3), + (0x10C84, 0x10CC4), + (0x10C85, 0x10CC5), + (0x10C86, 0x10CC6), + (0x10C87, 0x10CC7), + (0x10C88, 0x10CC8), + (0x10C89, 0x10CC9), + (0x10C8A, 0x10CCA), + (0x10C8B, 0x10CCB), + (0x10C8C, 0x10CCC), + (0x10C8D, 0x10CCD), + (0x10C8E, 0x10CCE), + (0x10C8F, 0x10CCF), + (0x10C90, 0x10CD0), + (0x10C91, 0x10CD1), + (0x10C92, 0x10CD2), + (0x10C93, 0x10CD3), + (0x10C94, 0x10CD4), + (0x10C95, 0x10CD5), + (0x10C96, 0x10CD6), + (0x10C97, 0x10CD7), + (0x10C98, 0x10CD8), + (0x10C99, 0x10CD9), + (0x10C9A, 0x10CDA), + (0x10C9B, 0x10CDB), + (0x10C9C, 0x10CDC), + (0x10C9D, 0x10CDD), + (0x10C9E, 0x10CDE), + (0x10C9F, 0x10CDF), + (0x10CA0, 0x10CE0), + (0x10CA1, 0x10CE1), + (0x10CA2, 0x10CE2), + (0x10CA3, 0x10CE3), + (0x10CA4, 0x10CE4), + (0x10CA5, 0x10CE5), + (0x10CA6, 0x10CE6), + (0x10CA7, 0x10CE7), + (0x10CA8, 0x10CE8), + (0x10CA9, 0x10CE9), + (0x10CAA, 0x10CEA), + (0x10CAB, 0x10CEB), + (0x10CAC, 0x10CEC), + (0x10CAD, 0x10CED), + (0x10CAE, 0x10CEE), + (0x10CAF, 0x10CEF), + (0x10CB0, 0x10CF0), + (0x10CB1, 0x10CF1), + (0x10CB2, 0x10CF2), + (0x118A0, 0x118C0), + (0x118A1, 0x118C1), + (0x118A2, 0x118C2), + (0x118A3, 0x118C3), + (0x118A4, 0x118C4), + (0x118A5, 0x118C5), + (0x118A6, 0x118C6), + (0x118A7, 0x118C7), + (0x118A8, 0x118C8), + (0x118A9, 0x118C9), + (0x118AA, 0x118CA), + (0x118AB, 0x118CB), + (0x118AC, 0x118CC), + (0x118AD, 0x118CD), + (0x118AE, 0x118CE), + (0x118AF, 0x118CF), + (0x118B0, 0x118D0), + (0x118B1, 0x118D1), + (0x118B2, 0x118D2), + (0x118B3, 0x118D3), + (0x118B4, 0x118D4), + (0x118B5, 0x118D5), + (0x118B6, 0x118D6), + (0x118B7, 0x118D7), + (0x118B8, 0x118D8), + (0x118B9, 0x118D9), + (0x118BA, 0x118DA), + (0x118BB, 0x118DB), + (0x118BC, 0x118DC), + (0x118BD, 0x118DD), + (0x118BE, 0x118DE), + (0x118BF, 0x118DF), + (0x16E40, 0x16E60), + (0x16E41, 0x16E61), + (0x16E42, 0x16E62), + (0x16E43, 0x16E63), + (0x16E44, 0x16E64), + (0x16E45, 0x16E65), + (0x16E46, 0x16E66), + (0x16E47, 0x16E67), + (0x16E48, 0x16E68), + (0x16E49, 0x16E69), + (0x16E4A, 0x16E6A), + (0x16E4B, 0x16E6B), + (0x16E4C, 0x16E6C), + (0x16E4D, 0x16E6D), + (0x16E4E, 0x16E6E), + (0x16E4F, 0x16E6F), + (0x16E50, 0x16E70), + (0x16E51, 0x16E71), + (0x16E52, 0x16E72), + (0x16E53, 0x16E73), + (0x16E54, 0x16E74), + (0x16E55, 0x16E75), + (0x16E56, 0x16E76), + (0x16E57, 0x16E77), + (0x16E58, 0x16E78), + (0x16E59, 0x16E79), + (0x16E5A, 0x16E7A), + (0x16E5B, 0x16E7B), + (0x16E5C, 0x16E7C), + (0x16E5D, 0x16E7D), + (0x16E5E, 0x16E7E), + (0x16E5F, 0x16E7F), + (0x1E900, 0x1E922), + (0x1E901, 0x1E923), + (0x1E902, 0x1E924), + (0x1E903, 0x1E925), + (0x1E904, 0x1E926), + (0x1E905, 0x1E927), + (0x1E906, 0x1E928), + (0x1E907, 0x1E929), + (0x1E908, 0x1E92A), + (0x1E909, 0x1E92B), + (0x1E90A, 0x1E92C), + (0x1E90B, 0x1E92D), + (0x1E90C, 0x1E92E), + (0x1E90D, 0x1E92F), + (0x1E90E, 0x1E930), + (0x1E90F, 0x1E931), + (0x1E910, 0x1E932), + (0x1E911, 0x1E933), + (0x1E912, 0x1E934), + (0x1E913, 0x1E935), + (0x1E914, 0x1E936), + (0x1E915, 0x1E937), + (0x1E916, 0x1E938), + (0x1E917, 0x1E939), + (0x1E918, 0x1E93A), + (0x1E919, 0x1E93B), + (0x1E91A, 0x1E93C), + (0x1E91B, 0x1E93D), + (0x1E91C, 0x1E93E), + (0x1E91D, 0x1E93F), + (0x1E91E, 0x1E940), + (0x1E91F, 0x1E941), + (0x1E920, 0x1E942), + (0x1E921, 0x1E943), +] diff --git a/crates/sqlbuild-core/src/text/re_ignorecase_keys/unicode_15_1_0.in b/crates/sqlbuild-core/src/text/re_ignorecase_keys/unicode_15_1_0.in new file mode 100644 index 0000000000..54383d346b --- /dev/null +++ b/crates/sqlbuild-core/src/text/re_ignorecase_keys/unicode_15_1_0.in @@ -0,0 +1,1463 @@ +// Generated by `scripts/generate_python_char_table.py`; do not edit. +// Every character whose `re.IGNORECASE` match key is not itself in Unicode 15.1.0, in code point order. +&[ + (0x0041, 0x0061), + (0x0042, 0x0062), + (0x0043, 0x0063), + (0x0044, 0x0064), + (0x0045, 0x0065), + (0x0046, 0x0066), + (0x0047, 0x0067), + (0x0048, 0x0068), + (0x0049, 0x0069), + (0x004A, 0x006A), + (0x004B, 0x006B), + (0x004C, 0x006C), + (0x004D, 0x006D), + (0x004E, 0x006E), + (0x004F, 0x006F), + (0x0050, 0x0070), + (0x0051, 0x0071), + (0x0052, 0x0072), + (0x0053, 0x0073), + (0x0054, 0x0074), + (0x0055, 0x0075), + (0x0056, 0x0076), + (0x0057, 0x0077), + (0x0058, 0x0078), + (0x0059, 0x0079), + (0x005A, 0x007A), + (0x00C0, 0x00E0), + (0x00C1, 0x00E1), + (0x00C2, 0x00E2), + (0x00C3, 0x00E3), + (0x00C4, 0x00E4), + (0x00C5, 0x00E5), + (0x00C6, 0x00E6), + (0x00C7, 0x00E7), + (0x00C8, 0x00E8), + (0x00C9, 0x00E9), + (0x00CA, 0x00EA), + (0x00CB, 0x00EB), + (0x00CC, 0x00EC), + (0x00CD, 0x00ED), + (0x00CE, 0x00EE), + (0x00CF, 0x00EF), + (0x00D0, 0x00F0), + (0x00D1, 0x00F1), + (0x00D2, 0x00F2), + (0x00D3, 0x00F3), + (0x00D4, 0x00F4), + (0x00D5, 0x00F5), + (0x00D6, 0x00F6), + (0x00D8, 0x00F8), + (0x00D9, 0x00F9), + (0x00DA, 0x00FA), + (0x00DB, 0x00FB), + (0x00DC, 0x00FC), + (0x00DD, 0x00FD), + (0x00DE, 0x00FE), + (0x0100, 0x0101), + (0x0102, 0x0103), + (0x0104, 0x0105), + (0x0106, 0x0107), + (0x0108, 0x0109), + (0x010A, 0x010B), + (0x010C, 0x010D), + (0x010E, 0x010F), + (0x0110, 0x0111), + (0x0112, 0x0113), + (0x0114, 0x0115), + (0x0116, 0x0117), + (0x0118, 0x0119), + (0x011A, 0x011B), + (0x011C, 0x011D), + (0x011E, 0x011F), + (0x0120, 0x0121), + (0x0122, 0x0123), + (0x0124, 0x0125), + (0x0126, 0x0127), + (0x0128, 0x0129), + (0x012A, 0x012B), + (0x012C, 0x012D), + (0x012E, 0x012F), + (0x0130, 0x0069), + (0x0131, 0x0069), + (0x0132, 0x0133), + (0x0134, 0x0135), + (0x0136, 0x0137), + (0x0139, 0x013A), + (0x013B, 0x013C), + (0x013D, 0x013E), + (0x013F, 0x0140), + (0x0141, 0x0142), + (0x0143, 0x0144), + (0x0145, 0x0146), + (0x0147, 0x0148), + (0x014A, 0x014B), + (0x014C, 0x014D), + (0x014E, 0x014F), + (0x0150, 0x0151), + (0x0152, 0x0153), + (0x0154, 0x0155), + (0x0156, 0x0157), + (0x0158, 0x0159), + (0x015A, 0x015B), + (0x015C, 0x015D), + (0x015E, 0x015F), + (0x0160, 0x0161), + (0x0162, 0x0163), + (0x0164, 0x0165), + (0x0166, 0x0167), + (0x0168, 0x0169), + (0x016A, 0x016B), + (0x016C, 0x016D), + (0x016E, 0x016F), + (0x0170, 0x0171), + (0x0172, 0x0173), + (0x0174, 0x0175), + (0x0176, 0x0177), + (0x0178, 0x00FF), + (0x0179, 0x017A), + (0x017B, 0x017C), + (0x017D, 0x017E), + (0x017F, 0x0073), + (0x0181, 0x0253), + (0x0182, 0x0183), + (0x0184, 0x0185), + (0x0186, 0x0254), + (0x0187, 0x0188), + (0x0189, 0x0256), + (0x018A, 0x0257), + (0x018B, 0x018C), + (0x018E, 0x01DD), + (0x018F, 0x0259), + (0x0190, 0x025B), + (0x0191, 0x0192), + (0x0193, 0x0260), + (0x0194, 0x0263), + (0x0196, 0x0269), + (0x0197, 0x0268), + (0x0198, 0x0199), + (0x019C, 0x026F), + (0x019D, 0x0272), + (0x019F, 0x0275), + (0x01A0, 0x01A1), + (0x01A2, 0x01A3), + (0x01A4, 0x01A5), + (0x01A6, 0x0280), + (0x01A7, 0x01A8), + (0x01A9, 0x0283), + (0x01AC, 0x01AD), + (0x01AE, 0x0288), + (0x01AF, 0x01B0), + (0x01B1, 0x028A), + (0x01B2, 0x028B), + (0x01B3, 0x01B4), + (0x01B5, 0x01B6), + (0x01B7, 0x0292), + (0x01B8, 0x01B9), + (0x01BC, 0x01BD), + (0x01C4, 0x01C6), + (0x01C5, 0x01C6), + (0x01C7, 0x01C9), + (0x01C8, 0x01C9), + (0x01CA, 0x01CC), + (0x01CB, 0x01CC), + (0x01CD, 0x01CE), + (0x01CF, 0x01D0), + (0x01D1, 0x01D2), + (0x01D3, 0x01D4), + (0x01D5, 0x01D6), + (0x01D7, 0x01D8), + (0x01D9, 0x01DA), + (0x01DB, 0x01DC), + (0x01DE, 0x01DF), + (0x01E0, 0x01E1), + (0x01E2, 0x01E3), + (0x01E4, 0x01E5), + (0x01E6, 0x01E7), + (0x01E8, 0x01E9), + (0x01EA, 0x01EB), + (0x01EC, 0x01ED), + (0x01EE, 0x01EF), + (0x01F1, 0x01F3), + (0x01F2, 0x01F3), + (0x01F4, 0x01F5), + (0x01F6, 0x0195), + (0x01F7, 0x01BF), + (0x01F8, 0x01F9), + (0x01FA, 0x01FB), + (0x01FC, 0x01FD), + (0x01FE, 0x01FF), + (0x0200, 0x0201), + (0x0202, 0x0203), + (0x0204, 0x0205), + (0x0206, 0x0207), + (0x0208, 0x0209), + (0x020A, 0x020B), + (0x020C, 0x020D), + (0x020E, 0x020F), + (0x0210, 0x0211), + (0x0212, 0x0213), + (0x0214, 0x0215), + (0x0216, 0x0217), + (0x0218, 0x0219), + (0x021A, 0x021B), + (0x021C, 0x021D), + (0x021E, 0x021F), + (0x0220, 0x019E), + (0x0222, 0x0223), + (0x0224, 0x0225), + (0x0226, 0x0227), + (0x0228, 0x0229), + (0x022A, 0x022B), + (0x022C, 0x022D), + (0x022E, 0x022F), + (0x0230, 0x0231), + (0x0232, 0x0233), + (0x023A, 0x2C65), + (0x023B, 0x023C), + (0x023D, 0x019A), + (0x023E, 0x2C66), + (0x0241, 0x0242), + (0x0243, 0x0180), + (0x0244, 0x0289), + (0x0245, 0x028C), + (0x0246, 0x0247), + (0x0248, 0x0249), + (0x024A, 0x024B), + (0x024C, 0x024D), + (0x024E, 0x024F), + (0x0370, 0x0371), + (0x0372, 0x0373), + (0x0376, 0x0377), + (0x037F, 0x03F3), + (0x0386, 0x03AC), + (0x0388, 0x03AD), + (0x0389, 0x03AE), + (0x038A, 0x03AF), + (0x038C, 0x03CC), + (0x038E, 0x03CD), + (0x038F, 0x03CE), + (0x0391, 0x03B1), + (0x0392, 0x03B2), + (0x0393, 0x03B3), + (0x0394, 0x03B4), + (0x0395, 0x03B5), + (0x0396, 0x03B6), + (0x0397, 0x03B7), + (0x0398, 0x03B8), + (0x0399, 0x0345), + (0x039A, 0x03BA), + (0x039B, 0x03BB), + (0x039C, 0x00B5), + (0x039D, 0x03BD), + (0x039E, 0x03BE), + (0x039F, 0x03BF), + (0x03A0, 0x03C0), + (0x03A1, 0x03C1), + (0x03A3, 0x03C2), + (0x03A4, 0x03C4), + (0x03A5, 0x03C5), + (0x03A6, 0x03C6), + (0x03A7, 0x03C7), + (0x03A8, 0x03C8), + (0x03A9, 0x03C9), + (0x03AA, 0x03CA), + (0x03AB, 0x03CB), + (0x03B9, 0x0345), + (0x03BC, 0x00B5), + (0x03C3, 0x03C2), + (0x03CF, 0x03D7), + (0x03D0, 0x03B2), + (0x03D1, 0x03B8), + (0x03D5, 0x03C6), + (0x03D6, 0x03C0), + (0x03D8, 0x03D9), + (0x03DA, 0x03DB), + (0x03DC, 0x03DD), + (0x03DE, 0x03DF), + (0x03E0, 0x03E1), + (0x03E2, 0x03E3), + (0x03E4, 0x03E5), + (0x03E6, 0x03E7), + (0x03E8, 0x03E9), + (0x03EA, 0x03EB), + (0x03EC, 0x03ED), + (0x03EE, 0x03EF), + (0x03F0, 0x03BA), + (0x03F1, 0x03C1), + (0x03F4, 0x03B8), + (0x03F5, 0x03B5), + (0x03F7, 0x03F8), + (0x03F9, 0x03F2), + (0x03FA, 0x03FB), + (0x03FD, 0x037B), + (0x03FE, 0x037C), + (0x03FF, 0x037D), + (0x0400, 0x0450), + (0x0401, 0x0451), + (0x0402, 0x0452), + (0x0403, 0x0453), + (0x0404, 0x0454), + (0x0405, 0x0455), + (0x0406, 0x0456), + (0x0407, 0x0457), + (0x0408, 0x0458), + (0x0409, 0x0459), + (0x040A, 0x045A), + (0x040B, 0x045B), + (0x040C, 0x045C), + (0x040D, 0x045D), + (0x040E, 0x045E), + (0x040F, 0x045F), + (0x0410, 0x0430), + (0x0411, 0x0431), + (0x0412, 0x0432), + (0x0413, 0x0433), + (0x0414, 0x0434), + (0x0415, 0x0435), + (0x0416, 0x0436), + (0x0417, 0x0437), + (0x0418, 0x0438), + (0x0419, 0x0439), + (0x041A, 0x043A), + (0x041B, 0x043B), + (0x041C, 0x043C), + (0x041D, 0x043D), + (0x041E, 0x043E), + (0x041F, 0x043F), + (0x0420, 0x0440), + (0x0421, 0x0441), + (0x0422, 0x0442), + (0x0423, 0x0443), + (0x0424, 0x0444), + (0x0425, 0x0445), + (0x0426, 0x0446), + (0x0427, 0x0447), + (0x0428, 0x0448), + (0x0429, 0x0449), + (0x042A, 0x044A), + (0x042B, 0x044B), + (0x042C, 0x044C), + (0x042D, 0x044D), + (0x042E, 0x044E), + (0x042F, 0x044F), + (0x0460, 0x0461), + (0x0462, 0x0463), + (0x0464, 0x0465), + (0x0466, 0x0467), + (0x0468, 0x0469), + (0x046A, 0x046B), + (0x046C, 0x046D), + (0x046E, 0x046F), + (0x0470, 0x0471), + (0x0472, 0x0473), + (0x0474, 0x0475), + (0x0476, 0x0477), + (0x0478, 0x0479), + (0x047A, 0x047B), + (0x047C, 0x047D), + (0x047E, 0x047F), + (0x0480, 0x0481), + (0x048A, 0x048B), + (0x048C, 0x048D), + (0x048E, 0x048F), + (0x0490, 0x0491), + (0x0492, 0x0493), + (0x0494, 0x0495), + (0x0496, 0x0497), + (0x0498, 0x0499), + (0x049A, 0x049B), + (0x049C, 0x049D), + (0x049E, 0x049F), + (0x04A0, 0x04A1), + (0x04A2, 0x04A3), + (0x04A4, 0x04A5), + (0x04A6, 0x04A7), + (0x04A8, 0x04A9), + (0x04AA, 0x04AB), + (0x04AC, 0x04AD), + (0x04AE, 0x04AF), + (0x04B0, 0x04B1), + (0x04B2, 0x04B3), + (0x04B4, 0x04B5), + (0x04B6, 0x04B7), + (0x04B8, 0x04B9), + (0x04BA, 0x04BB), + (0x04BC, 0x04BD), + (0x04BE, 0x04BF), + (0x04C0, 0x04CF), + (0x04C1, 0x04C2), + (0x04C3, 0x04C4), + (0x04C5, 0x04C6), + (0x04C7, 0x04C8), + (0x04C9, 0x04CA), + (0x04CB, 0x04CC), + (0x04CD, 0x04CE), + (0x04D0, 0x04D1), + (0x04D2, 0x04D3), + (0x04D4, 0x04D5), + (0x04D6, 0x04D7), + (0x04D8, 0x04D9), + (0x04DA, 0x04DB), + (0x04DC, 0x04DD), + (0x04DE, 0x04DF), + (0x04E0, 0x04E1), + (0x04E2, 0x04E3), + (0x04E4, 0x04E5), + (0x04E6, 0x04E7), + (0x04E8, 0x04E9), + (0x04EA, 0x04EB), + (0x04EC, 0x04ED), + (0x04EE, 0x04EF), + (0x04F0, 0x04F1), + (0x04F2, 0x04F3), + (0x04F4, 0x04F5), + (0x04F6, 0x04F7), + (0x04F8, 0x04F9), + (0x04FA, 0x04FB), + (0x04FC, 0x04FD), + (0x04FE, 0x04FF), + (0x0500, 0x0501), + (0x0502, 0x0503), + (0x0504, 0x0505), + (0x0506, 0x0507), + (0x0508, 0x0509), + (0x050A, 0x050B), + (0x050C, 0x050D), + (0x050E, 0x050F), + (0x0510, 0x0511), + (0x0512, 0x0513), + (0x0514, 0x0515), + (0x0516, 0x0517), + (0x0518, 0x0519), + (0x051A, 0x051B), + (0x051C, 0x051D), + (0x051E, 0x051F), + (0x0520, 0x0521), + (0x0522, 0x0523), + (0x0524, 0x0525), + (0x0526, 0x0527), + (0x0528, 0x0529), + (0x052A, 0x052B), + (0x052C, 0x052D), + (0x052E, 0x052F), + (0x0531, 0x0561), + (0x0532, 0x0562), + (0x0533, 0x0563), + (0x0534, 0x0564), + (0x0535, 0x0565), + (0x0536, 0x0566), + (0x0537, 0x0567), + (0x0538, 0x0568), + (0x0539, 0x0569), + (0x053A, 0x056A), + (0x053B, 0x056B), + (0x053C, 0x056C), + (0x053D, 0x056D), + (0x053E, 0x056E), + (0x053F, 0x056F), + (0x0540, 0x0570), + (0x0541, 0x0571), + (0x0542, 0x0572), + (0x0543, 0x0573), + (0x0544, 0x0574), + (0x0545, 0x0575), + (0x0546, 0x0576), + (0x0547, 0x0577), + (0x0548, 0x0578), + (0x0549, 0x0579), + (0x054A, 0x057A), + (0x054B, 0x057B), + (0x054C, 0x057C), + (0x054D, 0x057D), + (0x054E, 0x057E), + (0x054F, 0x057F), + (0x0550, 0x0580), + (0x0551, 0x0581), + (0x0552, 0x0582), + (0x0553, 0x0583), + (0x0554, 0x0584), + (0x0555, 0x0585), + (0x0556, 0x0586), + (0x10A0, 0x2D00), + (0x10A1, 0x2D01), + (0x10A2, 0x2D02), + (0x10A3, 0x2D03), + (0x10A4, 0x2D04), + (0x10A5, 0x2D05), + (0x10A6, 0x2D06), + (0x10A7, 0x2D07), + (0x10A8, 0x2D08), + (0x10A9, 0x2D09), + (0x10AA, 0x2D0A), + (0x10AB, 0x2D0B), + (0x10AC, 0x2D0C), + (0x10AD, 0x2D0D), + (0x10AE, 0x2D0E), + (0x10AF, 0x2D0F), + (0x10B0, 0x2D10), + (0x10B1, 0x2D11), + (0x10B2, 0x2D12), + (0x10B3, 0x2D13), + (0x10B4, 0x2D14), + (0x10B5, 0x2D15), + (0x10B6, 0x2D16), + (0x10B7, 0x2D17), + (0x10B8, 0x2D18), + (0x10B9, 0x2D19), + (0x10BA, 0x2D1A), + (0x10BB, 0x2D1B), + (0x10BC, 0x2D1C), + (0x10BD, 0x2D1D), + (0x10BE, 0x2D1E), + (0x10BF, 0x2D1F), + (0x10C0, 0x2D20), + (0x10C1, 0x2D21), + (0x10C2, 0x2D22), + (0x10C3, 0x2D23), + (0x10C4, 0x2D24), + (0x10C5, 0x2D25), + (0x10C7, 0x2D27), + (0x10CD, 0x2D2D), + (0x13A0, 0xAB70), + (0x13A1, 0xAB71), + (0x13A2, 0xAB72), + (0x13A3, 0xAB73), + (0x13A4, 0xAB74), + (0x13A5, 0xAB75), + (0x13A6, 0xAB76), + (0x13A7, 0xAB77), + (0x13A8, 0xAB78), + (0x13A9, 0xAB79), + (0x13AA, 0xAB7A), + (0x13AB, 0xAB7B), + (0x13AC, 0xAB7C), + (0x13AD, 0xAB7D), + (0x13AE, 0xAB7E), + (0x13AF, 0xAB7F), + (0x13B0, 0xAB80), + (0x13B1, 0xAB81), + (0x13B2, 0xAB82), + (0x13B3, 0xAB83), + (0x13B4, 0xAB84), + (0x13B5, 0xAB85), + (0x13B6, 0xAB86), + (0x13B7, 0xAB87), + (0x13B8, 0xAB88), + (0x13B9, 0xAB89), + (0x13BA, 0xAB8A), + (0x13BB, 0xAB8B), + (0x13BC, 0xAB8C), + (0x13BD, 0xAB8D), + (0x13BE, 0xAB8E), + (0x13BF, 0xAB8F), + (0x13C0, 0xAB90), + (0x13C1, 0xAB91), + (0x13C2, 0xAB92), + (0x13C3, 0xAB93), + (0x13C4, 0xAB94), + (0x13C5, 0xAB95), + (0x13C6, 0xAB96), + (0x13C7, 0xAB97), + (0x13C8, 0xAB98), + (0x13C9, 0xAB99), + (0x13CA, 0xAB9A), + (0x13CB, 0xAB9B), + (0x13CC, 0xAB9C), + (0x13CD, 0xAB9D), + (0x13CE, 0xAB9E), + (0x13CF, 0xAB9F), + (0x13D0, 0xABA0), + (0x13D1, 0xABA1), + (0x13D2, 0xABA2), + (0x13D3, 0xABA3), + (0x13D4, 0xABA4), + (0x13D5, 0xABA5), + (0x13D6, 0xABA6), + (0x13D7, 0xABA7), + (0x13D8, 0xABA8), + (0x13D9, 0xABA9), + (0x13DA, 0xABAA), + (0x13DB, 0xABAB), + (0x13DC, 0xABAC), + (0x13DD, 0xABAD), + (0x13DE, 0xABAE), + (0x13DF, 0xABAF), + (0x13E0, 0xABB0), + (0x13E1, 0xABB1), + (0x13E2, 0xABB2), + (0x13E3, 0xABB3), + (0x13E4, 0xABB4), + (0x13E5, 0xABB5), + (0x13E6, 0xABB6), + (0x13E7, 0xABB7), + (0x13E8, 0xABB8), + (0x13E9, 0xABB9), + (0x13EA, 0xABBA), + (0x13EB, 0xABBB), + (0x13EC, 0xABBC), + (0x13ED, 0xABBD), + (0x13EE, 0xABBE), + (0x13EF, 0xABBF), + (0x13F0, 0x13F8), + (0x13F1, 0x13F9), + (0x13F2, 0x13FA), + (0x13F3, 0x13FB), + (0x13F4, 0x13FC), + (0x13F5, 0x13FD), + (0x1C80, 0x0432), + (0x1C81, 0x0434), + (0x1C82, 0x043E), + (0x1C83, 0x0441), + (0x1C84, 0x0442), + (0x1C85, 0x0442), + (0x1C86, 0x044A), + (0x1C87, 0x0463), + (0x1C90, 0x10D0), + (0x1C91, 0x10D1), + (0x1C92, 0x10D2), + (0x1C93, 0x10D3), + (0x1C94, 0x10D4), + (0x1C95, 0x10D5), + (0x1C96, 0x10D6), + (0x1C97, 0x10D7), + (0x1C98, 0x10D8), + (0x1C99, 0x10D9), + (0x1C9A, 0x10DA), + (0x1C9B, 0x10DB), + (0x1C9C, 0x10DC), + (0x1C9D, 0x10DD), + (0x1C9E, 0x10DE), + (0x1C9F, 0x10DF), + (0x1CA0, 0x10E0), + (0x1CA1, 0x10E1), + (0x1CA2, 0x10E2), + (0x1CA3, 0x10E3), + (0x1CA4, 0x10E4), + (0x1CA5, 0x10E5), + (0x1CA6, 0x10E6), + (0x1CA7, 0x10E7), + (0x1CA8, 0x10E8), + (0x1CA9, 0x10E9), + (0x1CAA, 0x10EA), + (0x1CAB, 0x10EB), + (0x1CAC, 0x10EC), + (0x1CAD, 0x10ED), + (0x1CAE, 0x10EE), + (0x1CAF, 0x10EF), + (0x1CB0, 0x10F0), + (0x1CB1, 0x10F1), + (0x1CB2, 0x10F2), + (0x1CB3, 0x10F3), + (0x1CB4, 0x10F4), + (0x1CB5, 0x10F5), + (0x1CB6, 0x10F6), + (0x1CB7, 0x10F7), + (0x1CB8, 0x10F8), + (0x1CB9, 0x10F9), + (0x1CBA, 0x10FA), + (0x1CBD, 0x10FD), + (0x1CBE, 0x10FE), + (0x1CBF, 0x10FF), + (0x1E00, 0x1E01), + (0x1E02, 0x1E03), + (0x1E04, 0x1E05), + (0x1E06, 0x1E07), + (0x1E08, 0x1E09), + (0x1E0A, 0x1E0B), + (0x1E0C, 0x1E0D), + (0x1E0E, 0x1E0F), + (0x1E10, 0x1E11), + (0x1E12, 0x1E13), + (0x1E14, 0x1E15), + (0x1E16, 0x1E17), + (0x1E18, 0x1E19), + (0x1E1A, 0x1E1B), + (0x1E1C, 0x1E1D), + (0x1E1E, 0x1E1F), + (0x1E20, 0x1E21), + (0x1E22, 0x1E23), + (0x1E24, 0x1E25), + (0x1E26, 0x1E27), + (0x1E28, 0x1E29), + (0x1E2A, 0x1E2B), + (0x1E2C, 0x1E2D), + (0x1E2E, 0x1E2F), + (0x1E30, 0x1E31), + (0x1E32, 0x1E33), + (0x1E34, 0x1E35), + (0x1E36, 0x1E37), + (0x1E38, 0x1E39), + (0x1E3A, 0x1E3B), + (0x1E3C, 0x1E3D), + (0x1E3E, 0x1E3F), + (0x1E40, 0x1E41), + (0x1E42, 0x1E43), + (0x1E44, 0x1E45), + (0x1E46, 0x1E47), + (0x1E48, 0x1E49), + (0x1E4A, 0x1E4B), + (0x1E4C, 0x1E4D), + (0x1E4E, 0x1E4F), + (0x1E50, 0x1E51), + (0x1E52, 0x1E53), + (0x1E54, 0x1E55), + (0x1E56, 0x1E57), + (0x1E58, 0x1E59), + (0x1E5A, 0x1E5B), + (0x1E5C, 0x1E5D), + (0x1E5E, 0x1E5F), + (0x1E60, 0x1E61), + (0x1E62, 0x1E63), + (0x1E64, 0x1E65), + (0x1E66, 0x1E67), + (0x1E68, 0x1E69), + (0x1E6A, 0x1E6B), + (0x1E6C, 0x1E6D), + (0x1E6E, 0x1E6F), + (0x1E70, 0x1E71), + (0x1E72, 0x1E73), + (0x1E74, 0x1E75), + (0x1E76, 0x1E77), + (0x1E78, 0x1E79), + (0x1E7A, 0x1E7B), + (0x1E7C, 0x1E7D), + (0x1E7E, 0x1E7F), + (0x1E80, 0x1E81), + (0x1E82, 0x1E83), + (0x1E84, 0x1E85), + (0x1E86, 0x1E87), + (0x1E88, 0x1E89), + (0x1E8A, 0x1E8B), + (0x1E8C, 0x1E8D), + (0x1E8E, 0x1E8F), + (0x1E90, 0x1E91), + (0x1E92, 0x1E93), + (0x1E94, 0x1E95), + (0x1E9B, 0x1E61), + (0x1E9E, 0x00DF), + (0x1EA0, 0x1EA1), + (0x1EA2, 0x1EA3), + (0x1EA4, 0x1EA5), + (0x1EA6, 0x1EA7), + (0x1EA8, 0x1EA9), + (0x1EAA, 0x1EAB), + (0x1EAC, 0x1EAD), + (0x1EAE, 0x1EAF), + (0x1EB0, 0x1EB1), + (0x1EB2, 0x1EB3), + (0x1EB4, 0x1EB5), + (0x1EB6, 0x1EB7), + (0x1EB8, 0x1EB9), + (0x1EBA, 0x1EBB), + (0x1EBC, 0x1EBD), + (0x1EBE, 0x1EBF), + (0x1EC0, 0x1EC1), + (0x1EC2, 0x1EC3), + (0x1EC4, 0x1EC5), + (0x1EC6, 0x1EC7), + (0x1EC8, 0x1EC9), + (0x1ECA, 0x1ECB), + (0x1ECC, 0x1ECD), + (0x1ECE, 0x1ECF), + (0x1ED0, 0x1ED1), + (0x1ED2, 0x1ED3), + (0x1ED4, 0x1ED5), + (0x1ED6, 0x1ED7), + (0x1ED8, 0x1ED9), + (0x1EDA, 0x1EDB), + (0x1EDC, 0x1EDD), + (0x1EDE, 0x1EDF), + (0x1EE0, 0x1EE1), + (0x1EE2, 0x1EE3), + (0x1EE4, 0x1EE5), + (0x1EE6, 0x1EE7), + (0x1EE8, 0x1EE9), + (0x1EEA, 0x1EEB), + (0x1EEC, 0x1EED), + (0x1EEE, 0x1EEF), + (0x1EF0, 0x1EF1), + (0x1EF2, 0x1EF3), + (0x1EF4, 0x1EF5), + (0x1EF6, 0x1EF7), + (0x1EF8, 0x1EF9), + (0x1EFA, 0x1EFB), + (0x1EFC, 0x1EFD), + (0x1EFE, 0x1EFF), + (0x1F08, 0x1F00), + (0x1F09, 0x1F01), + (0x1F0A, 0x1F02), + (0x1F0B, 0x1F03), + (0x1F0C, 0x1F04), + (0x1F0D, 0x1F05), + (0x1F0E, 0x1F06), + (0x1F0F, 0x1F07), + (0x1F18, 0x1F10), + (0x1F19, 0x1F11), + (0x1F1A, 0x1F12), + (0x1F1B, 0x1F13), + (0x1F1C, 0x1F14), + (0x1F1D, 0x1F15), + (0x1F28, 0x1F20), + (0x1F29, 0x1F21), + (0x1F2A, 0x1F22), + (0x1F2B, 0x1F23), + (0x1F2C, 0x1F24), + (0x1F2D, 0x1F25), + (0x1F2E, 0x1F26), + (0x1F2F, 0x1F27), + (0x1F38, 0x1F30), + (0x1F39, 0x1F31), + (0x1F3A, 0x1F32), + (0x1F3B, 0x1F33), + (0x1F3C, 0x1F34), + (0x1F3D, 0x1F35), + (0x1F3E, 0x1F36), + (0x1F3F, 0x1F37), + (0x1F48, 0x1F40), + (0x1F49, 0x1F41), + (0x1F4A, 0x1F42), + (0x1F4B, 0x1F43), + (0x1F4C, 0x1F44), + (0x1F4D, 0x1F45), + (0x1F59, 0x1F51), + (0x1F5B, 0x1F53), + (0x1F5D, 0x1F55), + (0x1F5F, 0x1F57), + (0x1F68, 0x1F60), + (0x1F69, 0x1F61), + (0x1F6A, 0x1F62), + (0x1F6B, 0x1F63), + (0x1F6C, 0x1F64), + (0x1F6D, 0x1F65), + (0x1F6E, 0x1F66), + (0x1F6F, 0x1F67), + (0x1F88, 0x1F80), + (0x1F89, 0x1F81), + (0x1F8A, 0x1F82), + (0x1F8B, 0x1F83), + (0x1F8C, 0x1F84), + (0x1F8D, 0x1F85), + (0x1F8E, 0x1F86), + (0x1F8F, 0x1F87), + (0x1F98, 0x1F90), + (0x1F99, 0x1F91), + (0x1F9A, 0x1F92), + (0x1F9B, 0x1F93), + (0x1F9C, 0x1F94), + (0x1F9D, 0x1F95), + (0x1F9E, 0x1F96), + (0x1F9F, 0x1F97), + (0x1FA8, 0x1FA0), + (0x1FA9, 0x1FA1), + (0x1FAA, 0x1FA2), + (0x1FAB, 0x1FA3), + (0x1FAC, 0x1FA4), + (0x1FAD, 0x1FA5), + (0x1FAE, 0x1FA6), + (0x1FAF, 0x1FA7), + (0x1FB8, 0x1FB0), + (0x1FB9, 0x1FB1), + (0x1FBA, 0x1F70), + (0x1FBB, 0x1F71), + (0x1FBC, 0x1FB3), + (0x1FBE, 0x0345), + (0x1FC8, 0x1F72), + (0x1FC9, 0x1F73), + (0x1FCA, 0x1F74), + (0x1FCB, 0x1F75), + (0x1FCC, 0x1FC3), + (0x1FD3, 0x0390), + (0x1FD8, 0x1FD0), + (0x1FD9, 0x1FD1), + (0x1FDA, 0x1F76), + (0x1FDB, 0x1F77), + (0x1FE3, 0x03B0), + (0x1FE8, 0x1FE0), + (0x1FE9, 0x1FE1), + (0x1FEA, 0x1F7A), + (0x1FEB, 0x1F7B), + (0x1FEC, 0x1FE5), + (0x1FF8, 0x1F78), + (0x1FF9, 0x1F79), + (0x1FFA, 0x1F7C), + (0x1FFB, 0x1F7D), + (0x1FFC, 0x1FF3), + (0x2126, 0x03C9), + (0x212A, 0x006B), + (0x212B, 0x00E5), + (0x2132, 0x214E), + (0x2160, 0x2170), + (0x2161, 0x2171), + (0x2162, 0x2172), + (0x2163, 0x2173), + (0x2164, 0x2174), + (0x2165, 0x2175), + (0x2166, 0x2176), + (0x2167, 0x2177), + (0x2168, 0x2178), + (0x2169, 0x2179), + (0x216A, 0x217A), + (0x216B, 0x217B), + (0x216C, 0x217C), + (0x216D, 0x217D), + (0x216E, 0x217E), + (0x216F, 0x217F), + (0x2183, 0x2184), + (0x24B6, 0x24D0), + (0x24B7, 0x24D1), + (0x24B8, 0x24D2), + (0x24B9, 0x24D3), + (0x24BA, 0x24D4), + (0x24BB, 0x24D5), + (0x24BC, 0x24D6), + (0x24BD, 0x24D7), + (0x24BE, 0x24D8), + (0x24BF, 0x24D9), + (0x24C0, 0x24DA), + (0x24C1, 0x24DB), + (0x24C2, 0x24DC), + (0x24C3, 0x24DD), + (0x24C4, 0x24DE), + (0x24C5, 0x24DF), + (0x24C6, 0x24E0), + (0x24C7, 0x24E1), + (0x24C8, 0x24E2), + (0x24C9, 0x24E3), + (0x24CA, 0x24E4), + (0x24CB, 0x24E5), + (0x24CC, 0x24E6), + (0x24CD, 0x24E7), + (0x24CE, 0x24E8), + (0x24CF, 0x24E9), + (0x2C00, 0x2C30), + (0x2C01, 0x2C31), + (0x2C02, 0x2C32), + (0x2C03, 0x2C33), + (0x2C04, 0x2C34), + (0x2C05, 0x2C35), + (0x2C06, 0x2C36), + (0x2C07, 0x2C37), + (0x2C08, 0x2C38), + (0x2C09, 0x2C39), + (0x2C0A, 0x2C3A), + (0x2C0B, 0x2C3B), + (0x2C0C, 0x2C3C), + (0x2C0D, 0x2C3D), + (0x2C0E, 0x2C3E), + (0x2C0F, 0x2C3F), + (0x2C10, 0x2C40), + (0x2C11, 0x2C41), + (0x2C12, 0x2C42), + (0x2C13, 0x2C43), + (0x2C14, 0x2C44), + (0x2C15, 0x2C45), + (0x2C16, 0x2C46), + (0x2C17, 0x2C47), + (0x2C18, 0x2C48), + (0x2C19, 0x2C49), + (0x2C1A, 0x2C4A), + (0x2C1B, 0x2C4B), + (0x2C1C, 0x2C4C), + (0x2C1D, 0x2C4D), + (0x2C1E, 0x2C4E), + (0x2C1F, 0x2C4F), + (0x2C20, 0x2C50), + (0x2C21, 0x2C51), + (0x2C22, 0x2C52), + (0x2C23, 0x2C53), + (0x2C24, 0x2C54), + (0x2C25, 0x2C55), + (0x2C26, 0x2C56), + (0x2C27, 0x2C57), + (0x2C28, 0x2C58), + (0x2C29, 0x2C59), + (0x2C2A, 0x2C5A), + (0x2C2B, 0x2C5B), + (0x2C2C, 0x2C5C), + (0x2C2D, 0x2C5D), + (0x2C2E, 0x2C5E), + (0x2C2F, 0x2C5F), + (0x2C60, 0x2C61), + (0x2C62, 0x026B), + (0x2C63, 0x1D7D), + (0x2C64, 0x027D), + (0x2C67, 0x2C68), + (0x2C69, 0x2C6A), + (0x2C6B, 0x2C6C), + (0x2C6D, 0x0251), + (0x2C6E, 0x0271), + (0x2C6F, 0x0250), + (0x2C70, 0x0252), + (0x2C72, 0x2C73), + (0x2C75, 0x2C76), + (0x2C7E, 0x023F), + (0x2C7F, 0x0240), + (0x2C80, 0x2C81), + (0x2C82, 0x2C83), + (0x2C84, 0x2C85), + (0x2C86, 0x2C87), + (0x2C88, 0x2C89), + (0x2C8A, 0x2C8B), + (0x2C8C, 0x2C8D), + (0x2C8E, 0x2C8F), + (0x2C90, 0x2C91), + (0x2C92, 0x2C93), + (0x2C94, 0x2C95), + (0x2C96, 0x2C97), + (0x2C98, 0x2C99), + (0x2C9A, 0x2C9B), + (0x2C9C, 0x2C9D), + (0x2C9E, 0x2C9F), + (0x2CA0, 0x2CA1), + (0x2CA2, 0x2CA3), + (0x2CA4, 0x2CA5), + (0x2CA6, 0x2CA7), + (0x2CA8, 0x2CA9), + (0x2CAA, 0x2CAB), + (0x2CAC, 0x2CAD), + (0x2CAE, 0x2CAF), + (0x2CB0, 0x2CB1), + (0x2CB2, 0x2CB3), + (0x2CB4, 0x2CB5), + (0x2CB6, 0x2CB7), + (0x2CB8, 0x2CB9), + (0x2CBA, 0x2CBB), + (0x2CBC, 0x2CBD), + (0x2CBE, 0x2CBF), + (0x2CC0, 0x2CC1), + (0x2CC2, 0x2CC3), + (0x2CC4, 0x2CC5), + (0x2CC6, 0x2CC7), + (0x2CC8, 0x2CC9), + (0x2CCA, 0x2CCB), + (0x2CCC, 0x2CCD), + (0x2CCE, 0x2CCF), + (0x2CD0, 0x2CD1), + (0x2CD2, 0x2CD3), + (0x2CD4, 0x2CD5), + (0x2CD6, 0x2CD7), + (0x2CD8, 0x2CD9), + (0x2CDA, 0x2CDB), + (0x2CDC, 0x2CDD), + (0x2CDE, 0x2CDF), + (0x2CE0, 0x2CE1), + (0x2CE2, 0x2CE3), + (0x2CEB, 0x2CEC), + (0x2CED, 0x2CEE), + (0x2CF2, 0x2CF3), + (0xA640, 0xA641), + (0xA642, 0xA643), + (0xA644, 0xA645), + (0xA646, 0xA647), + (0xA648, 0xA649), + (0xA64A, 0x1C88), + (0xA64B, 0x1C88), + (0xA64C, 0xA64D), + (0xA64E, 0xA64F), + (0xA650, 0xA651), + (0xA652, 0xA653), + (0xA654, 0xA655), + (0xA656, 0xA657), + (0xA658, 0xA659), + (0xA65A, 0xA65B), + (0xA65C, 0xA65D), + (0xA65E, 0xA65F), + (0xA660, 0xA661), + (0xA662, 0xA663), + (0xA664, 0xA665), + (0xA666, 0xA667), + (0xA668, 0xA669), + (0xA66A, 0xA66B), + (0xA66C, 0xA66D), + (0xA680, 0xA681), + (0xA682, 0xA683), + (0xA684, 0xA685), + (0xA686, 0xA687), + (0xA688, 0xA689), + (0xA68A, 0xA68B), + (0xA68C, 0xA68D), + (0xA68E, 0xA68F), + (0xA690, 0xA691), + (0xA692, 0xA693), + (0xA694, 0xA695), + (0xA696, 0xA697), + (0xA698, 0xA699), + (0xA69A, 0xA69B), + (0xA722, 0xA723), + (0xA724, 0xA725), + (0xA726, 0xA727), + (0xA728, 0xA729), + (0xA72A, 0xA72B), + (0xA72C, 0xA72D), + (0xA72E, 0xA72F), + (0xA732, 0xA733), + (0xA734, 0xA735), + (0xA736, 0xA737), + (0xA738, 0xA739), + (0xA73A, 0xA73B), + (0xA73C, 0xA73D), + (0xA73E, 0xA73F), + (0xA740, 0xA741), + (0xA742, 0xA743), + (0xA744, 0xA745), + (0xA746, 0xA747), + (0xA748, 0xA749), + (0xA74A, 0xA74B), + (0xA74C, 0xA74D), + (0xA74E, 0xA74F), + (0xA750, 0xA751), + (0xA752, 0xA753), + (0xA754, 0xA755), + (0xA756, 0xA757), + (0xA758, 0xA759), + (0xA75A, 0xA75B), + (0xA75C, 0xA75D), + (0xA75E, 0xA75F), + (0xA760, 0xA761), + (0xA762, 0xA763), + (0xA764, 0xA765), + (0xA766, 0xA767), + (0xA768, 0xA769), + (0xA76A, 0xA76B), + (0xA76C, 0xA76D), + (0xA76E, 0xA76F), + (0xA779, 0xA77A), + (0xA77B, 0xA77C), + (0xA77D, 0x1D79), + (0xA77E, 0xA77F), + (0xA780, 0xA781), + (0xA782, 0xA783), + (0xA784, 0xA785), + (0xA786, 0xA787), + (0xA78B, 0xA78C), + (0xA78D, 0x0265), + (0xA790, 0xA791), + (0xA792, 0xA793), + (0xA796, 0xA797), + (0xA798, 0xA799), + (0xA79A, 0xA79B), + (0xA79C, 0xA79D), + (0xA79E, 0xA79F), + (0xA7A0, 0xA7A1), + (0xA7A2, 0xA7A3), + (0xA7A4, 0xA7A5), + (0xA7A6, 0xA7A7), + (0xA7A8, 0xA7A9), + (0xA7AA, 0x0266), + (0xA7AB, 0x025C), + (0xA7AC, 0x0261), + (0xA7AD, 0x026C), + (0xA7AE, 0x026A), + (0xA7B0, 0x029E), + (0xA7B1, 0x0287), + (0xA7B2, 0x029D), + (0xA7B3, 0xAB53), + (0xA7B4, 0xA7B5), + (0xA7B6, 0xA7B7), + (0xA7B8, 0xA7B9), + (0xA7BA, 0xA7BB), + (0xA7BC, 0xA7BD), + (0xA7BE, 0xA7BF), + (0xA7C0, 0xA7C1), + (0xA7C2, 0xA7C3), + (0xA7C4, 0xA794), + (0xA7C5, 0x0282), + (0xA7C6, 0x1D8E), + (0xA7C7, 0xA7C8), + (0xA7C9, 0xA7CA), + (0xA7D0, 0xA7D1), + (0xA7D6, 0xA7D7), + (0xA7D8, 0xA7D9), + (0xA7F5, 0xA7F6), + (0xFB06, 0xFB05), + (0xFF21, 0xFF41), + (0xFF22, 0xFF42), + (0xFF23, 0xFF43), + (0xFF24, 0xFF44), + (0xFF25, 0xFF45), + (0xFF26, 0xFF46), + (0xFF27, 0xFF47), + (0xFF28, 0xFF48), + (0xFF29, 0xFF49), + (0xFF2A, 0xFF4A), + (0xFF2B, 0xFF4B), + (0xFF2C, 0xFF4C), + (0xFF2D, 0xFF4D), + (0xFF2E, 0xFF4E), + (0xFF2F, 0xFF4F), + (0xFF30, 0xFF50), + (0xFF31, 0xFF51), + (0xFF32, 0xFF52), + (0xFF33, 0xFF53), + (0xFF34, 0xFF54), + (0xFF35, 0xFF55), + (0xFF36, 0xFF56), + (0xFF37, 0xFF57), + (0xFF38, 0xFF58), + (0xFF39, 0xFF59), + (0xFF3A, 0xFF5A), + (0x10400, 0x10428), + (0x10401, 0x10429), + (0x10402, 0x1042A), + (0x10403, 0x1042B), + (0x10404, 0x1042C), + (0x10405, 0x1042D), + (0x10406, 0x1042E), + (0x10407, 0x1042F), + (0x10408, 0x10430), + (0x10409, 0x10431), + (0x1040A, 0x10432), + (0x1040B, 0x10433), + (0x1040C, 0x10434), + (0x1040D, 0x10435), + (0x1040E, 0x10436), + (0x1040F, 0x10437), + (0x10410, 0x10438), + (0x10411, 0x10439), + (0x10412, 0x1043A), + (0x10413, 0x1043B), + (0x10414, 0x1043C), + (0x10415, 0x1043D), + (0x10416, 0x1043E), + (0x10417, 0x1043F), + (0x10418, 0x10440), + (0x10419, 0x10441), + (0x1041A, 0x10442), + (0x1041B, 0x10443), + (0x1041C, 0x10444), + (0x1041D, 0x10445), + (0x1041E, 0x10446), + (0x1041F, 0x10447), + (0x10420, 0x10448), + (0x10421, 0x10449), + (0x10422, 0x1044A), + (0x10423, 0x1044B), + (0x10424, 0x1044C), + (0x10425, 0x1044D), + (0x10426, 0x1044E), + (0x10427, 0x1044F), + (0x104B0, 0x104D8), + (0x104B1, 0x104D9), + (0x104B2, 0x104DA), + (0x104B3, 0x104DB), + (0x104B4, 0x104DC), + (0x104B5, 0x104DD), + (0x104B6, 0x104DE), + (0x104B7, 0x104DF), + (0x104B8, 0x104E0), + (0x104B9, 0x104E1), + (0x104BA, 0x104E2), + (0x104BB, 0x104E3), + (0x104BC, 0x104E4), + (0x104BD, 0x104E5), + (0x104BE, 0x104E6), + (0x104BF, 0x104E7), + (0x104C0, 0x104E8), + (0x104C1, 0x104E9), + (0x104C2, 0x104EA), + (0x104C3, 0x104EB), + (0x104C4, 0x104EC), + (0x104C5, 0x104ED), + (0x104C6, 0x104EE), + (0x104C7, 0x104EF), + (0x104C8, 0x104F0), + (0x104C9, 0x104F1), + (0x104CA, 0x104F2), + (0x104CB, 0x104F3), + (0x104CC, 0x104F4), + (0x104CD, 0x104F5), + (0x104CE, 0x104F6), + (0x104CF, 0x104F7), + (0x104D0, 0x104F8), + (0x104D1, 0x104F9), + (0x104D2, 0x104FA), + (0x104D3, 0x104FB), + (0x10570, 0x10597), + (0x10571, 0x10598), + (0x10572, 0x10599), + (0x10573, 0x1059A), + (0x10574, 0x1059B), + (0x10575, 0x1059C), + (0x10576, 0x1059D), + (0x10577, 0x1059E), + (0x10578, 0x1059F), + (0x10579, 0x105A0), + (0x1057A, 0x105A1), + (0x1057C, 0x105A3), + (0x1057D, 0x105A4), + (0x1057E, 0x105A5), + (0x1057F, 0x105A6), + (0x10580, 0x105A7), + (0x10581, 0x105A8), + (0x10582, 0x105A9), + (0x10583, 0x105AA), + (0x10584, 0x105AB), + (0x10585, 0x105AC), + (0x10586, 0x105AD), + (0x10587, 0x105AE), + (0x10588, 0x105AF), + (0x10589, 0x105B0), + (0x1058A, 0x105B1), + (0x1058C, 0x105B3), + (0x1058D, 0x105B4), + (0x1058E, 0x105B5), + (0x1058F, 0x105B6), + (0x10590, 0x105B7), + (0x10591, 0x105B8), + (0x10592, 0x105B9), + (0x10594, 0x105BB), + (0x10595, 0x105BC), + (0x10C80, 0x10CC0), + (0x10C81, 0x10CC1), + (0x10C82, 0x10CC2), + (0x10C83, 0x10CC3), + (0x10C84, 0x10CC4), + (0x10C85, 0x10CC5), + (0x10C86, 0x10CC6), + (0x10C87, 0x10CC7), + (0x10C88, 0x10CC8), + (0x10C89, 0x10CC9), + (0x10C8A, 0x10CCA), + (0x10C8B, 0x10CCB), + (0x10C8C, 0x10CCC), + (0x10C8D, 0x10CCD), + (0x10C8E, 0x10CCE), + (0x10C8F, 0x10CCF), + (0x10C90, 0x10CD0), + (0x10C91, 0x10CD1), + (0x10C92, 0x10CD2), + (0x10C93, 0x10CD3), + (0x10C94, 0x10CD4), + (0x10C95, 0x10CD5), + (0x10C96, 0x10CD6), + (0x10C97, 0x10CD7), + (0x10C98, 0x10CD8), + (0x10C99, 0x10CD9), + (0x10C9A, 0x10CDA), + (0x10C9B, 0x10CDB), + (0x10C9C, 0x10CDC), + (0x10C9D, 0x10CDD), + (0x10C9E, 0x10CDE), + (0x10C9F, 0x10CDF), + (0x10CA0, 0x10CE0), + (0x10CA1, 0x10CE1), + (0x10CA2, 0x10CE2), + (0x10CA3, 0x10CE3), + (0x10CA4, 0x10CE4), + (0x10CA5, 0x10CE5), + (0x10CA6, 0x10CE6), + (0x10CA7, 0x10CE7), + (0x10CA8, 0x10CE8), + (0x10CA9, 0x10CE9), + (0x10CAA, 0x10CEA), + (0x10CAB, 0x10CEB), + (0x10CAC, 0x10CEC), + (0x10CAD, 0x10CED), + (0x10CAE, 0x10CEE), + (0x10CAF, 0x10CEF), + (0x10CB0, 0x10CF0), + (0x10CB1, 0x10CF1), + (0x10CB2, 0x10CF2), + (0x118A0, 0x118C0), + (0x118A1, 0x118C1), + (0x118A2, 0x118C2), + (0x118A3, 0x118C3), + (0x118A4, 0x118C4), + (0x118A5, 0x118C5), + (0x118A6, 0x118C6), + (0x118A7, 0x118C7), + (0x118A8, 0x118C8), + (0x118A9, 0x118C9), + (0x118AA, 0x118CA), + (0x118AB, 0x118CB), + (0x118AC, 0x118CC), + (0x118AD, 0x118CD), + (0x118AE, 0x118CE), + (0x118AF, 0x118CF), + (0x118B0, 0x118D0), + (0x118B1, 0x118D1), + (0x118B2, 0x118D2), + (0x118B3, 0x118D3), + (0x118B4, 0x118D4), + (0x118B5, 0x118D5), + (0x118B6, 0x118D6), + (0x118B7, 0x118D7), + (0x118B8, 0x118D8), + (0x118B9, 0x118D9), + (0x118BA, 0x118DA), + (0x118BB, 0x118DB), + (0x118BC, 0x118DC), + (0x118BD, 0x118DD), + (0x118BE, 0x118DE), + (0x118BF, 0x118DF), + (0x16E40, 0x16E60), + (0x16E41, 0x16E61), + (0x16E42, 0x16E62), + (0x16E43, 0x16E63), + (0x16E44, 0x16E64), + (0x16E45, 0x16E65), + (0x16E46, 0x16E66), + (0x16E47, 0x16E67), + (0x16E48, 0x16E68), + (0x16E49, 0x16E69), + (0x16E4A, 0x16E6A), + (0x16E4B, 0x16E6B), + (0x16E4C, 0x16E6C), + (0x16E4D, 0x16E6D), + (0x16E4E, 0x16E6E), + (0x16E4F, 0x16E6F), + (0x16E50, 0x16E70), + (0x16E51, 0x16E71), + (0x16E52, 0x16E72), + (0x16E53, 0x16E73), + (0x16E54, 0x16E74), + (0x16E55, 0x16E75), + (0x16E56, 0x16E76), + (0x16E57, 0x16E77), + (0x16E58, 0x16E78), + (0x16E59, 0x16E79), + (0x16E5A, 0x16E7A), + (0x16E5B, 0x16E7B), + (0x16E5C, 0x16E7C), + (0x16E5D, 0x16E7D), + (0x16E5E, 0x16E7E), + (0x16E5F, 0x16E7F), + (0x1E900, 0x1E922), + (0x1E901, 0x1E923), + (0x1E902, 0x1E924), + (0x1E903, 0x1E925), + (0x1E904, 0x1E926), + (0x1E905, 0x1E927), + (0x1E906, 0x1E928), + (0x1E907, 0x1E929), + (0x1E908, 0x1E92A), + (0x1E909, 0x1E92B), + (0x1E90A, 0x1E92C), + (0x1E90B, 0x1E92D), + (0x1E90C, 0x1E92E), + (0x1E90D, 0x1E92F), + (0x1E90E, 0x1E930), + (0x1E90F, 0x1E931), + (0x1E910, 0x1E932), + (0x1E911, 0x1E933), + (0x1E912, 0x1E934), + (0x1E913, 0x1E935), + (0x1E914, 0x1E936), + (0x1E915, 0x1E937), + (0x1E916, 0x1E938), + (0x1E917, 0x1E939), + (0x1E918, 0x1E93A), + (0x1E919, 0x1E93B), + (0x1E91A, 0x1E93C), + (0x1E91B, 0x1E93D), + (0x1E91C, 0x1E93E), + (0x1E91D, 0x1E93F), + (0x1E91E, 0x1E940), + (0x1E91F, 0x1E941), + (0x1E920, 0x1E942), + (0x1E921, 0x1E943), +] diff --git a/crates/sqlbuild-core/src/text/re_ignorecase_keys/unicode_16_0_0.in b/crates/sqlbuild-core/src/text/re_ignorecase_keys/unicode_16_0_0.in new file mode 100644 index 0000000000..23702337b4 --- /dev/null +++ b/crates/sqlbuild-core/src/text/re_ignorecase_keys/unicode_16_0_0.in @@ -0,0 +1,1490 @@ +// Generated by `scripts/generate_python_char_table.py`; do not edit. +// Every character whose `re.IGNORECASE` match key is not itself in Unicode 16.0.0, in code point order. +&[ + (0x0041, 0x0061), + (0x0042, 0x0062), + (0x0043, 0x0063), + (0x0044, 0x0064), + (0x0045, 0x0065), + (0x0046, 0x0066), + (0x0047, 0x0067), + (0x0048, 0x0068), + (0x0049, 0x0069), + (0x004A, 0x006A), + (0x004B, 0x006B), + (0x004C, 0x006C), + (0x004D, 0x006D), + (0x004E, 0x006E), + (0x004F, 0x006F), + (0x0050, 0x0070), + (0x0051, 0x0071), + (0x0052, 0x0072), + (0x0053, 0x0073), + (0x0054, 0x0074), + (0x0055, 0x0075), + (0x0056, 0x0076), + (0x0057, 0x0077), + (0x0058, 0x0078), + (0x0059, 0x0079), + (0x005A, 0x007A), + (0x00C0, 0x00E0), + (0x00C1, 0x00E1), + (0x00C2, 0x00E2), + (0x00C3, 0x00E3), + (0x00C4, 0x00E4), + (0x00C5, 0x00E5), + (0x00C6, 0x00E6), + (0x00C7, 0x00E7), + (0x00C8, 0x00E8), + (0x00C9, 0x00E9), + (0x00CA, 0x00EA), + (0x00CB, 0x00EB), + (0x00CC, 0x00EC), + (0x00CD, 0x00ED), + (0x00CE, 0x00EE), + (0x00CF, 0x00EF), + (0x00D0, 0x00F0), + (0x00D1, 0x00F1), + (0x00D2, 0x00F2), + (0x00D3, 0x00F3), + (0x00D4, 0x00F4), + (0x00D5, 0x00F5), + (0x00D6, 0x00F6), + (0x00D8, 0x00F8), + (0x00D9, 0x00F9), + (0x00DA, 0x00FA), + (0x00DB, 0x00FB), + (0x00DC, 0x00FC), + (0x00DD, 0x00FD), + (0x00DE, 0x00FE), + (0x0100, 0x0101), + (0x0102, 0x0103), + (0x0104, 0x0105), + (0x0106, 0x0107), + (0x0108, 0x0109), + (0x010A, 0x010B), + (0x010C, 0x010D), + (0x010E, 0x010F), + (0x0110, 0x0111), + (0x0112, 0x0113), + (0x0114, 0x0115), + (0x0116, 0x0117), + (0x0118, 0x0119), + (0x011A, 0x011B), + (0x011C, 0x011D), + (0x011E, 0x011F), + (0x0120, 0x0121), + (0x0122, 0x0123), + (0x0124, 0x0125), + (0x0126, 0x0127), + (0x0128, 0x0129), + (0x012A, 0x012B), + (0x012C, 0x012D), + (0x012E, 0x012F), + (0x0130, 0x0069), + (0x0131, 0x0069), + (0x0132, 0x0133), + (0x0134, 0x0135), + (0x0136, 0x0137), + (0x0139, 0x013A), + (0x013B, 0x013C), + (0x013D, 0x013E), + (0x013F, 0x0140), + (0x0141, 0x0142), + (0x0143, 0x0144), + (0x0145, 0x0146), + (0x0147, 0x0148), + (0x014A, 0x014B), + (0x014C, 0x014D), + (0x014E, 0x014F), + (0x0150, 0x0151), + (0x0152, 0x0153), + (0x0154, 0x0155), + (0x0156, 0x0157), + (0x0158, 0x0159), + (0x015A, 0x015B), + (0x015C, 0x015D), + (0x015E, 0x015F), + (0x0160, 0x0161), + (0x0162, 0x0163), + (0x0164, 0x0165), + (0x0166, 0x0167), + (0x0168, 0x0169), + (0x016A, 0x016B), + (0x016C, 0x016D), + (0x016E, 0x016F), + (0x0170, 0x0171), + (0x0172, 0x0173), + (0x0174, 0x0175), + (0x0176, 0x0177), + (0x0178, 0x00FF), + (0x0179, 0x017A), + (0x017B, 0x017C), + (0x017D, 0x017E), + (0x017F, 0x0073), + (0x0181, 0x0253), + (0x0182, 0x0183), + (0x0184, 0x0185), + (0x0186, 0x0254), + (0x0187, 0x0188), + (0x0189, 0x0256), + (0x018A, 0x0257), + (0x018B, 0x018C), + (0x018E, 0x01DD), + (0x018F, 0x0259), + (0x0190, 0x025B), + (0x0191, 0x0192), + (0x0193, 0x0260), + (0x0194, 0x0263), + (0x0196, 0x0269), + (0x0197, 0x0268), + (0x0198, 0x0199), + (0x019C, 0x026F), + (0x019D, 0x0272), + (0x019F, 0x0275), + (0x01A0, 0x01A1), + (0x01A2, 0x01A3), + (0x01A4, 0x01A5), + (0x01A6, 0x0280), + (0x01A7, 0x01A8), + (0x01A9, 0x0283), + (0x01AC, 0x01AD), + (0x01AE, 0x0288), + (0x01AF, 0x01B0), + (0x01B1, 0x028A), + (0x01B2, 0x028B), + (0x01B3, 0x01B4), + (0x01B5, 0x01B6), + (0x01B7, 0x0292), + (0x01B8, 0x01B9), + (0x01BC, 0x01BD), + (0x01C4, 0x01C6), + (0x01C5, 0x01C6), + (0x01C7, 0x01C9), + (0x01C8, 0x01C9), + (0x01CA, 0x01CC), + (0x01CB, 0x01CC), + (0x01CD, 0x01CE), + (0x01CF, 0x01D0), + (0x01D1, 0x01D2), + (0x01D3, 0x01D4), + (0x01D5, 0x01D6), + (0x01D7, 0x01D8), + (0x01D9, 0x01DA), + (0x01DB, 0x01DC), + (0x01DE, 0x01DF), + (0x01E0, 0x01E1), + (0x01E2, 0x01E3), + (0x01E4, 0x01E5), + (0x01E6, 0x01E7), + (0x01E8, 0x01E9), + (0x01EA, 0x01EB), + (0x01EC, 0x01ED), + (0x01EE, 0x01EF), + (0x01F1, 0x01F3), + (0x01F2, 0x01F3), + (0x01F4, 0x01F5), + (0x01F6, 0x0195), + (0x01F7, 0x01BF), + (0x01F8, 0x01F9), + (0x01FA, 0x01FB), + (0x01FC, 0x01FD), + (0x01FE, 0x01FF), + (0x0200, 0x0201), + (0x0202, 0x0203), + (0x0204, 0x0205), + (0x0206, 0x0207), + (0x0208, 0x0209), + (0x020A, 0x020B), + (0x020C, 0x020D), + (0x020E, 0x020F), + (0x0210, 0x0211), + (0x0212, 0x0213), + (0x0214, 0x0215), + (0x0216, 0x0217), + (0x0218, 0x0219), + (0x021A, 0x021B), + (0x021C, 0x021D), + (0x021E, 0x021F), + (0x0220, 0x019E), + (0x0222, 0x0223), + (0x0224, 0x0225), + (0x0226, 0x0227), + (0x0228, 0x0229), + (0x022A, 0x022B), + (0x022C, 0x022D), + (0x022E, 0x022F), + (0x0230, 0x0231), + (0x0232, 0x0233), + (0x023A, 0x2C65), + (0x023B, 0x023C), + (0x023D, 0x019A), + (0x023E, 0x2C66), + (0x0241, 0x0242), + (0x0243, 0x0180), + (0x0244, 0x0289), + (0x0245, 0x028C), + (0x0246, 0x0247), + (0x0248, 0x0249), + (0x024A, 0x024B), + (0x024C, 0x024D), + (0x024E, 0x024F), + (0x0370, 0x0371), + (0x0372, 0x0373), + (0x0376, 0x0377), + (0x037F, 0x03F3), + (0x0386, 0x03AC), + (0x0388, 0x03AD), + (0x0389, 0x03AE), + (0x038A, 0x03AF), + (0x038C, 0x03CC), + (0x038E, 0x03CD), + (0x038F, 0x03CE), + (0x0391, 0x03B1), + (0x0392, 0x03B2), + (0x0393, 0x03B3), + (0x0394, 0x03B4), + (0x0395, 0x03B5), + (0x0396, 0x03B6), + (0x0397, 0x03B7), + (0x0398, 0x03B8), + (0x0399, 0x0345), + (0x039A, 0x03BA), + (0x039B, 0x03BB), + (0x039C, 0x00B5), + (0x039D, 0x03BD), + (0x039E, 0x03BE), + (0x039F, 0x03BF), + (0x03A0, 0x03C0), + (0x03A1, 0x03C1), + (0x03A3, 0x03C2), + (0x03A4, 0x03C4), + (0x03A5, 0x03C5), + (0x03A6, 0x03C6), + (0x03A7, 0x03C7), + (0x03A8, 0x03C8), + (0x03A9, 0x03C9), + (0x03AA, 0x03CA), + (0x03AB, 0x03CB), + (0x03B9, 0x0345), + (0x03BC, 0x00B5), + (0x03C3, 0x03C2), + (0x03CF, 0x03D7), + (0x03D0, 0x03B2), + (0x03D1, 0x03B8), + (0x03D5, 0x03C6), + (0x03D6, 0x03C0), + (0x03D8, 0x03D9), + (0x03DA, 0x03DB), + (0x03DC, 0x03DD), + (0x03DE, 0x03DF), + (0x03E0, 0x03E1), + (0x03E2, 0x03E3), + (0x03E4, 0x03E5), + (0x03E6, 0x03E7), + (0x03E8, 0x03E9), + (0x03EA, 0x03EB), + (0x03EC, 0x03ED), + (0x03EE, 0x03EF), + (0x03F0, 0x03BA), + (0x03F1, 0x03C1), + (0x03F4, 0x03B8), + (0x03F5, 0x03B5), + (0x03F7, 0x03F8), + (0x03F9, 0x03F2), + (0x03FA, 0x03FB), + (0x03FD, 0x037B), + (0x03FE, 0x037C), + (0x03FF, 0x037D), + (0x0400, 0x0450), + (0x0401, 0x0451), + (0x0402, 0x0452), + (0x0403, 0x0453), + (0x0404, 0x0454), + (0x0405, 0x0455), + (0x0406, 0x0456), + (0x0407, 0x0457), + (0x0408, 0x0458), + (0x0409, 0x0459), + (0x040A, 0x045A), + (0x040B, 0x045B), + (0x040C, 0x045C), + (0x040D, 0x045D), + (0x040E, 0x045E), + (0x040F, 0x045F), + (0x0410, 0x0430), + (0x0411, 0x0431), + (0x0412, 0x0432), + (0x0413, 0x0433), + (0x0414, 0x0434), + (0x0415, 0x0435), + (0x0416, 0x0436), + (0x0417, 0x0437), + (0x0418, 0x0438), + (0x0419, 0x0439), + (0x041A, 0x043A), + (0x041B, 0x043B), + (0x041C, 0x043C), + (0x041D, 0x043D), + (0x041E, 0x043E), + (0x041F, 0x043F), + (0x0420, 0x0440), + (0x0421, 0x0441), + (0x0422, 0x0442), + (0x0423, 0x0443), + (0x0424, 0x0444), + (0x0425, 0x0445), + (0x0426, 0x0446), + (0x0427, 0x0447), + (0x0428, 0x0448), + (0x0429, 0x0449), + (0x042A, 0x044A), + (0x042B, 0x044B), + (0x042C, 0x044C), + (0x042D, 0x044D), + (0x042E, 0x044E), + (0x042F, 0x044F), + (0x0460, 0x0461), + (0x0462, 0x0463), + (0x0464, 0x0465), + (0x0466, 0x0467), + (0x0468, 0x0469), + (0x046A, 0x046B), + (0x046C, 0x046D), + (0x046E, 0x046F), + (0x0470, 0x0471), + (0x0472, 0x0473), + (0x0474, 0x0475), + (0x0476, 0x0477), + (0x0478, 0x0479), + (0x047A, 0x047B), + (0x047C, 0x047D), + (0x047E, 0x047F), + (0x0480, 0x0481), + (0x048A, 0x048B), + (0x048C, 0x048D), + (0x048E, 0x048F), + (0x0490, 0x0491), + (0x0492, 0x0493), + (0x0494, 0x0495), + (0x0496, 0x0497), + (0x0498, 0x0499), + (0x049A, 0x049B), + (0x049C, 0x049D), + (0x049E, 0x049F), + (0x04A0, 0x04A1), + (0x04A2, 0x04A3), + (0x04A4, 0x04A5), + (0x04A6, 0x04A7), + (0x04A8, 0x04A9), + (0x04AA, 0x04AB), + (0x04AC, 0x04AD), + (0x04AE, 0x04AF), + (0x04B0, 0x04B1), + (0x04B2, 0x04B3), + (0x04B4, 0x04B5), + (0x04B6, 0x04B7), + (0x04B8, 0x04B9), + (0x04BA, 0x04BB), + (0x04BC, 0x04BD), + (0x04BE, 0x04BF), + (0x04C0, 0x04CF), + (0x04C1, 0x04C2), + (0x04C3, 0x04C4), + (0x04C5, 0x04C6), + (0x04C7, 0x04C8), + (0x04C9, 0x04CA), + (0x04CB, 0x04CC), + (0x04CD, 0x04CE), + (0x04D0, 0x04D1), + (0x04D2, 0x04D3), + (0x04D4, 0x04D5), + (0x04D6, 0x04D7), + (0x04D8, 0x04D9), + (0x04DA, 0x04DB), + (0x04DC, 0x04DD), + (0x04DE, 0x04DF), + (0x04E0, 0x04E1), + (0x04E2, 0x04E3), + (0x04E4, 0x04E5), + (0x04E6, 0x04E7), + (0x04E8, 0x04E9), + (0x04EA, 0x04EB), + (0x04EC, 0x04ED), + (0x04EE, 0x04EF), + (0x04F0, 0x04F1), + (0x04F2, 0x04F3), + (0x04F4, 0x04F5), + (0x04F6, 0x04F7), + (0x04F8, 0x04F9), + (0x04FA, 0x04FB), + (0x04FC, 0x04FD), + (0x04FE, 0x04FF), + (0x0500, 0x0501), + (0x0502, 0x0503), + (0x0504, 0x0505), + (0x0506, 0x0507), + (0x0508, 0x0509), + (0x050A, 0x050B), + (0x050C, 0x050D), + (0x050E, 0x050F), + (0x0510, 0x0511), + (0x0512, 0x0513), + (0x0514, 0x0515), + (0x0516, 0x0517), + (0x0518, 0x0519), + (0x051A, 0x051B), + (0x051C, 0x051D), + (0x051E, 0x051F), + (0x0520, 0x0521), + (0x0522, 0x0523), + (0x0524, 0x0525), + (0x0526, 0x0527), + (0x0528, 0x0529), + (0x052A, 0x052B), + (0x052C, 0x052D), + (0x052E, 0x052F), + (0x0531, 0x0561), + (0x0532, 0x0562), + (0x0533, 0x0563), + (0x0534, 0x0564), + (0x0535, 0x0565), + (0x0536, 0x0566), + (0x0537, 0x0567), + (0x0538, 0x0568), + (0x0539, 0x0569), + (0x053A, 0x056A), + (0x053B, 0x056B), + (0x053C, 0x056C), + (0x053D, 0x056D), + (0x053E, 0x056E), + (0x053F, 0x056F), + (0x0540, 0x0570), + (0x0541, 0x0571), + (0x0542, 0x0572), + (0x0543, 0x0573), + (0x0544, 0x0574), + (0x0545, 0x0575), + (0x0546, 0x0576), + (0x0547, 0x0577), + (0x0548, 0x0578), + (0x0549, 0x0579), + (0x054A, 0x057A), + (0x054B, 0x057B), + (0x054C, 0x057C), + (0x054D, 0x057D), + (0x054E, 0x057E), + (0x054F, 0x057F), + (0x0550, 0x0580), + (0x0551, 0x0581), + (0x0552, 0x0582), + (0x0553, 0x0583), + (0x0554, 0x0584), + (0x0555, 0x0585), + (0x0556, 0x0586), + (0x10A0, 0x2D00), + (0x10A1, 0x2D01), + (0x10A2, 0x2D02), + (0x10A3, 0x2D03), + (0x10A4, 0x2D04), + (0x10A5, 0x2D05), + (0x10A6, 0x2D06), + (0x10A7, 0x2D07), + (0x10A8, 0x2D08), + (0x10A9, 0x2D09), + (0x10AA, 0x2D0A), + (0x10AB, 0x2D0B), + (0x10AC, 0x2D0C), + (0x10AD, 0x2D0D), + (0x10AE, 0x2D0E), + (0x10AF, 0x2D0F), + (0x10B0, 0x2D10), + (0x10B1, 0x2D11), + (0x10B2, 0x2D12), + (0x10B3, 0x2D13), + (0x10B4, 0x2D14), + (0x10B5, 0x2D15), + (0x10B6, 0x2D16), + (0x10B7, 0x2D17), + (0x10B8, 0x2D18), + (0x10B9, 0x2D19), + (0x10BA, 0x2D1A), + (0x10BB, 0x2D1B), + (0x10BC, 0x2D1C), + (0x10BD, 0x2D1D), + (0x10BE, 0x2D1E), + (0x10BF, 0x2D1F), + (0x10C0, 0x2D20), + (0x10C1, 0x2D21), + (0x10C2, 0x2D22), + (0x10C3, 0x2D23), + (0x10C4, 0x2D24), + (0x10C5, 0x2D25), + (0x10C7, 0x2D27), + (0x10CD, 0x2D2D), + (0x13A0, 0xAB70), + (0x13A1, 0xAB71), + (0x13A2, 0xAB72), + (0x13A3, 0xAB73), + (0x13A4, 0xAB74), + (0x13A5, 0xAB75), + (0x13A6, 0xAB76), + (0x13A7, 0xAB77), + (0x13A8, 0xAB78), + (0x13A9, 0xAB79), + (0x13AA, 0xAB7A), + (0x13AB, 0xAB7B), + (0x13AC, 0xAB7C), + (0x13AD, 0xAB7D), + (0x13AE, 0xAB7E), + (0x13AF, 0xAB7F), + (0x13B0, 0xAB80), + (0x13B1, 0xAB81), + (0x13B2, 0xAB82), + (0x13B3, 0xAB83), + (0x13B4, 0xAB84), + (0x13B5, 0xAB85), + (0x13B6, 0xAB86), + (0x13B7, 0xAB87), + (0x13B8, 0xAB88), + (0x13B9, 0xAB89), + (0x13BA, 0xAB8A), + (0x13BB, 0xAB8B), + (0x13BC, 0xAB8C), + (0x13BD, 0xAB8D), + (0x13BE, 0xAB8E), + (0x13BF, 0xAB8F), + (0x13C0, 0xAB90), + (0x13C1, 0xAB91), + (0x13C2, 0xAB92), + (0x13C3, 0xAB93), + (0x13C4, 0xAB94), + (0x13C5, 0xAB95), + (0x13C6, 0xAB96), + (0x13C7, 0xAB97), + (0x13C8, 0xAB98), + (0x13C9, 0xAB99), + (0x13CA, 0xAB9A), + (0x13CB, 0xAB9B), + (0x13CC, 0xAB9C), + (0x13CD, 0xAB9D), + (0x13CE, 0xAB9E), + (0x13CF, 0xAB9F), + (0x13D0, 0xABA0), + (0x13D1, 0xABA1), + (0x13D2, 0xABA2), + (0x13D3, 0xABA3), + (0x13D4, 0xABA4), + (0x13D5, 0xABA5), + (0x13D6, 0xABA6), + (0x13D7, 0xABA7), + (0x13D8, 0xABA8), + (0x13D9, 0xABA9), + (0x13DA, 0xABAA), + (0x13DB, 0xABAB), + (0x13DC, 0xABAC), + (0x13DD, 0xABAD), + (0x13DE, 0xABAE), + (0x13DF, 0xABAF), + (0x13E0, 0xABB0), + (0x13E1, 0xABB1), + (0x13E2, 0xABB2), + (0x13E3, 0xABB3), + (0x13E4, 0xABB4), + (0x13E5, 0xABB5), + (0x13E6, 0xABB6), + (0x13E7, 0xABB7), + (0x13E8, 0xABB8), + (0x13E9, 0xABB9), + (0x13EA, 0xABBA), + (0x13EB, 0xABBB), + (0x13EC, 0xABBC), + (0x13ED, 0xABBD), + (0x13EE, 0xABBE), + (0x13EF, 0xABBF), + (0x13F0, 0x13F8), + (0x13F1, 0x13F9), + (0x13F2, 0x13FA), + (0x13F3, 0x13FB), + (0x13F4, 0x13FC), + (0x13F5, 0x13FD), + (0x1C80, 0x0432), + (0x1C81, 0x0434), + (0x1C82, 0x043E), + (0x1C83, 0x0441), + (0x1C84, 0x0442), + (0x1C85, 0x0442), + (0x1C86, 0x044A), + (0x1C87, 0x0463), + (0x1C89, 0x1C8A), + (0x1C90, 0x10D0), + (0x1C91, 0x10D1), + (0x1C92, 0x10D2), + (0x1C93, 0x10D3), + (0x1C94, 0x10D4), + (0x1C95, 0x10D5), + (0x1C96, 0x10D6), + (0x1C97, 0x10D7), + (0x1C98, 0x10D8), + (0x1C99, 0x10D9), + (0x1C9A, 0x10DA), + (0x1C9B, 0x10DB), + (0x1C9C, 0x10DC), + (0x1C9D, 0x10DD), + (0x1C9E, 0x10DE), + (0x1C9F, 0x10DF), + (0x1CA0, 0x10E0), + (0x1CA1, 0x10E1), + (0x1CA2, 0x10E2), + (0x1CA3, 0x10E3), + (0x1CA4, 0x10E4), + (0x1CA5, 0x10E5), + (0x1CA6, 0x10E6), + (0x1CA7, 0x10E7), + (0x1CA8, 0x10E8), + (0x1CA9, 0x10E9), + (0x1CAA, 0x10EA), + (0x1CAB, 0x10EB), + (0x1CAC, 0x10EC), + (0x1CAD, 0x10ED), + (0x1CAE, 0x10EE), + (0x1CAF, 0x10EF), + (0x1CB0, 0x10F0), + (0x1CB1, 0x10F1), + (0x1CB2, 0x10F2), + (0x1CB3, 0x10F3), + (0x1CB4, 0x10F4), + (0x1CB5, 0x10F5), + (0x1CB6, 0x10F6), + (0x1CB7, 0x10F7), + (0x1CB8, 0x10F8), + (0x1CB9, 0x10F9), + (0x1CBA, 0x10FA), + (0x1CBD, 0x10FD), + (0x1CBE, 0x10FE), + (0x1CBF, 0x10FF), + (0x1E00, 0x1E01), + (0x1E02, 0x1E03), + (0x1E04, 0x1E05), + (0x1E06, 0x1E07), + (0x1E08, 0x1E09), + (0x1E0A, 0x1E0B), + (0x1E0C, 0x1E0D), + (0x1E0E, 0x1E0F), + (0x1E10, 0x1E11), + (0x1E12, 0x1E13), + (0x1E14, 0x1E15), + (0x1E16, 0x1E17), + (0x1E18, 0x1E19), + (0x1E1A, 0x1E1B), + (0x1E1C, 0x1E1D), + (0x1E1E, 0x1E1F), + (0x1E20, 0x1E21), + (0x1E22, 0x1E23), + (0x1E24, 0x1E25), + (0x1E26, 0x1E27), + (0x1E28, 0x1E29), + (0x1E2A, 0x1E2B), + (0x1E2C, 0x1E2D), + (0x1E2E, 0x1E2F), + (0x1E30, 0x1E31), + (0x1E32, 0x1E33), + (0x1E34, 0x1E35), + (0x1E36, 0x1E37), + (0x1E38, 0x1E39), + (0x1E3A, 0x1E3B), + (0x1E3C, 0x1E3D), + (0x1E3E, 0x1E3F), + (0x1E40, 0x1E41), + (0x1E42, 0x1E43), + (0x1E44, 0x1E45), + (0x1E46, 0x1E47), + (0x1E48, 0x1E49), + (0x1E4A, 0x1E4B), + (0x1E4C, 0x1E4D), + (0x1E4E, 0x1E4F), + (0x1E50, 0x1E51), + (0x1E52, 0x1E53), + (0x1E54, 0x1E55), + (0x1E56, 0x1E57), + (0x1E58, 0x1E59), + (0x1E5A, 0x1E5B), + (0x1E5C, 0x1E5D), + (0x1E5E, 0x1E5F), + (0x1E60, 0x1E61), + (0x1E62, 0x1E63), + (0x1E64, 0x1E65), + (0x1E66, 0x1E67), + (0x1E68, 0x1E69), + (0x1E6A, 0x1E6B), + (0x1E6C, 0x1E6D), + (0x1E6E, 0x1E6F), + (0x1E70, 0x1E71), + (0x1E72, 0x1E73), + (0x1E74, 0x1E75), + (0x1E76, 0x1E77), + (0x1E78, 0x1E79), + (0x1E7A, 0x1E7B), + (0x1E7C, 0x1E7D), + (0x1E7E, 0x1E7F), + (0x1E80, 0x1E81), + (0x1E82, 0x1E83), + (0x1E84, 0x1E85), + (0x1E86, 0x1E87), + (0x1E88, 0x1E89), + (0x1E8A, 0x1E8B), + (0x1E8C, 0x1E8D), + (0x1E8E, 0x1E8F), + (0x1E90, 0x1E91), + (0x1E92, 0x1E93), + (0x1E94, 0x1E95), + (0x1E9B, 0x1E61), + (0x1E9E, 0x00DF), + (0x1EA0, 0x1EA1), + (0x1EA2, 0x1EA3), + (0x1EA4, 0x1EA5), + (0x1EA6, 0x1EA7), + (0x1EA8, 0x1EA9), + (0x1EAA, 0x1EAB), + (0x1EAC, 0x1EAD), + (0x1EAE, 0x1EAF), + (0x1EB0, 0x1EB1), + (0x1EB2, 0x1EB3), + (0x1EB4, 0x1EB5), + (0x1EB6, 0x1EB7), + (0x1EB8, 0x1EB9), + (0x1EBA, 0x1EBB), + (0x1EBC, 0x1EBD), + (0x1EBE, 0x1EBF), + (0x1EC0, 0x1EC1), + (0x1EC2, 0x1EC3), + (0x1EC4, 0x1EC5), + (0x1EC6, 0x1EC7), + (0x1EC8, 0x1EC9), + (0x1ECA, 0x1ECB), + (0x1ECC, 0x1ECD), + (0x1ECE, 0x1ECF), + (0x1ED0, 0x1ED1), + (0x1ED2, 0x1ED3), + (0x1ED4, 0x1ED5), + (0x1ED6, 0x1ED7), + (0x1ED8, 0x1ED9), + (0x1EDA, 0x1EDB), + (0x1EDC, 0x1EDD), + (0x1EDE, 0x1EDF), + (0x1EE0, 0x1EE1), + (0x1EE2, 0x1EE3), + (0x1EE4, 0x1EE5), + (0x1EE6, 0x1EE7), + (0x1EE8, 0x1EE9), + (0x1EEA, 0x1EEB), + (0x1EEC, 0x1EED), + (0x1EEE, 0x1EEF), + (0x1EF0, 0x1EF1), + (0x1EF2, 0x1EF3), + (0x1EF4, 0x1EF5), + (0x1EF6, 0x1EF7), + (0x1EF8, 0x1EF9), + (0x1EFA, 0x1EFB), + (0x1EFC, 0x1EFD), + (0x1EFE, 0x1EFF), + (0x1F08, 0x1F00), + (0x1F09, 0x1F01), + (0x1F0A, 0x1F02), + (0x1F0B, 0x1F03), + (0x1F0C, 0x1F04), + (0x1F0D, 0x1F05), + (0x1F0E, 0x1F06), + (0x1F0F, 0x1F07), + (0x1F18, 0x1F10), + (0x1F19, 0x1F11), + (0x1F1A, 0x1F12), + (0x1F1B, 0x1F13), + (0x1F1C, 0x1F14), + (0x1F1D, 0x1F15), + (0x1F28, 0x1F20), + (0x1F29, 0x1F21), + (0x1F2A, 0x1F22), + (0x1F2B, 0x1F23), + (0x1F2C, 0x1F24), + (0x1F2D, 0x1F25), + (0x1F2E, 0x1F26), + (0x1F2F, 0x1F27), + (0x1F38, 0x1F30), + (0x1F39, 0x1F31), + (0x1F3A, 0x1F32), + (0x1F3B, 0x1F33), + (0x1F3C, 0x1F34), + (0x1F3D, 0x1F35), + (0x1F3E, 0x1F36), + (0x1F3F, 0x1F37), + (0x1F48, 0x1F40), + (0x1F49, 0x1F41), + (0x1F4A, 0x1F42), + (0x1F4B, 0x1F43), + (0x1F4C, 0x1F44), + (0x1F4D, 0x1F45), + (0x1F59, 0x1F51), + (0x1F5B, 0x1F53), + (0x1F5D, 0x1F55), + (0x1F5F, 0x1F57), + (0x1F68, 0x1F60), + (0x1F69, 0x1F61), + (0x1F6A, 0x1F62), + (0x1F6B, 0x1F63), + (0x1F6C, 0x1F64), + (0x1F6D, 0x1F65), + (0x1F6E, 0x1F66), + (0x1F6F, 0x1F67), + (0x1F88, 0x1F80), + (0x1F89, 0x1F81), + (0x1F8A, 0x1F82), + (0x1F8B, 0x1F83), + (0x1F8C, 0x1F84), + (0x1F8D, 0x1F85), + (0x1F8E, 0x1F86), + (0x1F8F, 0x1F87), + (0x1F98, 0x1F90), + (0x1F99, 0x1F91), + (0x1F9A, 0x1F92), + (0x1F9B, 0x1F93), + (0x1F9C, 0x1F94), + (0x1F9D, 0x1F95), + (0x1F9E, 0x1F96), + (0x1F9F, 0x1F97), + (0x1FA8, 0x1FA0), + (0x1FA9, 0x1FA1), + (0x1FAA, 0x1FA2), + (0x1FAB, 0x1FA3), + (0x1FAC, 0x1FA4), + (0x1FAD, 0x1FA5), + (0x1FAE, 0x1FA6), + (0x1FAF, 0x1FA7), + (0x1FB8, 0x1FB0), + (0x1FB9, 0x1FB1), + (0x1FBA, 0x1F70), + (0x1FBB, 0x1F71), + (0x1FBC, 0x1FB3), + (0x1FBE, 0x0345), + (0x1FC8, 0x1F72), + (0x1FC9, 0x1F73), + (0x1FCA, 0x1F74), + (0x1FCB, 0x1F75), + (0x1FCC, 0x1FC3), + (0x1FD3, 0x0390), + (0x1FD8, 0x1FD0), + (0x1FD9, 0x1FD1), + (0x1FDA, 0x1F76), + (0x1FDB, 0x1F77), + (0x1FE3, 0x03B0), + (0x1FE8, 0x1FE0), + (0x1FE9, 0x1FE1), + (0x1FEA, 0x1F7A), + (0x1FEB, 0x1F7B), + (0x1FEC, 0x1FE5), + (0x1FF8, 0x1F78), + (0x1FF9, 0x1F79), + (0x1FFA, 0x1F7C), + (0x1FFB, 0x1F7D), + (0x1FFC, 0x1FF3), + (0x2126, 0x03C9), + (0x212A, 0x006B), + (0x212B, 0x00E5), + (0x2132, 0x214E), + (0x2160, 0x2170), + (0x2161, 0x2171), + (0x2162, 0x2172), + (0x2163, 0x2173), + (0x2164, 0x2174), + (0x2165, 0x2175), + (0x2166, 0x2176), + (0x2167, 0x2177), + (0x2168, 0x2178), + (0x2169, 0x2179), + (0x216A, 0x217A), + (0x216B, 0x217B), + (0x216C, 0x217C), + (0x216D, 0x217D), + (0x216E, 0x217E), + (0x216F, 0x217F), + (0x2183, 0x2184), + (0x24B6, 0x24D0), + (0x24B7, 0x24D1), + (0x24B8, 0x24D2), + (0x24B9, 0x24D3), + (0x24BA, 0x24D4), + (0x24BB, 0x24D5), + (0x24BC, 0x24D6), + (0x24BD, 0x24D7), + (0x24BE, 0x24D8), + (0x24BF, 0x24D9), + (0x24C0, 0x24DA), + (0x24C1, 0x24DB), + (0x24C2, 0x24DC), + (0x24C3, 0x24DD), + (0x24C4, 0x24DE), + (0x24C5, 0x24DF), + (0x24C6, 0x24E0), + (0x24C7, 0x24E1), + (0x24C8, 0x24E2), + (0x24C9, 0x24E3), + (0x24CA, 0x24E4), + (0x24CB, 0x24E5), + (0x24CC, 0x24E6), + (0x24CD, 0x24E7), + (0x24CE, 0x24E8), + (0x24CF, 0x24E9), + (0x2C00, 0x2C30), + (0x2C01, 0x2C31), + (0x2C02, 0x2C32), + (0x2C03, 0x2C33), + (0x2C04, 0x2C34), + (0x2C05, 0x2C35), + (0x2C06, 0x2C36), + (0x2C07, 0x2C37), + (0x2C08, 0x2C38), + (0x2C09, 0x2C39), + (0x2C0A, 0x2C3A), + (0x2C0B, 0x2C3B), + (0x2C0C, 0x2C3C), + (0x2C0D, 0x2C3D), + (0x2C0E, 0x2C3E), + (0x2C0F, 0x2C3F), + (0x2C10, 0x2C40), + (0x2C11, 0x2C41), + (0x2C12, 0x2C42), + (0x2C13, 0x2C43), + (0x2C14, 0x2C44), + (0x2C15, 0x2C45), + (0x2C16, 0x2C46), + (0x2C17, 0x2C47), + (0x2C18, 0x2C48), + (0x2C19, 0x2C49), + (0x2C1A, 0x2C4A), + (0x2C1B, 0x2C4B), + (0x2C1C, 0x2C4C), + (0x2C1D, 0x2C4D), + (0x2C1E, 0x2C4E), + (0x2C1F, 0x2C4F), + (0x2C20, 0x2C50), + (0x2C21, 0x2C51), + (0x2C22, 0x2C52), + (0x2C23, 0x2C53), + (0x2C24, 0x2C54), + (0x2C25, 0x2C55), + (0x2C26, 0x2C56), + (0x2C27, 0x2C57), + (0x2C28, 0x2C58), + (0x2C29, 0x2C59), + (0x2C2A, 0x2C5A), + (0x2C2B, 0x2C5B), + (0x2C2C, 0x2C5C), + (0x2C2D, 0x2C5D), + (0x2C2E, 0x2C5E), + (0x2C2F, 0x2C5F), + (0x2C60, 0x2C61), + (0x2C62, 0x026B), + (0x2C63, 0x1D7D), + (0x2C64, 0x027D), + (0x2C67, 0x2C68), + (0x2C69, 0x2C6A), + (0x2C6B, 0x2C6C), + (0x2C6D, 0x0251), + (0x2C6E, 0x0271), + (0x2C6F, 0x0250), + (0x2C70, 0x0252), + (0x2C72, 0x2C73), + (0x2C75, 0x2C76), + (0x2C7E, 0x023F), + (0x2C7F, 0x0240), + (0x2C80, 0x2C81), + (0x2C82, 0x2C83), + (0x2C84, 0x2C85), + (0x2C86, 0x2C87), + (0x2C88, 0x2C89), + (0x2C8A, 0x2C8B), + (0x2C8C, 0x2C8D), + (0x2C8E, 0x2C8F), + (0x2C90, 0x2C91), + (0x2C92, 0x2C93), + (0x2C94, 0x2C95), + (0x2C96, 0x2C97), + (0x2C98, 0x2C99), + (0x2C9A, 0x2C9B), + (0x2C9C, 0x2C9D), + (0x2C9E, 0x2C9F), + (0x2CA0, 0x2CA1), + (0x2CA2, 0x2CA3), + (0x2CA4, 0x2CA5), + (0x2CA6, 0x2CA7), + (0x2CA8, 0x2CA9), + (0x2CAA, 0x2CAB), + (0x2CAC, 0x2CAD), + (0x2CAE, 0x2CAF), + (0x2CB0, 0x2CB1), + (0x2CB2, 0x2CB3), + (0x2CB4, 0x2CB5), + (0x2CB6, 0x2CB7), + (0x2CB8, 0x2CB9), + (0x2CBA, 0x2CBB), + (0x2CBC, 0x2CBD), + (0x2CBE, 0x2CBF), + (0x2CC0, 0x2CC1), + (0x2CC2, 0x2CC3), + (0x2CC4, 0x2CC5), + (0x2CC6, 0x2CC7), + (0x2CC8, 0x2CC9), + (0x2CCA, 0x2CCB), + (0x2CCC, 0x2CCD), + (0x2CCE, 0x2CCF), + (0x2CD0, 0x2CD1), + (0x2CD2, 0x2CD3), + (0x2CD4, 0x2CD5), + (0x2CD6, 0x2CD7), + (0x2CD8, 0x2CD9), + (0x2CDA, 0x2CDB), + (0x2CDC, 0x2CDD), + (0x2CDE, 0x2CDF), + (0x2CE0, 0x2CE1), + (0x2CE2, 0x2CE3), + (0x2CEB, 0x2CEC), + (0x2CED, 0x2CEE), + (0x2CF2, 0x2CF3), + (0xA640, 0xA641), + (0xA642, 0xA643), + (0xA644, 0xA645), + (0xA646, 0xA647), + (0xA648, 0xA649), + (0xA64A, 0x1C88), + (0xA64B, 0x1C88), + (0xA64C, 0xA64D), + (0xA64E, 0xA64F), + (0xA650, 0xA651), + (0xA652, 0xA653), + (0xA654, 0xA655), + (0xA656, 0xA657), + (0xA658, 0xA659), + (0xA65A, 0xA65B), + (0xA65C, 0xA65D), + (0xA65E, 0xA65F), + (0xA660, 0xA661), + (0xA662, 0xA663), + (0xA664, 0xA665), + (0xA666, 0xA667), + (0xA668, 0xA669), + (0xA66A, 0xA66B), + (0xA66C, 0xA66D), + (0xA680, 0xA681), + (0xA682, 0xA683), + (0xA684, 0xA685), + (0xA686, 0xA687), + (0xA688, 0xA689), + (0xA68A, 0xA68B), + (0xA68C, 0xA68D), + (0xA68E, 0xA68F), + (0xA690, 0xA691), + (0xA692, 0xA693), + (0xA694, 0xA695), + (0xA696, 0xA697), + (0xA698, 0xA699), + (0xA69A, 0xA69B), + (0xA722, 0xA723), + (0xA724, 0xA725), + (0xA726, 0xA727), + (0xA728, 0xA729), + (0xA72A, 0xA72B), + (0xA72C, 0xA72D), + (0xA72E, 0xA72F), + (0xA732, 0xA733), + (0xA734, 0xA735), + (0xA736, 0xA737), + (0xA738, 0xA739), + (0xA73A, 0xA73B), + (0xA73C, 0xA73D), + (0xA73E, 0xA73F), + (0xA740, 0xA741), + (0xA742, 0xA743), + (0xA744, 0xA745), + (0xA746, 0xA747), + (0xA748, 0xA749), + (0xA74A, 0xA74B), + (0xA74C, 0xA74D), + (0xA74E, 0xA74F), + (0xA750, 0xA751), + (0xA752, 0xA753), + (0xA754, 0xA755), + (0xA756, 0xA757), + (0xA758, 0xA759), + (0xA75A, 0xA75B), + (0xA75C, 0xA75D), + (0xA75E, 0xA75F), + (0xA760, 0xA761), + (0xA762, 0xA763), + (0xA764, 0xA765), + (0xA766, 0xA767), + (0xA768, 0xA769), + (0xA76A, 0xA76B), + (0xA76C, 0xA76D), + (0xA76E, 0xA76F), + (0xA779, 0xA77A), + (0xA77B, 0xA77C), + (0xA77D, 0x1D79), + (0xA77E, 0xA77F), + (0xA780, 0xA781), + (0xA782, 0xA783), + (0xA784, 0xA785), + (0xA786, 0xA787), + (0xA78B, 0xA78C), + (0xA78D, 0x0265), + (0xA790, 0xA791), + (0xA792, 0xA793), + (0xA796, 0xA797), + (0xA798, 0xA799), + (0xA79A, 0xA79B), + (0xA79C, 0xA79D), + (0xA79E, 0xA79F), + (0xA7A0, 0xA7A1), + (0xA7A2, 0xA7A3), + (0xA7A4, 0xA7A5), + (0xA7A6, 0xA7A7), + (0xA7A8, 0xA7A9), + (0xA7AA, 0x0266), + (0xA7AB, 0x025C), + (0xA7AC, 0x0261), + (0xA7AD, 0x026C), + (0xA7AE, 0x026A), + (0xA7B0, 0x029E), + (0xA7B1, 0x0287), + (0xA7B2, 0x029D), + (0xA7B3, 0xAB53), + (0xA7B4, 0xA7B5), + (0xA7B6, 0xA7B7), + (0xA7B8, 0xA7B9), + (0xA7BA, 0xA7BB), + (0xA7BC, 0xA7BD), + (0xA7BE, 0xA7BF), + (0xA7C0, 0xA7C1), + (0xA7C2, 0xA7C3), + (0xA7C4, 0xA794), + (0xA7C5, 0x0282), + (0xA7C6, 0x1D8E), + (0xA7C7, 0xA7C8), + (0xA7C9, 0xA7CA), + (0xA7CB, 0x0264), + (0xA7CC, 0xA7CD), + (0xA7D0, 0xA7D1), + (0xA7D6, 0xA7D7), + (0xA7D8, 0xA7D9), + (0xA7DA, 0xA7DB), + (0xA7DC, 0x019B), + (0xA7F5, 0xA7F6), + (0xFB06, 0xFB05), + (0xFF21, 0xFF41), + (0xFF22, 0xFF42), + (0xFF23, 0xFF43), + (0xFF24, 0xFF44), + (0xFF25, 0xFF45), + (0xFF26, 0xFF46), + (0xFF27, 0xFF47), + (0xFF28, 0xFF48), + (0xFF29, 0xFF49), + (0xFF2A, 0xFF4A), + (0xFF2B, 0xFF4B), + (0xFF2C, 0xFF4C), + (0xFF2D, 0xFF4D), + (0xFF2E, 0xFF4E), + (0xFF2F, 0xFF4F), + (0xFF30, 0xFF50), + (0xFF31, 0xFF51), + (0xFF32, 0xFF52), + (0xFF33, 0xFF53), + (0xFF34, 0xFF54), + (0xFF35, 0xFF55), + (0xFF36, 0xFF56), + (0xFF37, 0xFF57), + (0xFF38, 0xFF58), + (0xFF39, 0xFF59), + (0xFF3A, 0xFF5A), + (0x10400, 0x10428), + (0x10401, 0x10429), + (0x10402, 0x1042A), + (0x10403, 0x1042B), + (0x10404, 0x1042C), + (0x10405, 0x1042D), + (0x10406, 0x1042E), + (0x10407, 0x1042F), + (0x10408, 0x10430), + (0x10409, 0x10431), + (0x1040A, 0x10432), + (0x1040B, 0x10433), + (0x1040C, 0x10434), + (0x1040D, 0x10435), + (0x1040E, 0x10436), + (0x1040F, 0x10437), + (0x10410, 0x10438), + (0x10411, 0x10439), + (0x10412, 0x1043A), + (0x10413, 0x1043B), + (0x10414, 0x1043C), + (0x10415, 0x1043D), + (0x10416, 0x1043E), + (0x10417, 0x1043F), + (0x10418, 0x10440), + (0x10419, 0x10441), + (0x1041A, 0x10442), + (0x1041B, 0x10443), + (0x1041C, 0x10444), + (0x1041D, 0x10445), + (0x1041E, 0x10446), + (0x1041F, 0x10447), + (0x10420, 0x10448), + (0x10421, 0x10449), + (0x10422, 0x1044A), + (0x10423, 0x1044B), + (0x10424, 0x1044C), + (0x10425, 0x1044D), + (0x10426, 0x1044E), + (0x10427, 0x1044F), + (0x104B0, 0x104D8), + (0x104B1, 0x104D9), + (0x104B2, 0x104DA), + (0x104B3, 0x104DB), + (0x104B4, 0x104DC), + (0x104B5, 0x104DD), + (0x104B6, 0x104DE), + (0x104B7, 0x104DF), + (0x104B8, 0x104E0), + (0x104B9, 0x104E1), + (0x104BA, 0x104E2), + (0x104BB, 0x104E3), + (0x104BC, 0x104E4), + (0x104BD, 0x104E5), + (0x104BE, 0x104E6), + (0x104BF, 0x104E7), + (0x104C0, 0x104E8), + (0x104C1, 0x104E9), + (0x104C2, 0x104EA), + (0x104C3, 0x104EB), + (0x104C4, 0x104EC), + (0x104C5, 0x104ED), + (0x104C6, 0x104EE), + (0x104C7, 0x104EF), + (0x104C8, 0x104F0), + (0x104C9, 0x104F1), + (0x104CA, 0x104F2), + (0x104CB, 0x104F3), + (0x104CC, 0x104F4), + (0x104CD, 0x104F5), + (0x104CE, 0x104F6), + (0x104CF, 0x104F7), + (0x104D0, 0x104F8), + (0x104D1, 0x104F9), + (0x104D2, 0x104FA), + (0x104D3, 0x104FB), + (0x10570, 0x10597), + (0x10571, 0x10598), + (0x10572, 0x10599), + (0x10573, 0x1059A), + (0x10574, 0x1059B), + (0x10575, 0x1059C), + (0x10576, 0x1059D), + (0x10577, 0x1059E), + (0x10578, 0x1059F), + (0x10579, 0x105A0), + (0x1057A, 0x105A1), + (0x1057C, 0x105A3), + (0x1057D, 0x105A4), + (0x1057E, 0x105A5), + (0x1057F, 0x105A6), + (0x10580, 0x105A7), + (0x10581, 0x105A8), + (0x10582, 0x105A9), + (0x10583, 0x105AA), + (0x10584, 0x105AB), + (0x10585, 0x105AC), + (0x10586, 0x105AD), + (0x10587, 0x105AE), + (0x10588, 0x105AF), + (0x10589, 0x105B0), + (0x1058A, 0x105B1), + (0x1058C, 0x105B3), + (0x1058D, 0x105B4), + (0x1058E, 0x105B5), + (0x1058F, 0x105B6), + (0x10590, 0x105B7), + (0x10591, 0x105B8), + (0x10592, 0x105B9), + (0x10594, 0x105BB), + (0x10595, 0x105BC), + (0x10C80, 0x10CC0), + (0x10C81, 0x10CC1), + (0x10C82, 0x10CC2), + (0x10C83, 0x10CC3), + (0x10C84, 0x10CC4), + (0x10C85, 0x10CC5), + (0x10C86, 0x10CC6), + (0x10C87, 0x10CC7), + (0x10C88, 0x10CC8), + (0x10C89, 0x10CC9), + (0x10C8A, 0x10CCA), + (0x10C8B, 0x10CCB), + (0x10C8C, 0x10CCC), + (0x10C8D, 0x10CCD), + (0x10C8E, 0x10CCE), + (0x10C8F, 0x10CCF), + (0x10C90, 0x10CD0), + (0x10C91, 0x10CD1), + (0x10C92, 0x10CD2), + (0x10C93, 0x10CD3), + (0x10C94, 0x10CD4), + (0x10C95, 0x10CD5), + (0x10C96, 0x10CD6), + (0x10C97, 0x10CD7), + (0x10C98, 0x10CD8), + (0x10C99, 0x10CD9), + (0x10C9A, 0x10CDA), + (0x10C9B, 0x10CDB), + (0x10C9C, 0x10CDC), + (0x10C9D, 0x10CDD), + (0x10C9E, 0x10CDE), + (0x10C9F, 0x10CDF), + (0x10CA0, 0x10CE0), + (0x10CA1, 0x10CE1), + (0x10CA2, 0x10CE2), + (0x10CA3, 0x10CE3), + (0x10CA4, 0x10CE4), + (0x10CA5, 0x10CE5), + (0x10CA6, 0x10CE6), + (0x10CA7, 0x10CE7), + (0x10CA8, 0x10CE8), + (0x10CA9, 0x10CE9), + (0x10CAA, 0x10CEA), + (0x10CAB, 0x10CEB), + (0x10CAC, 0x10CEC), + (0x10CAD, 0x10CED), + (0x10CAE, 0x10CEE), + (0x10CAF, 0x10CEF), + (0x10CB0, 0x10CF0), + (0x10CB1, 0x10CF1), + (0x10CB2, 0x10CF2), + (0x10D50, 0x10D70), + (0x10D51, 0x10D71), + (0x10D52, 0x10D72), + (0x10D53, 0x10D73), + (0x10D54, 0x10D74), + (0x10D55, 0x10D75), + (0x10D56, 0x10D76), + (0x10D57, 0x10D77), + (0x10D58, 0x10D78), + (0x10D59, 0x10D79), + (0x10D5A, 0x10D7A), + (0x10D5B, 0x10D7B), + (0x10D5C, 0x10D7C), + (0x10D5D, 0x10D7D), + (0x10D5E, 0x10D7E), + (0x10D5F, 0x10D7F), + (0x10D60, 0x10D80), + (0x10D61, 0x10D81), + (0x10D62, 0x10D82), + (0x10D63, 0x10D83), + (0x10D64, 0x10D84), + (0x10D65, 0x10D85), + (0x118A0, 0x118C0), + (0x118A1, 0x118C1), + (0x118A2, 0x118C2), + (0x118A3, 0x118C3), + (0x118A4, 0x118C4), + (0x118A5, 0x118C5), + (0x118A6, 0x118C6), + (0x118A7, 0x118C7), + (0x118A8, 0x118C8), + (0x118A9, 0x118C9), + (0x118AA, 0x118CA), + (0x118AB, 0x118CB), + (0x118AC, 0x118CC), + (0x118AD, 0x118CD), + (0x118AE, 0x118CE), + (0x118AF, 0x118CF), + (0x118B0, 0x118D0), + (0x118B1, 0x118D1), + (0x118B2, 0x118D2), + (0x118B3, 0x118D3), + (0x118B4, 0x118D4), + (0x118B5, 0x118D5), + (0x118B6, 0x118D6), + (0x118B7, 0x118D7), + (0x118B8, 0x118D8), + (0x118B9, 0x118D9), + (0x118BA, 0x118DA), + (0x118BB, 0x118DB), + (0x118BC, 0x118DC), + (0x118BD, 0x118DD), + (0x118BE, 0x118DE), + (0x118BF, 0x118DF), + (0x16E40, 0x16E60), + (0x16E41, 0x16E61), + (0x16E42, 0x16E62), + (0x16E43, 0x16E63), + (0x16E44, 0x16E64), + (0x16E45, 0x16E65), + (0x16E46, 0x16E66), + (0x16E47, 0x16E67), + (0x16E48, 0x16E68), + (0x16E49, 0x16E69), + (0x16E4A, 0x16E6A), + (0x16E4B, 0x16E6B), + (0x16E4C, 0x16E6C), + (0x16E4D, 0x16E6D), + (0x16E4E, 0x16E6E), + (0x16E4F, 0x16E6F), + (0x16E50, 0x16E70), + (0x16E51, 0x16E71), + (0x16E52, 0x16E72), + (0x16E53, 0x16E73), + (0x16E54, 0x16E74), + (0x16E55, 0x16E75), + (0x16E56, 0x16E76), + (0x16E57, 0x16E77), + (0x16E58, 0x16E78), + (0x16E59, 0x16E79), + (0x16E5A, 0x16E7A), + (0x16E5B, 0x16E7B), + (0x16E5C, 0x16E7C), + (0x16E5D, 0x16E7D), + (0x16E5E, 0x16E7E), + (0x16E5F, 0x16E7F), + (0x1E900, 0x1E922), + (0x1E901, 0x1E923), + (0x1E902, 0x1E924), + (0x1E903, 0x1E925), + (0x1E904, 0x1E926), + (0x1E905, 0x1E927), + (0x1E906, 0x1E928), + (0x1E907, 0x1E929), + (0x1E908, 0x1E92A), + (0x1E909, 0x1E92B), + (0x1E90A, 0x1E92C), + (0x1E90B, 0x1E92D), + (0x1E90C, 0x1E92E), + (0x1E90D, 0x1E92F), + (0x1E90E, 0x1E930), + (0x1E90F, 0x1E931), + (0x1E910, 0x1E932), + (0x1E911, 0x1E933), + (0x1E912, 0x1E934), + (0x1E913, 0x1E935), + (0x1E914, 0x1E936), + (0x1E915, 0x1E937), + (0x1E916, 0x1E938), + (0x1E917, 0x1E939), + (0x1E918, 0x1E93A), + (0x1E919, 0x1E93B), + (0x1E91A, 0x1E93C), + (0x1E91B, 0x1E93D), + (0x1E91C, 0x1E93E), + (0x1E91D, 0x1E93F), + (0x1E91E, 0x1E940), + (0x1E91F, 0x1E941), + (0x1E920, 0x1E942), + (0x1E921, 0x1E943), +] diff --git a/crates/sqlbuild-core/src/text/tests/test_python_compat.rs b/crates/sqlbuild-core/src/text/tests/test_python_compat.rs index e09e2ec546..b14e4acbdc 100644 --- a/crates/sqlbuild-core/src/text/tests/test_python_compat.rs +++ b/crates/sqlbuild-core/src/text/tests/test_python_compat.rs @@ -4,11 +4,15 @@ use crate::text::main::is_python_alpha::is_python_alpha; use crate::text::main::is_python_decimal::is_python_decimal; use crate::text::main::is_python_space::is_python_space; use crate::text::main::is_python_word::is_python_word; +use crate::text::main::python_casefold::python_casefold; use crate::text::main::python_cleandoc::python_cleandoc; +use crate::text::main::python_ignorecase_key::python_ignorecase_key; use crate::text::main::python_text::python_text; +use crate::text::main::python_upper::python_upper; use crate::text::models::PythonText; use crate::text::tests::test_types::{ - CharacterClassTestCase, CleandocTestCase, CloseMatchesTestCase, PythonTextTestCase, + CaseMappingTestCase, CharacterClassTestCase, CleandocTestCase, CloseMatchesTestCase, + IgnorecaseTestCase, PythonTextTestCase, }; const KEYS: &[&str] = &[ @@ -285,3 +289,153 @@ fn given_python_versions_when_cleaning_bodies_then_cleandoc_matches_that_version ); } } + +#[test] +fn given_unicode_versions_when_folding_and_upper_casing_then_python_str_methods_agree() { + let test_cases = [ + CaseMappingTestCase { + description: "ASCII, final sigma, sharp s, dotted I and a ligature", + unicode_version: "15.0.0", + text: "Orders \u{3a3}\u{391}\u{3a3} \u{df} \u{130} \u{fb01}", + expected_casefold: "orders \u{3c3}\u{3b1}\u{3c3} ss i\u{307} fi", + expected_upper: "ORDERS \u{3a3}\u{391}\u{3a3} SS \u{130} FI", + }, + CaseMappingTestCase { + description: "a capital Unicode 16.0 added folds only there", + unicode_version: "15.1.0", + text: "\u{a7cb}", + expected_casefold: "\u{a7cb}", + expected_upper: "\u{a7cb}", + }, + CaseMappingTestCase { + description: "the same capital under Unicode 16.0", + unicode_version: "16.0.0", + text: "\u{a7cb}", + expected_casefold: "\u{264}", + expected_upper: "\u{a7cb}", + }, + ]; + for test_case in test_cases { + let python: PythonText = + python_text((3, 13), test_case.unicode_version).expect("the version is supported"); + + assert_eq!( + ( + python_casefold(python, test_case.text), + python_upper(python, test_case.text) + ), + ( + test_case.expected_casefold.to_owned(), + test_case.expected_upper.to_owned() + ), + "{}", + test_case.description + ); + } +} + +#[test] +fn given_character_pairs_when_matching_ignoring_case_then_python_re_agrees() { + let test_cases = [ + IgnorecaseTestCase { + description: "k against \u{212a}", + pattern: 'k', + text: '\u{212a}', + expected_match: true, + }, + IgnorecaseTestCase { + description: "K against \u{212a}", + pattern: 'K', + text: '\u{212a}', + expected_match: true, + }, + IgnorecaseTestCase { + description: "s against \u{17f}", + pattern: 's', + text: '\u{17f}', + expected_match: true, + }, + IgnorecaseTestCase { + description: "i against \u{131}", + pattern: 'i', + text: '\u{131}', + expected_match: true, + }, + IgnorecaseTestCase { + description: "I against \u{130}", + pattern: 'I', + text: '\u{130}', + expected_match: true, + }, + IgnorecaseTestCase { + description: "i against \u{130}", + pattern: 'i', + text: '\u{130}', + expected_match: true, + }, + IgnorecaseTestCase { + description: "\u{3c3} against \u{3c2}", + pattern: '\u{3c3}', + text: '\u{3c2}', + expected_match: true, + }, + IgnorecaseTestCase { + description: "\u{3a3} against \u{3c2}", + pattern: '\u{3a3}', + text: '\u{3c2}', + expected_match: true, + }, + IgnorecaseTestCase { + description: "\u{b5} against \u{39c}", + pattern: '\u{b5}', + text: '\u{39c}', + expected_match: true, + }, + IgnorecaseTestCase { + description: "\u{df} against \u{1e9e}", + pattern: '\u{df}', + text: '\u{1e9e}', + expected_match: true, + }, + IgnorecaseTestCase { + description: "\u{df} against S", + pattern: '\u{df}', + text: 'S', + expected_match: false, + }, + IgnorecaseTestCase { + description: "\u{130} against \u{131}", + pattern: '\u{130}', + text: '\u{131}', + expected_match: true, + }, + IgnorecaseTestCase { + description: "a against \u{e1}", + pattern: 'a', + text: '\u{e1}', + expected_match: false, + }, + IgnorecaseTestCase { + description: "\u{1c80} against \u{412}", + pattern: '\u{1c80}', + text: '\u{412}', + expected_match: true, + }, + IgnorecaseTestCase { + description: "\u{fb05} against \u{fb06}", + pattern: '\u{fb05}', + text: '\u{fb06}', + expected_match: true, + }, + ]; + let python: PythonText = python_text((3, 12), "15.0.0").expect("Python 3.12 is supported"); + for test_case in test_cases { + assert_eq!( + python_ignorecase_key(python, test_case.pattern) + == python_ignorecase_key(python, test_case.text), + test_case.expected_match, + "{}", + test_case.description + ); + } +} diff --git a/crates/sqlbuild-core/src/text/tests/test_types.rs b/crates/sqlbuild-core/src/text/tests/test_types.rs index 4b5d761cf5..32828b6c9d 100644 --- a/crates/sqlbuild-core/src/text/tests/test_types.rs +++ b/crates/sqlbuild-core/src/text/tests/test_types.rs @@ -52,3 +52,19 @@ pub(super) struct CleandocTestCase { pub(super) text: &'static str, pub(super) expected_text: &'static str, } + +pub(super) struct CaseMappingTestCase { + pub(super) description: &'static str, + pub(super) unicode_version: &'static str, + pub(super) text: &'static str, + pub(super) expected_casefold: &'static str, + pub(super) expected_upper: &'static str, +} + +/// `re.fullmatch(re.escape(pattern), text, re.IGNORECASE)` under Python 3.12. +pub(crate) struct IgnorecaseTestCase { + pub(crate) description: &'static str, + pub(crate) pattern: char, + pub(crate) text: char, + pub(crate) expected_match: bool, +} diff --git a/crates/sqlbuild-core/src/text/upper_mappings/unicode_15_0_0.in b/crates/sqlbuild-core/src/text/upper_mappings/unicode_15_0_0.in new file mode 100644 index 0000000000..a45b06a971 --- /dev/null +++ b/crates/sqlbuild-core/src/text/upper_mappings/unicode_15_0_0.in @@ -0,0 +1,1529 @@ +// Generated by `scripts/generate_python_char_table.py`; do not edit. +// Every character `str.upper()` changes in Unicode 15.0.0, in code point order. +&[ + (0x0061, "\u{41}"), + (0x0062, "\u{42}"), + (0x0063, "\u{43}"), + (0x0064, "\u{44}"), + (0x0065, "\u{45}"), + (0x0066, "\u{46}"), + (0x0067, "\u{47}"), + (0x0068, "\u{48}"), + (0x0069, "\u{49}"), + (0x006A, "\u{4a}"), + (0x006B, "\u{4b}"), + (0x006C, "\u{4c}"), + (0x006D, "\u{4d}"), + (0x006E, "\u{4e}"), + (0x006F, "\u{4f}"), + (0x0070, "\u{50}"), + (0x0071, "\u{51}"), + (0x0072, "\u{52}"), + (0x0073, "\u{53}"), + (0x0074, "\u{54}"), + (0x0075, "\u{55}"), + (0x0076, "\u{56}"), + (0x0077, "\u{57}"), + (0x0078, "\u{58}"), + (0x0079, "\u{59}"), + (0x007A, "\u{5a}"), + (0x00B5, "\u{39c}"), + (0x00DF, "\u{53}\u{53}"), + (0x00E0, "\u{c0}"), + (0x00E1, "\u{c1}"), + (0x00E2, "\u{c2}"), + (0x00E3, "\u{c3}"), + (0x00E4, "\u{c4}"), + (0x00E5, "\u{c5}"), + (0x00E6, "\u{c6}"), + (0x00E7, "\u{c7}"), + (0x00E8, "\u{c8}"), + (0x00E9, "\u{c9}"), + (0x00EA, "\u{ca}"), + (0x00EB, "\u{cb}"), + (0x00EC, "\u{cc}"), + (0x00ED, "\u{cd}"), + (0x00EE, "\u{ce}"), + (0x00EF, "\u{cf}"), + (0x00F0, "\u{d0}"), + (0x00F1, "\u{d1}"), + (0x00F2, "\u{d2}"), + (0x00F3, "\u{d3}"), + (0x00F4, "\u{d4}"), + (0x00F5, "\u{d5}"), + (0x00F6, "\u{d6}"), + (0x00F8, "\u{d8}"), + (0x00F9, "\u{d9}"), + (0x00FA, "\u{da}"), + (0x00FB, "\u{db}"), + (0x00FC, "\u{dc}"), + (0x00FD, "\u{dd}"), + (0x00FE, "\u{de}"), + (0x00FF, "\u{178}"), + (0x0101, "\u{100}"), + (0x0103, "\u{102}"), + (0x0105, "\u{104}"), + (0x0107, "\u{106}"), + (0x0109, "\u{108}"), + (0x010B, "\u{10a}"), + (0x010D, "\u{10c}"), + (0x010F, "\u{10e}"), + (0x0111, "\u{110}"), + (0x0113, "\u{112}"), + (0x0115, "\u{114}"), + (0x0117, "\u{116}"), + (0x0119, "\u{118}"), + (0x011B, "\u{11a}"), + (0x011D, "\u{11c}"), + (0x011F, "\u{11e}"), + (0x0121, "\u{120}"), + (0x0123, "\u{122}"), + (0x0125, "\u{124}"), + (0x0127, "\u{126}"), + (0x0129, "\u{128}"), + (0x012B, "\u{12a}"), + (0x012D, "\u{12c}"), + (0x012F, "\u{12e}"), + (0x0131, "\u{49}"), + (0x0133, "\u{132}"), + (0x0135, "\u{134}"), + (0x0137, "\u{136}"), + (0x013A, "\u{139}"), + (0x013C, "\u{13b}"), + (0x013E, "\u{13d}"), + (0x0140, "\u{13f}"), + (0x0142, "\u{141}"), + (0x0144, "\u{143}"), + (0x0146, "\u{145}"), + (0x0148, "\u{147}"), + (0x0149, "\u{2bc}\u{4e}"), + (0x014B, "\u{14a}"), + (0x014D, "\u{14c}"), + (0x014F, "\u{14e}"), + (0x0151, "\u{150}"), + (0x0153, "\u{152}"), + (0x0155, "\u{154}"), + (0x0157, "\u{156}"), + (0x0159, "\u{158}"), + (0x015B, "\u{15a}"), + (0x015D, "\u{15c}"), + (0x015F, "\u{15e}"), + (0x0161, "\u{160}"), + (0x0163, "\u{162}"), + (0x0165, "\u{164}"), + (0x0167, "\u{166}"), + (0x0169, "\u{168}"), + (0x016B, "\u{16a}"), + (0x016D, "\u{16c}"), + (0x016F, "\u{16e}"), + (0x0171, "\u{170}"), + (0x0173, "\u{172}"), + (0x0175, "\u{174}"), + (0x0177, "\u{176}"), + (0x017A, "\u{179}"), + (0x017C, "\u{17b}"), + (0x017E, "\u{17d}"), + (0x017F, "\u{53}"), + (0x0180, "\u{243}"), + (0x0183, "\u{182}"), + (0x0185, "\u{184}"), + (0x0188, "\u{187}"), + (0x018C, "\u{18b}"), + (0x0192, "\u{191}"), + (0x0195, "\u{1f6}"), + (0x0199, "\u{198}"), + (0x019A, "\u{23d}"), + (0x019E, "\u{220}"), + (0x01A1, "\u{1a0}"), + (0x01A3, "\u{1a2}"), + (0x01A5, "\u{1a4}"), + (0x01A8, "\u{1a7}"), + (0x01AD, "\u{1ac}"), + (0x01B0, "\u{1af}"), + (0x01B4, "\u{1b3}"), + (0x01B6, "\u{1b5}"), + (0x01B9, "\u{1b8}"), + (0x01BD, "\u{1bc}"), + (0x01BF, "\u{1f7}"), + (0x01C5, "\u{1c4}"), + (0x01C6, "\u{1c4}"), + (0x01C8, "\u{1c7}"), + (0x01C9, "\u{1c7}"), + (0x01CB, "\u{1ca}"), + (0x01CC, "\u{1ca}"), + (0x01CE, "\u{1cd}"), + (0x01D0, "\u{1cf}"), + (0x01D2, "\u{1d1}"), + (0x01D4, "\u{1d3}"), + (0x01D6, "\u{1d5}"), + (0x01D8, "\u{1d7}"), + (0x01DA, "\u{1d9}"), + (0x01DC, "\u{1db}"), + (0x01DD, "\u{18e}"), + (0x01DF, "\u{1de}"), + (0x01E1, "\u{1e0}"), + (0x01E3, "\u{1e2}"), + (0x01E5, "\u{1e4}"), + (0x01E7, "\u{1e6}"), + (0x01E9, "\u{1e8}"), + (0x01EB, "\u{1ea}"), + (0x01ED, "\u{1ec}"), + (0x01EF, "\u{1ee}"), + (0x01F0, "\u{4a}\u{30c}"), + (0x01F2, "\u{1f1}"), + (0x01F3, "\u{1f1}"), + (0x01F5, "\u{1f4}"), + (0x01F9, "\u{1f8}"), + (0x01FB, "\u{1fa}"), + (0x01FD, "\u{1fc}"), + (0x01FF, "\u{1fe}"), + (0x0201, "\u{200}"), + (0x0203, "\u{202}"), + (0x0205, "\u{204}"), + (0x0207, "\u{206}"), + (0x0209, "\u{208}"), + (0x020B, "\u{20a}"), + (0x020D, "\u{20c}"), + (0x020F, "\u{20e}"), + (0x0211, "\u{210}"), + (0x0213, "\u{212}"), + (0x0215, "\u{214}"), + (0x0217, "\u{216}"), + (0x0219, "\u{218}"), + (0x021B, "\u{21a}"), + (0x021D, "\u{21c}"), + (0x021F, "\u{21e}"), + (0x0223, "\u{222}"), + (0x0225, "\u{224}"), + (0x0227, "\u{226}"), + (0x0229, "\u{228}"), + (0x022B, "\u{22a}"), + (0x022D, "\u{22c}"), + (0x022F, "\u{22e}"), + (0x0231, "\u{230}"), + (0x0233, "\u{232}"), + (0x023C, "\u{23b}"), + (0x023F, "\u{2c7e}"), + (0x0240, "\u{2c7f}"), + (0x0242, "\u{241}"), + (0x0247, "\u{246}"), + (0x0249, "\u{248}"), + (0x024B, "\u{24a}"), + (0x024D, "\u{24c}"), + (0x024F, "\u{24e}"), + (0x0250, "\u{2c6f}"), + (0x0251, "\u{2c6d}"), + (0x0252, "\u{2c70}"), + (0x0253, "\u{181}"), + (0x0254, "\u{186}"), + (0x0256, "\u{189}"), + (0x0257, "\u{18a}"), + (0x0259, "\u{18f}"), + (0x025B, "\u{190}"), + (0x025C, "\u{a7ab}"), + (0x0260, "\u{193}"), + (0x0261, "\u{a7ac}"), + (0x0263, "\u{194}"), + (0x0265, "\u{a78d}"), + (0x0266, "\u{a7aa}"), + (0x0268, "\u{197}"), + (0x0269, "\u{196}"), + (0x026A, "\u{a7ae}"), + (0x026B, "\u{2c62}"), + (0x026C, "\u{a7ad}"), + (0x026F, "\u{19c}"), + (0x0271, "\u{2c6e}"), + (0x0272, "\u{19d}"), + (0x0275, "\u{19f}"), + (0x027D, "\u{2c64}"), + (0x0280, "\u{1a6}"), + (0x0282, "\u{a7c5}"), + (0x0283, "\u{1a9}"), + (0x0287, "\u{a7b1}"), + (0x0288, "\u{1ae}"), + (0x0289, "\u{244}"), + (0x028A, "\u{1b1}"), + (0x028B, "\u{1b2}"), + (0x028C, "\u{245}"), + (0x0292, "\u{1b7}"), + (0x029D, "\u{a7b2}"), + (0x029E, "\u{a7b0}"), + (0x0345, "\u{399}"), + (0x0371, "\u{370}"), + (0x0373, "\u{372}"), + (0x0377, "\u{376}"), + (0x037B, "\u{3fd}"), + (0x037C, "\u{3fe}"), + (0x037D, "\u{3ff}"), + (0x0390, "\u{399}\u{308}\u{301}"), + (0x03AC, "\u{386}"), + (0x03AD, "\u{388}"), + (0x03AE, "\u{389}"), + (0x03AF, "\u{38a}"), + (0x03B0, "\u{3a5}\u{308}\u{301}"), + (0x03B1, "\u{391}"), + (0x03B2, "\u{392}"), + (0x03B3, "\u{393}"), + (0x03B4, "\u{394}"), + (0x03B5, "\u{395}"), + (0x03B6, "\u{396}"), + (0x03B7, "\u{397}"), + (0x03B8, "\u{398}"), + (0x03B9, "\u{399}"), + (0x03BA, "\u{39a}"), + (0x03BB, "\u{39b}"), + (0x03BC, "\u{39c}"), + (0x03BD, "\u{39d}"), + (0x03BE, "\u{39e}"), + (0x03BF, "\u{39f}"), + (0x03C0, "\u{3a0}"), + (0x03C1, "\u{3a1}"), + (0x03C2, "\u{3a3}"), + (0x03C3, "\u{3a3}"), + (0x03C4, "\u{3a4}"), + (0x03C5, "\u{3a5}"), + (0x03C6, "\u{3a6}"), + (0x03C7, "\u{3a7}"), + (0x03C8, "\u{3a8}"), + (0x03C9, "\u{3a9}"), + (0x03CA, "\u{3aa}"), + (0x03CB, "\u{3ab}"), + (0x03CC, "\u{38c}"), + (0x03CD, "\u{38e}"), + (0x03CE, "\u{38f}"), + (0x03D0, "\u{392}"), + (0x03D1, "\u{398}"), + (0x03D5, "\u{3a6}"), + (0x03D6, "\u{3a0}"), + (0x03D7, "\u{3cf}"), + (0x03D9, "\u{3d8}"), + (0x03DB, "\u{3da}"), + (0x03DD, "\u{3dc}"), + (0x03DF, "\u{3de}"), + (0x03E1, "\u{3e0}"), + (0x03E3, "\u{3e2}"), + (0x03E5, "\u{3e4}"), + (0x03E7, "\u{3e6}"), + (0x03E9, "\u{3e8}"), + (0x03EB, "\u{3ea}"), + (0x03ED, "\u{3ec}"), + (0x03EF, "\u{3ee}"), + (0x03F0, "\u{39a}"), + (0x03F1, "\u{3a1}"), + (0x03F2, "\u{3f9}"), + (0x03F3, "\u{37f}"), + (0x03F5, "\u{395}"), + (0x03F8, "\u{3f7}"), + (0x03FB, "\u{3fa}"), + (0x0430, "\u{410}"), + (0x0431, "\u{411}"), + (0x0432, "\u{412}"), + (0x0433, "\u{413}"), + (0x0434, "\u{414}"), + (0x0435, "\u{415}"), + (0x0436, "\u{416}"), + (0x0437, "\u{417}"), + (0x0438, "\u{418}"), + (0x0439, "\u{419}"), + (0x043A, "\u{41a}"), + (0x043B, "\u{41b}"), + (0x043C, "\u{41c}"), + (0x043D, "\u{41d}"), + (0x043E, "\u{41e}"), + (0x043F, "\u{41f}"), + (0x0440, "\u{420}"), + (0x0441, "\u{421}"), + (0x0442, "\u{422}"), + (0x0443, "\u{423}"), + (0x0444, "\u{424}"), + (0x0445, "\u{425}"), + (0x0446, "\u{426}"), + (0x0447, "\u{427}"), + (0x0448, "\u{428}"), + (0x0449, "\u{429}"), + (0x044A, "\u{42a}"), + (0x044B, "\u{42b}"), + (0x044C, "\u{42c}"), + (0x044D, "\u{42d}"), + (0x044E, "\u{42e}"), + (0x044F, "\u{42f}"), + (0x0450, "\u{400}"), + (0x0451, "\u{401}"), + (0x0452, "\u{402}"), + (0x0453, "\u{403}"), + (0x0454, "\u{404}"), + (0x0455, "\u{405}"), + (0x0456, "\u{406}"), + (0x0457, "\u{407}"), + (0x0458, "\u{408}"), + (0x0459, "\u{409}"), + (0x045A, "\u{40a}"), + (0x045B, "\u{40b}"), + (0x045C, "\u{40c}"), + (0x045D, "\u{40d}"), + (0x045E, "\u{40e}"), + (0x045F, "\u{40f}"), + (0x0461, "\u{460}"), + (0x0463, "\u{462}"), + (0x0465, "\u{464}"), + (0x0467, "\u{466}"), + (0x0469, "\u{468}"), + (0x046B, "\u{46a}"), + (0x046D, "\u{46c}"), + (0x046F, "\u{46e}"), + (0x0471, "\u{470}"), + (0x0473, "\u{472}"), + (0x0475, "\u{474}"), + (0x0477, "\u{476}"), + (0x0479, "\u{478}"), + (0x047B, "\u{47a}"), + (0x047D, "\u{47c}"), + (0x047F, "\u{47e}"), + (0x0481, "\u{480}"), + (0x048B, "\u{48a}"), + (0x048D, "\u{48c}"), + (0x048F, "\u{48e}"), + (0x0491, "\u{490}"), + (0x0493, "\u{492}"), + (0x0495, "\u{494}"), + (0x0497, "\u{496}"), + (0x0499, "\u{498}"), + (0x049B, "\u{49a}"), + (0x049D, "\u{49c}"), + (0x049F, "\u{49e}"), + (0x04A1, "\u{4a0}"), + (0x04A3, "\u{4a2}"), + (0x04A5, "\u{4a4}"), + (0x04A7, "\u{4a6}"), + (0x04A9, "\u{4a8}"), + (0x04AB, "\u{4aa}"), + (0x04AD, "\u{4ac}"), + (0x04AF, "\u{4ae}"), + (0x04B1, "\u{4b0}"), + (0x04B3, "\u{4b2}"), + (0x04B5, "\u{4b4}"), + (0x04B7, "\u{4b6}"), + (0x04B9, "\u{4b8}"), + (0x04BB, "\u{4ba}"), + (0x04BD, "\u{4bc}"), + (0x04BF, "\u{4be}"), + (0x04C2, "\u{4c1}"), + (0x04C4, "\u{4c3}"), + (0x04C6, "\u{4c5}"), + (0x04C8, "\u{4c7}"), + (0x04CA, "\u{4c9}"), + (0x04CC, "\u{4cb}"), + (0x04CE, "\u{4cd}"), + (0x04CF, "\u{4c0}"), + (0x04D1, "\u{4d0}"), + (0x04D3, "\u{4d2}"), + (0x04D5, "\u{4d4}"), + (0x04D7, "\u{4d6}"), + (0x04D9, "\u{4d8}"), + (0x04DB, "\u{4da}"), + (0x04DD, "\u{4dc}"), + (0x04DF, "\u{4de}"), + (0x04E1, "\u{4e0}"), + (0x04E3, "\u{4e2}"), + (0x04E5, "\u{4e4}"), + (0x04E7, "\u{4e6}"), + (0x04E9, "\u{4e8}"), + (0x04EB, "\u{4ea}"), + (0x04ED, "\u{4ec}"), + (0x04EF, "\u{4ee}"), + (0x04F1, "\u{4f0}"), + (0x04F3, "\u{4f2}"), + (0x04F5, "\u{4f4}"), + (0x04F7, "\u{4f6}"), + (0x04F9, "\u{4f8}"), + (0x04FB, "\u{4fa}"), + (0x04FD, "\u{4fc}"), + (0x04FF, "\u{4fe}"), + (0x0501, "\u{500}"), + (0x0503, "\u{502}"), + (0x0505, "\u{504}"), + (0x0507, "\u{506}"), + (0x0509, "\u{508}"), + (0x050B, "\u{50a}"), + (0x050D, "\u{50c}"), + (0x050F, "\u{50e}"), + (0x0511, "\u{510}"), + (0x0513, "\u{512}"), + (0x0515, "\u{514}"), + (0x0517, "\u{516}"), + (0x0519, "\u{518}"), + (0x051B, "\u{51a}"), + (0x051D, "\u{51c}"), + (0x051F, "\u{51e}"), + (0x0521, "\u{520}"), + (0x0523, "\u{522}"), + (0x0525, "\u{524}"), + (0x0527, "\u{526}"), + (0x0529, "\u{528}"), + (0x052B, "\u{52a}"), + (0x052D, "\u{52c}"), + (0x052F, "\u{52e}"), + (0x0561, "\u{531}"), + (0x0562, "\u{532}"), + (0x0563, "\u{533}"), + (0x0564, "\u{534}"), + (0x0565, "\u{535}"), + (0x0566, "\u{536}"), + (0x0567, "\u{537}"), + (0x0568, "\u{538}"), + (0x0569, "\u{539}"), + (0x056A, "\u{53a}"), + (0x056B, "\u{53b}"), + (0x056C, "\u{53c}"), + (0x056D, "\u{53d}"), + (0x056E, "\u{53e}"), + (0x056F, "\u{53f}"), + (0x0570, "\u{540}"), + (0x0571, "\u{541}"), + (0x0572, "\u{542}"), + (0x0573, "\u{543}"), + (0x0574, "\u{544}"), + (0x0575, "\u{545}"), + (0x0576, "\u{546}"), + (0x0577, "\u{547}"), + (0x0578, "\u{548}"), + (0x0579, "\u{549}"), + (0x057A, "\u{54a}"), + (0x057B, "\u{54b}"), + (0x057C, "\u{54c}"), + (0x057D, "\u{54d}"), + (0x057E, "\u{54e}"), + (0x057F, "\u{54f}"), + (0x0580, "\u{550}"), + (0x0581, "\u{551}"), + (0x0582, "\u{552}"), + (0x0583, "\u{553}"), + (0x0584, "\u{554}"), + (0x0585, "\u{555}"), + (0x0586, "\u{556}"), + (0x0587, "\u{535}\u{552}"), + (0x10D0, "\u{1c90}"), + (0x10D1, "\u{1c91}"), + (0x10D2, "\u{1c92}"), + (0x10D3, "\u{1c93}"), + (0x10D4, "\u{1c94}"), + (0x10D5, "\u{1c95}"), + (0x10D6, "\u{1c96}"), + (0x10D7, "\u{1c97}"), + (0x10D8, "\u{1c98}"), + (0x10D9, "\u{1c99}"), + (0x10DA, "\u{1c9a}"), + (0x10DB, "\u{1c9b}"), + (0x10DC, "\u{1c9c}"), + (0x10DD, "\u{1c9d}"), + (0x10DE, "\u{1c9e}"), + (0x10DF, "\u{1c9f}"), + (0x10E0, "\u{1ca0}"), + (0x10E1, "\u{1ca1}"), + (0x10E2, "\u{1ca2}"), + (0x10E3, "\u{1ca3}"), + (0x10E4, "\u{1ca4}"), + (0x10E5, "\u{1ca5}"), + (0x10E6, "\u{1ca6}"), + (0x10E7, "\u{1ca7}"), + (0x10E8, "\u{1ca8}"), + (0x10E9, "\u{1ca9}"), + (0x10EA, "\u{1caa}"), + (0x10EB, "\u{1cab}"), + (0x10EC, "\u{1cac}"), + (0x10ED, "\u{1cad}"), + (0x10EE, "\u{1cae}"), + (0x10EF, "\u{1caf}"), + (0x10F0, "\u{1cb0}"), + (0x10F1, "\u{1cb1}"), + (0x10F2, "\u{1cb2}"), + (0x10F3, "\u{1cb3}"), + (0x10F4, "\u{1cb4}"), + (0x10F5, "\u{1cb5}"), + (0x10F6, "\u{1cb6}"), + (0x10F7, "\u{1cb7}"), + (0x10F8, "\u{1cb8}"), + (0x10F9, "\u{1cb9}"), + (0x10FA, "\u{1cba}"), + (0x10FD, "\u{1cbd}"), + (0x10FE, "\u{1cbe}"), + (0x10FF, "\u{1cbf}"), + (0x13F8, "\u{13f0}"), + (0x13F9, "\u{13f1}"), + (0x13FA, "\u{13f2}"), + (0x13FB, "\u{13f3}"), + (0x13FC, "\u{13f4}"), + (0x13FD, "\u{13f5}"), + (0x1C80, "\u{412}"), + (0x1C81, "\u{414}"), + (0x1C82, "\u{41e}"), + (0x1C83, "\u{421}"), + (0x1C84, "\u{422}"), + (0x1C85, "\u{422}"), + (0x1C86, "\u{42a}"), + (0x1C87, "\u{462}"), + (0x1C88, "\u{a64a}"), + (0x1D79, "\u{a77d}"), + (0x1D7D, "\u{2c63}"), + (0x1D8E, "\u{a7c6}"), + (0x1E01, "\u{1e00}"), + (0x1E03, "\u{1e02}"), + (0x1E05, "\u{1e04}"), + (0x1E07, "\u{1e06}"), + (0x1E09, "\u{1e08}"), + (0x1E0B, "\u{1e0a}"), + (0x1E0D, "\u{1e0c}"), + (0x1E0F, "\u{1e0e}"), + (0x1E11, "\u{1e10}"), + (0x1E13, "\u{1e12}"), + (0x1E15, "\u{1e14}"), + (0x1E17, "\u{1e16}"), + (0x1E19, "\u{1e18}"), + (0x1E1B, "\u{1e1a}"), + (0x1E1D, "\u{1e1c}"), + (0x1E1F, "\u{1e1e}"), + (0x1E21, "\u{1e20}"), + (0x1E23, "\u{1e22}"), + (0x1E25, "\u{1e24}"), + (0x1E27, "\u{1e26}"), + (0x1E29, "\u{1e28}"), + (0x1E2B, "\u{1e2a}"), + (0x1E2D, "\u{1e2c}"), + (0x1E2F, "\u{1e2e}"), + (0x1E31, "\u{1e30}"), + (0x1E33, "\u{1e32}"), + (0x1E35, "\u{1e34}"), + (0x1E37, "\u{1e36}"), + (0x1E39, "\u{1e38}"), + (0x1E3B, "\u{1e3a}"), + (0x1E3D, "\u{1e3c}"), + (0x1E3F, "\u{1e3e}"), + (0x1E41, "\u{1e40}"), + (0x1E43, "\u{1e42}"), + (0x1E45, "\u{1e44}"), + (0x1E47, "\u{1e46}"), + (0x1E49, "\u{1e48}"), + (0x1E4B, "\u{1e4a}"), + (0x1E4D, "\u{1e4c}"), + (0x1E4F, "\u{1e4e}"), + (0x1E51, "\u{1e50}"), + (0x1E53, "\u{1e52}"), + (0x1E55, "\u{1e54}"), + (0x1E57, "\u{1e56}"), + (0x1E59, "\u{1e58}"), + (0x1E5B, "\u{1e5a}"), + (0x1E5D, "\u{1e5c}"), + (0x1E5F, "\u{1e5e}"), + (0x1E61, "\u{1e60}"), + (0x1E63, "\u{1e62}"), + (0x1E65, "\u{1e64}"), + (0x1E67, "\u{1e66}"), + (0x1E69, "\u{1e68}"), + (0x1E6B, "\u{1e6a}"), + (0x1E6D, "\u{1e6c}"), + (0x1E6F, "\u{1e6e}"), + (0x1E71, "\u{1e70}"), + (0x1E73, "\u{1e72}"), + (0x1E75, "\u{1e74}"), + (0x1E77, "\u{1e76}"), + (0x1E79, "\u{1e78}"), + (0x1E7B, "\u{1e7a}"), + (0x1E7D, "\u{1e7c}"), + (0x1E7F, "\u{1e7e}"), + (0x1E81, "\u{1e80}"), + (0x1E83, "\u{1e82}"), + (0x1E85, "\u{1e84}"), + (0x1E87, "\u{1e86}"), + (0x1E89, "\u{1e88}"), + (0x1E8B, "\u{1e8a}"), + (0x1E8D, "\u{1e8c}"), + (0x1E8F, "\u{1e8e}"), + (0x1E91, "\u{1e90}"), + (0x1E93, "\u{1e92}"), + (0x1E95, "\u{1e94}"), + (0x1E96, "\u{48}\u{331}"), + (0x1E97, "\u{54}\u{308}"), + (0x1E98, "\u{57}\u{30a}"), + (0x1E99, "\u{59}\u{30a}"), + (0x1E9A, "\u{41}\u{2be}"), + (0x1E9B, "\u{1e60}"), + (0x1EA1, "\u{1ea0}"), + (0x1EA3, "\u{1ea2}"), + (0x1EA5, "\u{1ea4}"), + (0x1EA7, "\u{1ea6}"), + (0x1EA9, "\u{1ea8}"), + (0x1EAB, "\u{1eaa}"), + (0x1EAD, "\u{1eac}"), + (0x1EAF, "\u{1eae}"), + (0x1EB1, "\u{1eb0}"), + (0x1EB3, "\u{1eb2}"), + (0x1EB5, "\u{1eb4}"), + (0x1EB7, "\u{1eb6}"), + (0x1EB9, "\u{1eb8}"), + (0x1EBB, "\u{1eba}"), + (0x1EBD, "\u{1ebc}"), + (0x1EBF, "\u{1ebe}"), + (0x1EC1, "\u{1ec0}"), + (0x1EC3, "\u{1ec2}"), + (0x1EC5, "\u{1ec4}"), + (0x1EC7, "\u{1ec6}"), + (0x1EC9, "\u{1ec8}"), + (0x1ECB, "\u{1eca}"), + (0x1ECD, "\u{1ecc}"), + (0x1ECF, "\u{1ece}"), + (0x1ED1, "\u{1ed0}"), + (0x1ED3, "\u{1ed2}"), + (0x1ED5, "\u{1ed4}"), + (0x1ED7, "\u{1ed6}"), + (0x1ED9, "\u{1ed8}"), + (0x1EDB, "\u{1eda}"), + (0x1EDD, "\u{1edc}"), + (0x1EDF, "\u{1ede}"), + (0x1EE1, "\u{1ee0}"), + (0x1EE3, "\u{1ee2}"), + (0x1EE5, "\u{1ee4}"), + (0x1EE7, "\u{1ee6}"), + (0x1EE9, "\u{1ee8}"), + (0x1EEB, "\u{1eea}"), + (0x1EED, "\u{1eec}"), + (0x1EEF, "\u{1eee}"), + (0x1EF1, "\u{1ef0}"), + (0x1EF3, "\u{1ef2}"), + (0x1EF5, "\u{1ef4}"), + (0x1EF7, "\u{1ef6}"), + (0x1EF9, "\u{1ef8}"), + (0x1EFB, "\u{1efa}"), + (0x1EFD, "\u{1efc}"), + (0x1EFF, "\u{1efe}"), + (0x1F00, "\u{1f08}"), + (0x1F01, "\u{1f09}"), + (0x1F02, "\u{1f0a}"), + (0x1F03, "\u{1f0b}"), + (0x1F04, "\u{1f0c}"), + (0x1F05, "\u{1f0d}"), + (0x1F06, "\u{1f0e}"), + (0x1F07, "\u{1f0f}"), + (0x1F10, "\u{1f18}"), + (0x1F11, "\u{1f19}"), + (0x1F12, "\u{1f1a}"), + (0x1F13, "\u{1f1b}"), + (0x1F14, "\u{1f1c}"), + (0x1F15, "\u{1f1d}"), + (0x1F20, "\u{1f28}"), + (0x1F21, "\u{1f29}"), + (0x1F22, "\u{1f2a}"), + (0x1F23, "\u{1f2b}"), + (0x1F24, "\u{1f2c}"), + (0x1F25, "\u{1f2d}"), + (0x1F26, "\u{1f2e}"), + (0x1F27, "\u{1f2f}"), + (0x1F30, "\u{1f38}"), + (0x1F31, "\u{1f39}"), + (0x1F32, "\u{1f3a}"), + (0x1F33, "\u{1f3b}"), + (0x1F34, "\u{1f3c}"), + (0x1F35, "\u{1f3d}"), + (0x1F36, "\u{1f3e}"), + (0x1F37, "\u{1f3f}"), + (0x1F40, "\u{1f48}"), + (0x1F41, "\u{1f49}"), + (0x1F42, "\u{1f4a}"), + (0x1F43, "\u{1f4b}"), + (0x1F44, "\u{1f4c}"), + (0x1F45, "\u{1f4d}"), + (0x1F50, "\u{3a5}\u{313}"), + (0x1F51, "\u{1f59}"), + (0x1F52, "\u{3a5}\u{313}\u{300}"), + (0x1F53, "\u{1f5b}"), + (0x1F54, "\u{3a5}\u{313}\u{301}"), + (0x1F55, "\u{1f5d}"), + (0x1F56, "\u{3a5}\u{313}\u{342}"), + (0x1F57, "\u{1f5f}"), + (0x1F60, "\u{1f68}"), + (0x1F61, "\u{1f69}"), + (0x1F62, "\u{1f6a}"), + (0x1F63, "\u{1f6b}"), + (0x1F64, "\u{1f6c}"), + (0x1F65, "\u{1f6d}"), + (0x1F66, "\u{1f6e}"), + (0x1F67, "\u{1f6f}"), + (0x1F70, "\u{1fba}"), + (0x1F71, "\u{1fbb}"), + (0x1F72, "\u{1fc8}"), + (0x1F73, "\u{1fc9}"), + (0x1F74, "\u{1fca}"), + (0x1F75, "\u{1fcb}"), + (0x1F76, "\u{1fda}"), + (0x1F77, "\u{1fdb}"), + (0x1F78, "\u{1ff8}"), + (0x1F79, "\u{1ff9}"), + (0x1F7A, "\u{1fea}"), + (0x1F7B, "\u{1feb}"), + (0x1F7C, "\u{1ffa}"), + (0x1F7D, "\u{1ffb}"), + (0x1F80, "\u{1f08}\u{399}"), + (0x1F81, "\u{1f09}\u{399}"), + (0x1F82, "\u{1f0a}\u{399}"), + (0x1F83, "\u{1f0b}\u{399}"), + (0x1F84, "\u{1f0c}\u{399}"), + (0x1F85, "\u{1f0d}\u{399}"), + (0x1F86, "\u{1f0e}\u{399}"), + (0x1F87, "\u{1f0f}\u{399}"), + (0x1F88, "\u{1f08}\u{399}"), + (0x1F89, "\u{1f09}\u{399}"), + (0x1F8A, "\u{1f0a}\u{399}"), + (0x1F8B, "\u{1f0b}\u{399}"), + (0x1F8C, "\u{1f0c}\u{399}"), + (0x1F8D, "\u{1f0d}\u{399}"), + (0x1F8E, "\u{1f0e}\u{399}"), + (0x1F8F, "\u{1f0f}\u{399}"), + (0x1F90, "\u{1f28}\u{399}"), + (0x1F91, "\u{1f29}\u{399}"), + (0x1F92, "\u{1f2a}\u{399}"), + (0x1F93, "\u{1f2b}\u{399}"), + (0x1F94, "\u{1f2c}\u{399}"), + (0x1F95, "\u{1f2d}\u{399}"), + (0x1F96, "\u{1f2e}\u{399}"), + (0x1F97, "\u{1f2f}\u{399}"), + (0x1F98, "\u{1f28}\u{399}"), + (0x1F99, "\u{1f29}\u{399}"), + (0x1F9A, "\u{1f2a}\u{399}"), + (0x1F9B, "\u{1f2b}\u{399}"), + (0x1F9C, "\u{1f2c}\u{399}"), + (0x1F9D, "\u{1f2d}\u{399}"), + (0x1F9E, "\u{1f2e}\u{399}"), + (0x1F9F, "\u{1f2f}\u{399}"), + (0x1FA0, "\u{1f68}\u{399}"), + (0x1FA1, "\u{1f69}\u{399}"), + (0x1FA2, "\u{1f6a}\u{399}"), + (0x1FA3, "\u{1f6b}\u{399}"), + (0x1FA4, "\u{1f6c}\u{399}"), + (0x1FA5, "\u{1f6d}\u{399}"), + (0x1FA6, "\u{1f6e}\u{399}"), + (0x1FA7, "\u{1f6f}\u{399}"), + (0x1FA8, "\u{1f68}\u{399}"), + (0x1FA9, "\u{1f69}\u{399}"), + (0x1FAA, "\u{1f6a}\u{399}"), + (0x1FAB, "\u{1f6b}\u{399}"), + (0x1FAC, "\u{1f6c}\u{399}"), + (0x1FAD, "\u{1f6d}\u{399}"), + (0x1FAE, "\u{1f6e}\u{399}"), + (0x1FAF, "\u{1f6f}\u{399}"), + (0x1FB0, "\u{1fb8}"), + (0x1FB1, "\u{1fb9}"), + (0x1FB2, "\u{1fba}\u{399}"), + (0x1FB3, "\u{391}\u{399}"), + (0x1FB4, "\u{386}\u{399}"), + (0x1FB6, "\u{391}\u{342}"), + (0x1FB7, "\u{391}\u{342}\u{399}"), + (0x1FBC, "\u{391}\u{399}"), + (0x1FBE, "\u{399}"), + (0x1FC2, "\u{1fca}\u{399}"), + (0x1FC3, "\u{397}\u{399}"), + (0x1FC4, "\u{389}\u{399}"), + (0x1FC6, "\u{397}\u{342}"), + (0x1FC7, "\u{397}\u{342}\u{399}"), + (0x1FCC, "\u{397}\u{399}"), + (0x1FD0, "\u{1fd8}"), + (0x1FD1, "\u{1fd9}"), + (0x1FD2, "\u{399}\u{308}\u{300}"), + (0x1FD3, "\u{399}\u{308}\u{301}"), + (0x1FD6, "\u{399}\u{342}"), + (0x1FD7, "\u{399}\u{308}\u{342}"), + (0x1FE0, "\u{1fe8}"), + (0x1FE1, "\u{1fe9}"), + (0x1FE2, "\u{3a5}\u{308}\u{300}"), + (0x1FE3, "\u{3a5}\u{308}\u{301}"), + (0x1FE4, "\u{3a1}\u{313}"), + (0x1FE5, "\u{1fec}"), + (0x1FE6, "\u{3a5}\u{342}"), + (0x1FE7, "\u{3a5}\u{308}\u{342}"), + (0x1FF2, "\u{1ffa}\u{399}"), + (0x1FF3, "\u{3a9}\u{399}"), + (0x1FF4, "\u{38f}\u{399}"), + (0x1FF6, "\u{3a9}\u{342}"), + (0x1FF7, "\u{3a9}\u{342}\u{399}"), + (0x1FFC, "\u{3a9}\u{399}"), + (0x214E, "\u{2132}"), + (0x2170, "\u{2160}"), + (0x2171, "\u{2161}"), + (0x2172, "\u{2162}"), + (0x2173, "\u{2163}"), + (0x2174, "\u{2164}"), + (0x2175, "\u{2165}"), + (0x2176, "\u{2166}"), + (0x2177, "\u{2167}"), + (0x2178, "\u{2168}"), + (0x2179, "\u{2169}"), + (0x217A, "\u{216a}"), + (0x217B, "\u{216b}"), + (0x217C, "\u{216c}"), + (0x217D, "\u{216d}"), + (0x217E, "\u{216e}"), + (0x217F, "\u{216f}"), + (0x2184, "\u{2183}"), + (0x24D0, "\u{24b6}"), + (0x24D1, "\u{24b7}"), + (0x24D2, "\u{24b8}"), + (0x24D3, "\u{24b9}"), + (0x24D4, "\u{24ba}"), + (0x24D5, "\u{24bb}"), + (0x24D6, "\u{24bc}"), + (0x24D7, "\u{24bd}"), + (0x24D8, "\u{24be}"), + (0x24D9, "\u{24bf}"), + (0x24DA, "\u{24c0}"), + (0x24DB, "\u{24c1}"), + (0x24DC, "\u{24c2}"), + (0x24DD, "\u{24c3}"), + (0x24DE, "\u{24c4}"), + (0x24DF, "\u{24c5}"), + (0x24E0, "\u{24c6}"), + (0x24E1, "\u{24c7}"), + (0x24E2, "\u{24c8}"), + (0x24E3, "\u{24c9}"), + (0x24E4, "\u{24ca}"), + (0x24E5, "\u{24cb}"), + (0x24E6, "\u{24cc}"), + (0x24E7, "\u{24cd}"), + (0x24E8, "\u{24ce}"), + (0x24E9, "\u{24cf}"), + (0x2C30, "\u{2c00}"), + (0x2C31, "\u{2c01}"), + (0x2C32, "\u{2c02}"), + (0x2C33, "\u{2c03}"), + (0x2C34, "\u{2c04}"), + (0x2C35, "\u{2c05}"), + (0x2C36, "\u{2c06}"), + (0x2C37, "\u{2c07}"), + (0x2C38, "\u{2c08}"), + (0x2C39, "\u{2c09}"), + (0x2C3A, "\u{2c0a}"), + (0x2C3B, "\u{2c0b}"), + (0x2C3C, "\u{2c0c}"), + (0x2C3D, "\u{2c0d}"), + (0x2C3E, "\u{2c0e}"), + (0x2C3F, "\u{2c0f}"), + (0x2C40, "\u{2c10}"), + (0x2C41, "\u{2c11}"), + (0x2C42, "\u{2c12}"), + (0x2C43, "\u{2c13}"), + (0x2C44, "\u{2c14}"), + (0x2C45, "\u{2c15}"), + (0x2C46, "\u{2c16}"), + (0x2C47, "\u{2c17}"), + (0x2C48, "\u{2c18}"), + (0x2C49, "\u{2c19}"), + (0x2C4A, "\u{2c1a}"), + (0x2C4B, "\u{2c1b}"), + (0x2C4C, "\u{2c1c}"), + (0x2C4D, "\u{2c1d}"), + (0x2C4E, "\u{2c1e}"), + (0x2C4F, "\u{2c1f}"), + (0x2C50, "\u{2c20}"), + (0x2C51, "\u{2c21}"), + (0x2C52, "\u{2c22}"), + (0x2C53, "\u{2c23}"), + (0x2C54, "\u{2c24}"), + (0x2C55, "\u{2c25}"), + (0x2C56, "\u{2c26}"), + (0x2C57, "\u{2c27}"), + (0x2C58, "\u{2c28}"), + (0x2C59, "\u{2c29}"), + (0x2C5A, "\u{2c2a}"), + (0x2C5B, "\u{2c2b}"), + (0x2C5C, "\u{2c2c}"), + (0x2C5D, "\u{2c2d}"), + (0x2C5E, "\u{2c2e}"), + (0x2C5F, "\u{2c2f}"), + (0x2C61, "\u{2c60}"), + (0x2C65, "\u{23a}"), + (0x2C66, "\u{23e}"), + (0x2C68, "\u{2c67}"), + (0x2C6A, "\u{2c69}"), + (0x2C6C, "\u{2c6b}"), + (0x2C73, "\u{2c72}"), + (0x2C76, "\u{2c75}"), + (0x2C81, "\u{2c80}"), + (0x2C83, "\u{2c82}"), + (0x2C85, "\u{2c84}"), + (0x2C87, "\u{2c86}"), + (0x2C89, "\u{2c88}"), + (0x2C8B, "\u{2c8a}"), + (0x2C8D, "\u{2c8c}"), + (0x2C8F, "\u{2c8e}"), + (0x2C91, "\u{2c90}"), + (0x2C93, "\u{2c92}"), + (0x2C95, "\u{2c94}"), + (0x2C97, "\u{2c96}"), + (0x2C99, "\u{2c98}"), + (0x2C9B, "\u{2c9a}"), + (0x2C9D, "\u{2c9c}"), + (0x2C9F, "\u{2c9e}"), + (0x2CA1, "\u{2ca0}"), + (0x2CA3, "\u{2ca2}"), + (0x2CA5, "\u{2ca4}"), + (0x2CA7, "\u{2ca6}"), + (0x2CA9, "\u{2ca8}"), + (0x2CAB, "\u{2caa}"), + (0x2CAD, "\u{2cac}"), + (0x2CAF, "\u{2cae}"), + (0x2CB1, "\u{2cb0}"), + (0x2CB3, "\u{2cb2}"), + (0x2CB5, "\u{2cb4}"), + (0x2CB7, "\u{2cb6}"), + (0x2CB9, "\u{2cb8}"), + (0x2CBB, "\u{2cba}"), + (0x2CBD, "\u{2cbc}"), + (0x2CBF, "\u{2cbe}"), + (0x2CC1, "\u{2cc0}"), + (0x2CC3, "\u{2cc2}"), + (0x2CC5, "\u{2cc4}"), + (0x2CC7, "\u{2cc6}"), + (0x2CC9, "\u{2cc8}"), + (0x2CCB, "\u{2cca}"), + (0x2CCD, "\u{2ccc}"), + (0x2CCF, "\u{2cce}"), + (0x2CD1, "\u{2cd0}"), + (0x2CD3, "\u{2cd2}"), + (0x2CD5, "\u{2cd4}"), + (0x2CD7, "\u{2cd6}"), + (0x2CD9, "\u{2cd8}"), + (0x2CDB, "\u{2cda}"), + (0x2CDD, "\u{2cdc}"), + (0x2CDF, "\u{2cde}"), + (0x2CE1, "\u{2ce0}"), + (0x2CE3, "\u{2ce2}"), + (0x2CEC, "\u{2ceb}"), + (0x2CEE, "\u{2ced}"), + (0x2CF3, "\u{2cf2}"), + (0x2D00, "\u{10a0}"), + (0x2D01, "\u{10a1}"), + (0x2D02, "\u{10a2}"), + (0x2D03, "\u{10a3}"), + (0x2D04, "\u{10a4}"), + (0x2D05, "\u{10a5}"), + (0x2D06, "\u{10a6}"), + (0x2D07, "\u{10a7}"), + (0x2D08, "\u{10a8}"), + (0x2D09, "\u{10a9}"), + (0x2D0A, "\u{10aa}"), + (0x2D0B, "\u{10ab}"), + (0x2D0C, "\u{10ac}"), + (0x2D0D, "\u{10ad}"), + (0x2D0E, "\u{10ae}"), + (0x2D0F, "\u{10af}"), + (0x2D10, "\u{10b0}"), + (0x2D11, "\u{10b1}"), + (0x2D12, "\u{10b2}"), + (0x2D13, "\u{10b3}"), + (0x2D14, "\u{10b4}"), + (0x2D15, "\u{10b5}"), + (0x2D16, "\u{10b6}"), + (0x2D17, "\u{10b7}"), + (0x2D18, "\u{10b8}"), + (0x2D19, "\u{10b9}"), + (0x2D1A, "\u{10ba}"), + (0x2D1B, "\u{10bb}"), + (0x2D1C, "\u{10bc}"), + (0x2D1D, "\u{10bd}"), + (0x2D1E, "\u{10be}"), + (0x2D1F, "\u{10bf}"), + (0x2D20, "\u{10c0}"), + (0x2D21, "\u{10c1}"), + (0x2D22, "\u{10c2}"), + (0x2D23, "\u{10c3}"), + (0x2D24, "\u{10c4}"), + (0x2D25, "\u{10c5}"), + (0x2D27, "\u{10c7}"), + (0x2D2D, "\u{10cd}"), + (0xA641, "\u{a640}"), + (0xA643, "\u{a642}"), + (0xA645, "\u{a644}"), + (0xA647, "\u{a646}"), + (0xA649, "\u{a648}"), + (0xA64B, "\u{a64a}"), + (0xA64D, "\u{a64c}"), + (0xA64F, "\u{a64e}"), + (0xA651, "\u{a650}"), + (0xA653, "\u{a652}"), + (0xA655, "\u{a654}"), + (0xA657, "\u{a656}"), + (0xA659, "\u{a658}"), + (0xA65B, "\u{a65a}"), + (0xA65D, "\u{a65c}"), + (0xA65F, "\u{a65e}"), + (0xA661, "\u{a660}"), + (0xA663, "\u{a662}"), + (0xA665, "\u{a664}"), + (0xA667, "\u{a666}"), + (0xA669, "\u{a668}"), + (0xA66B, "\u{a66a}"), + (0xA66D, "\u{a66c}"), + (0xA681, "\u{a680}"), + (0xA683, "\u{a682}"), + (0xA685, "\u{a684}"), + (0xA687, "\u{a686}"), + (0xA689, "\u{a688}"), + (0xA68B, "\u{a68a}"), + (0xA68D, "\u{a68c}"), + (0xA68F, "\u{a68e}"), + (0xA691, "\u{a690}"), + (0xA693, "\u{a692}"), + (0xA695, "\u{a694}"), + (0xA697, "\u{a696}"), + (0xA699, "\u{a698}"), + (0xA69B, "\u{a69a}"), + (0xA723, "\u{a722}"), + (0xA725, "\u{a724}"), + (0xA727, "\u{a726}"), + (0xA729, "\u{a728}"), + (0xA72B, "\u{a72a}"), + (0xA72D, "\u{a72c}"), + (0xA72F, "\u{a72e}"), + (0xA733, "\u{a732}"), + (0xA735, "\u{a734}"), + (0xA737, "\u{a736}"), + (0xA739, "\u{a738}"), + (0xA73B, "\u{a73a}"), + (0xA73D, "\u{a73c}"), + (0xA73F, "\u{a73e}"), + (0xA741, "\u{a740}"), + (0xA743, "\u{a742}"), + (0xA745, "\u{a744}"), + (0xA747, "\u{a746}"), + (0xA749, "\u{a748}"), + (0xA74B, "\u{a74a}"), + (0xA74D, "\u{a74c}"), + (0xA74F, "\u{a74e}"), + (0xA751, "\u{a750}"), + (0xA753, "\u{a752}"), + (0xA755, "\u{a754}"), + (0xA757, "\u{a756}"), + (0xA759, "\u{a758}"), + (0xA75B, "\u{a75a}"), + (0xA75D, "\u{a75c}"), + (0xA75F, "\u{a75e}"), + (0xA761, "\u{a760}"), + (0xA763, "\u{a762}"), + (0xA765, "\u{a764}"), + (0xA767, "\u{a766}"), + (0xA769, "\u{a768}"), + (0xA76B, "\u{a76a}"), + (0xA76D, "\u{a76c}"), + (0xA76F, "\u{a76e}"), + (0xA77A, "\u{a779}"), + (0xA77C, "\u{a77b}"), + (0xA77F, "\u{a77e}"), + (0xA781, "\u{a780}"), + (0xA783, "\u{a782}"), + (0xA785, "\u{a784}"), + (0xA787, "\u{a786}"), + (0xA78C, "\u{a78b}"), + (0xA791, "\u{a790}"), + (0xA793, "\u{a792}"), + (0xA794, "\u{a7c4}"), + (0xA797, "\u{a796}"), + (0xA799, "\u{a798}"), + (0xA79B, "\u{a79a}"), + (0xA79D, "\u{a79c}"), + (0xA79F, "\u{a79e}"), + (0xA7A1, "\u{a7a0}"), + (0xA7A3, "\u{a7a2}"), + (0xA7A5, "\u{a7a4}"), + (0xA7A7, "\u{a7a6}"), + (0xA7A9, "\u{a7a8}"), + (0xA7B5, "\u{a7b4}"), + (0xA7B7, "\u{a7b6}"), + (0xA7B9, "\u{a7b8}"), + (0xA7BB, "\u{a7ba}"), + (0xA7BD, "\u{a7bc}"), + (0xA7BF, "\u{a7be}"), + (0xA7C1, "\u{a7c0}"), + (0xA7C3, "\u{a7c2}"), + (0xA7C8, "\u{a7c7}"), + (0xA7CA, "\u{a7c9}"), + (0xA7D1, "\u{a7d0}"), + (0xA7D7, "\u{a7d6}"), + (0xA7D9, "\u{a7d8}"), + (0xA7F6, "\u{a7f5}"), + (0xAB53, "\u{a7b3}"), + (0xAB70, "\u{13a0}"), + (0xAB71, "\u{13a1}"), + (0xAB72, "\u{13a2}"), + (0xAB73, "\u{13a3}"), + (0xAB74, "\u{13a4}"), + (0xAB75, "\u{13a5}"), + (0xAB76, "\u{13a6}"), + (0xAB77, "\u{13a7}"), + (0xAB78, "\u{13a8}"), + (0xAB79, "\u{13a9}"), + (0xAB7A, "\u{13aa}"), + (0xAB7B, "\u{13ab}"), + (0xAB7C, "\u{13ac}"), + (0xAB7D, "\u{13ad}"), + (0xAB7E, "\u{13ae}"), + (0xAB7F, "\u{13af}"), + (0xAB80, "\u{13b0}"), + (0xAB81, "\u{13b1}"), + (0xAB82, "\u{13b2}"), + (0xAB83, "\u{13b3}"), + (0xAB84, "\u{13b4}"), + (0xAB85, "\u{13b5}"), + (0xAB86, "\u{13b6}"), + (0xAB87, "\u{13b7}"), + (0xAB88, "\u{13b8}"), + (0xAB89, "\u{13b9}"), + (0xAB8A, "\u{13ba}"), + (0xAB8B, "\u{13bb}"), + (0xAB8C, "\u{13bc}"), + (0xAB8D, "\u{13bd}"), + (0xAB8E, "\u{13be}"), + (0xAB8F, "\u{13bf}"), + (0xAB90, "\u{13c0}"), + (0xAB91, "\u{13c1}"), + (0xAB92, "\u{13c2}"), + (0xAB93, "\u{13c3}"), + (0xAB94, "\u{13c4}"), + (0xAB95, "\u{13c5}"), + (0xAB96, "\u{13c6}"), + (0xAB97, "\u{13c7}"), + (0xAB98, "\u{13c8}"), + (0xAB99, "\u{13c9}"), + (0xAB9A, "\u{13ca}"), + (0xAB9B, "\u{13cb}"), + (0xAB9C, "\u{13cc}"), + (0xAB9D, "\u{13cd}"), + (0xAB9E, "\u{13ce}"), + (0xAB9F, "\u{13cf}"), + (0xABA0, "\u{13d0}"), + (0xABA1, "\u{13d1}"), + (0xABA2, "\u{13d2}"), + (0xABA3, "\u{13d3}"), + (0xABA4, "\u{13d4}"), + (0xABA5, "\u{13d5}"), + (0xABA6, "\u{13d6}"), + (0xABA7, "\u{13d7}"), + (0xABA8, "\u{13d8}"), + (0xABA9, "\u{13d9}"), + (0xABAA, "\u{13da}"), + (0xABAB, "\u{13db}"), + (0xABAC, "\u{13dc}"), + (0xABAD, "\u{13dd}"), + (0xABAE, "\u{13de}"), + (0xABAF, "\u{13df}"), + (0xABB0, "\u{13e0}"), + (0xABB1, "\u{13e1}"), + (0xABB2, "\u{13e2}"), + (0xABB3, "\u{13e3}"), + (0xABB4, "\u{13e4}"), + (0xABB5, "\u{13e5}"), + (0xABB6, "\u{13e6}"), + (0xABB7, "\u{13e7}"), + (0xABB8, "\u{13e8}"), + (0xABB9, "\u{13e9}"), + (0xABBA, "\u{13ea}"), + (0xABBB, "\u{13eb}"), + (0xABBC, "\u{13ec}"), + (0xABBD, "\u{13ed}"), + (0xABBE, "\u{13ee}"), + (0xABBF, "\u{13ef}"), + (0xFB00, "\u{46}\u{46}"), + (0xFB01, "\u{46}\u{49}"), + (0xFB02, "\u{46}\u{4c}"), + (0xFB03, "\u{46}\u{46}\u{49}"), + (0xFB04, "\u{46}\u{46}\u{4c}"), + (0xFB05, "\u{53}\u{54}"), + (0xFB06, "\u{53}\u{54}"), + (0xFB13, "\u{544}\u{546}"), + (0xFB14, "\u{544}\u{535}"), + (0xFB15, "\u{544}\u{53b}"), + (0xFB16, "\u{54e}\u{546}"), + (0xFB17, "\u{544}\u{53d}"), + (0xFF41, "\u{ff21}"), + (0xFF42, "\u{ff22}"), + (0xFF43, "\u{ff23}"), + (0xFF44, "\u{ff24}"), + (0xFF45, "\u{ff25}"), + (0xFF46, "\u{ff26}"), + (0xFF47, "\u{ff27}"), + (0xFF48, "\u{ff28}"), + (0xFF49, "\u{ff29}"), + (0xFF4A, "\u{ff2a}"), + (0xFF4B, "\u{ff2b}"), + (0xFF4C, "\u{ff2c}"), + (0xFF4D, "\u{ff2d}"), + (0xFF4E, "\u{ff2e}"), + (0xFF4F, "\u{ff2f}"), + (0xFF50, "\u{ff30}"), + (0xFF51, "\u{ff31}"), + (0xFF52, "\u{ff32}"), + (0xFF53, "\u{ff33}"), + (0xFF54, "\u{ff34}"), + (0xFF55, "\u{ff35}"), + (0xFF56, "\u{ff36}"), + (0xFF57, "\u{ff37}"), + (0xFF58, "\u{ff38}"), + (0xFF59, "\u{ff39}"), + (0xFF5A, "\u{ff3a}"), + (0x10428, "\u{10400}"), + (0x10429, "\u{10401}"), + (0x1042A, "\u{10402}"), + (0x1042B, "\u{10403}"), + (0x1042C, "\u{10404}"), + (0x1042D, "\u{10405}"), + (0x1042E, "\u{10406}"), + (0x1042F, "\u{10407}"), + (0x10430, "\u{10408}"), + (0x10431, "\u{10409}"), + (0x10432, "\u{1040a}"), + (0x10433, "\u{1040b}"), + (0x10434, "\u{1040c}"), + (0x10435, "\u{1040d}"), + (0x10436, "\u{1040e}"), + (0x10437, "\u{1040f}"), + (0x10438, "\u{10410}"), + (0x10439, "\u{10411}"), + (0x1043A, "\u{10412}"), + (0x1043B, "\u{10413}"), + (0x1043C, "\u{10414}"), + (0x1043D, "\u{10415}"), + (0x1043E, "\u{10416}"), + (0x1043F, "\u{10417}"), + (0x10440, "\u{10418}"), + (0x10441, "\u{10419}"), + (0x10442, "\u{1041a}"), + (0x10443, "\u{1041b}"), + (0x10444, "\u{1041c}"), + (0x10445, "\u{1041d}"), + (0x10446, "\u{1041e}"), + (0x10447, "\u{1041f}"), + (0x10448, "\u{10420}"), + (0x10449, "\u{10421}"), + (0x1044A, "\u{10422}"), + (0x1044B, "\u{10423}"), + (0x1044C, "\u{10424}"), + (0x1044D, "\u{10425}"), + (0x1044E, "\u{10426}"), + (0x1044F, "\u{10427}"), + (0x104D8, "\u{104b0}"), + (0x104D9, "\u{104b1}"), + (0x104DA, "\u{104b2}"), + (0x104DB, "\u{104b3}"), + (0x104DC, "\u{104b4}"), + (0x104DD, "\u{104b5}"), + (0x104DE, "\u{104b6}"), + (0x104DF, "\u{104b7}"), + (0x104E0, "\u{104b8}"), + (0x104E1, "\u{104b9}"), + (0x104E2, "\u{104ba}"), + (0x104E3, "\u{104bb}"), + (0x104E4, "\u{104bc}"), + (0x104E5, "\u{104bd}"), + (0x104E6, "\u{104be}"), + (0x104E7, "\u{104bf}"), + (0x104E8, "\u{104c0}"), + (0x104E9, "\u{104c1}"), + (0x104EA, "\u{104c2}"), + (0x104EB, "\u{104c3}"), + (0x104EC, "\u{104c4}"), + (0x104ED, "\u{104c5}"), + (0x104EE, "\u{104c6}"), + (0x104EF, "\u{104c7}"), + (0x104F0, "\u{104c8}"), + (0x104F1, "\u{104c9}"), + (0x104F2, "\u{104ca}"), + (0x104F3, "\u{104cb}"), + (0x104F4, "\u{104cc}"), + (0x104F5, "\u{104cd}"), + (0x104F6, "\u{104ce}"), + (0x104F7, "\u{104cf}"), + (0x104F8, "\u{104d0}"), + (0x104F9, "\u{104d1}"), + (0x104FA, "\u{104d2}"), + (0x104FB, "\u{104d3}"), + (0x10597, "\u{10570}"), + (0x10598, "\u{10571}"), + (0x10599, "\u{10572}"), + (0x1059A, "\u{10573}"), + (0x1059B, "\u{10574}"), + (0x1059C, "\u{10575}"), + (0x1059D, "\u{10576}"), + (0x1059E, "\u{10577}"), + (0x1059F, "\u{10578}"), + (0x105A0, "\u{10579}"), + (0x105A1, "\u{1057a}"), + (0x105A3, "\u{1057c}"), + (0x105A4, "\u{1057d}"), + (0x105A5, "\u{1057e}"), + (0x105A6, "\u{1057f}"), + (0x105A7, "\u{10580}"), + (0x105A8, "\u{10581}"), + (0x105A9, "\u{10582}"), + (0x105AA, "\u{10583}"), + (0x105AB, "\u{10584}"), + (0x105AC, "\u{10585}"), + (0x105AD, "\u{10586}"), + (0x105AE, "\u{10587}"), + (0x105AF, "\u{10588}"), + (0x105B0, "\u{10589}"), + (0x105B1, "\u{1058a}"), + (0x105B3, "\u{1058c}"), + (0x105B4, "\u{1058d}"), + (0x105B5, "\u{1058e}"), + (0x105B6, "\u{1058f}"), + (0x105B7, "\u{10590}"), + (0x105B8, "\u{10591}"), + (0x105B9, "\u{10592}"), + (0x105BB, "\u{10594}"), + (0x105BC, "\u{10595}"), + (0x10CC0, "\u{10c80}"), + (0x10CC1, "\u{10c81}"), + (0x10CC2, "\u{10c82}"), + (0x10CC3, "\u{10c83}"), + (0x10CC4, "\u{10c84}"), + (0x10CC5, "\u{10c85}"), + (0x10CC6, "\u{10c86}"), + (0x10CC7, "\u{10c87}"), + (0x10CC8, "\u{10c88}"), + (0x10CC9, "\u{10c89}"), + (0x10CCA, "\u{10c8a}"), + (0x10CCB, "\u{10c8b}"), + (0x10CCC, "\u{10c8c}"), + (0x10CCD, "\u{10c8d}"), + (0x10CCE, "\u{10c8e}"), + (0x10CCF, "\u{10c8f}"), + (0x10CD0, "\u{10c90}"), + (0x10CD1, "\u{10c91}"), + (0x10CD2, "\u{10c92}"), + (0x10CD3, "\u{10c93}"), + (0x10CD4, "\u{10c94}"), + (0x10CD5, "\u{10c95}"), + (0x10CD6, "\u{10c96}"), + (0x10CD7, "\u{10c97}"), + (0x10CD8, "\u{10c98}"), + (0x10CD9, "\u{10c99}"), + (0x10CDA, "\u{10c9a}"), + (0x10CDB, "\u{10c9b}"), + (0x10CDC, "\u{10c9c}"), + (0x10CDD, "\u{10c9d}"), + (0x10CDE, "\u{10c9e}"), + (0x10CDF, "\u{10c9f}"), + (0x10CE0, "\u{10ca0}"), + (0x10CE1, "\u{10ca1}"), + (0x10CE2, "\u{10ca2}"), + (0x10CE3, "\u{10ca3}"), + (0x10CE4, "\u{10ca4}"), + (0x10CE5, "\u{10ca5}"), + (0x10CE6, "\u{10ca6}"), + (0x10CE7, "\u{10ca7}"), + (0x10CE8, "\u{10ca8}"), + (0x10CE9, "\u{10ca9}"), + (0x10CEA, "\u{10caa}"), + (0x10CEB, "\u{10cab}"), + (0x10CEC, "\u{10cac}"), + (0x10CED, "\u{10cad}"), + (0x10CEE, "\u{10cae}"), + (0x10CEF, "\u{10caf}"), + (0x10CF0, "\u{10cb0}"), + (0x10CF1, "\u{10cb1}"), + (0x10CF2, "\u{10cb2}"), + (0x118C0, "\u{118a0}"), + (0x118C1, "\u{118a1}"), + (0x118C2, "\u{118a2}"), + (0x118C3, "\u{118a3}"), + (0x118C4, "\u{118a4}"), + (0x118C5, "\u{118a5}"), + (0x118C6, "\u{118a6}"), + (0x118C7, "\u{118a7}"), + (0x118C8, "\u{118a8}"), + (0x118C9, "\u{118a9}"), + (0x118CA, "\u{118aa}"), + (0x118CB, "\u{118ab}"), + (0x118CC, "\u{118ac}"), + (0x118CD, "\u{118ad}"), + (0x118CE, "\u{118ae}"), + (0x118CF, "\u{118af}"), + (0x118D0, "\u{118b0}"), + (0x118D1, "\u{118b1}"), + (0x118D2, "\u{118b2}"), + (0x118D3, "\u{118b3}"), + (0x118D4, "\u{118b4}"), + (0x118D5, "\u{118b5}"), + (0x118D6, "\u{118b6}"), + (0x118D7, "\u{118b7}"), + (0x118D8, "\u{118b8}"), + (0x118D9, "\u{118b9}"), + (0x118DA, "\u{118ba}"), + (0x118DB, "\u{118bb}"), + (0x118DC, "\u{118bc}"), + (0x118DD, "\u{118bd}"), + (0x118DE, "\u{118be}"), + (0x118DF, "\u{118bf}"), + (0x16E60, "\u{16e40}"), + (0x16E61, "\u{16e41}"), + (0x16E62, "\u{16e42}"), + (0x16E63, "\u{16e43}"), + (0x16E64, "\u{16e44}"), + (0x16E65, "\u{16e45}"), + (0x16E66, "\u{16e46}"), + (0x16E67, "\u{16e47}"), + (0x16E68, "\u{16e48}"), + (0x16E69, "\u{16e49}"), + (0x16E6A, "\u{16e4a}"), + (0x16E6B, "\u{16e4b}"), + (0x16E6C, "\u{16e4c}"), + (0x16E6D, "\u{16e4d}"), + (0x16E6E, "\u{16e4e}"), + (0x16E6F, "\u{16e4f}"), + (0x16E70, "\u{16e50}"), + (0x16E71, "\u{16e51}"), + (0x16E72, "\u{16e52}"), + (0x16E73, "\u{16e53}"), + (0x16E74, "\u{16e54}"), + (0x16E75, "\u{16e55}"), + (0x16E76, "\u{16e56}"), + (0x16E77, "\u{16e57}"), + (0x16E78, "\u{16e58}"), + (0x16E79, "\u{16e59}"), + (0x16E7A, "\u{16e5a}"), + (0x16E7B, "\u{16e5b}"), + (0x16E7C, "\u{16e5c}"), + (0x16E7D, "\u{16e5d}"), + (0x16E7E, "\u{16e5e}"), + (0x16E7F, "\u{16e5f}"), + (0x1E922, "\u{1e900}"), + (0x1E923, "\u{1e901}"), + (0x1E924, "\u{1e902}"), + (0x1E925, "\u{1e903}"), + (0x1E926, "\u{1e904}"), + (0x1E927, "\u{1e905}"), + (0x1E928, "\u{1e906}"), + (0x1E929, "\u{1e907}"), + (0x1E92A, "\u{1e908}"), + (0x1E92B, "\u{1e909}"), + (0x1E92C, "\u{1e90a}"), + (0x1E92D, "\u{1e90b}"), + (0x1E92E, "\u{1e90c}"), + (0x1E92F, "\u{1e90d}"), + (0x1E930, "\u{1e90e}"), + (0x1E931, "\u{1e90f}"), + (0x1E932, "\u{1e910}"), + (0x1E933, "\u{1e911}"), + (0x1E934, "\u{1e912}"), + (0x1E935, "\u{1e913}"), + (0x1E936, "\u{1e914}"), + (0x1E937, "\u{1e915}"), + (0x1E938, "\u{1e916}"), + (0x1E939, "\u{1e917}"), + (0x1E93A, "\u{1e918}"), + (0x1E93B, "\u{1e919}"), + (0x1E93C, "\u{1e91a}"), + (0x1E93D, "\u{1e91b}"), + (0x1E93E, "\u{1e91c}"), + (0x1E93F, "\u{1e91d}"), + (0x1E940, "\u{1e91e}"), + (0x1E941, "\u{1e91f}"), + (0x1E942, "\u{1e920}"), + (0x1E943, "\u{1e921}"), +] diff --git a/crates/sqlbuild-core/src/text/upper_mappings/unicode_15_1_0.in b/crates/sqlbuild-core/src/text/upper_mappings/unicode_15_1_0.in new file mode 100644 index 0000000000..7638290364 --- /dev/null +++ b/crates/sqlbuild-core/src/text/upper_mappings/unicode_15_1_0.in @@ -0,0 +1,1529 @@ +// Generated by `scripts/generate_python_char_table.py`; do not edit. +// Every character `str.upper()` changes in Unicode 15.1.0, in code point order. +&[ + (0x0061, "\u{41}"), + (0x0062, "\u{42}"), + (0x0063, "\u{43}"), + (0x0064, "\u{44}"), + (0x0065, "\u{45}"), + (0x0066, "\u{46}"), + (0x0067, "\u{47}"), + (0x0068, "\u{48}"), + (0x0069, "\u{49}"), + (0x006A, "\u{4a}"), + (0x006B, "\u{4b}"), + (0x006C, "\u{4c}"), + (0x006D, "\u{4d}"), + (0x006E, "\u{4e}"), + (0x006F, "\u{4f}"), + (0x0070, "\u{50}"), + (0x0071, "\u{51}"), + (0x0072, "\u{52}"), + (0x0073, "\u{53}"), + (0x0074, "\u{54}"), + (0x0075, "\u{55}"), + (0x0076, "\u{56}"), + (0x0077, "\u{57}"), + (0x0078, "\u{58}"), + (0x0079, "\u{59}"), + (0x007A, "\u{5a}"), + (0x00B5, "\u{39c}"), + (0x00DF, "\u{53}\u{53}"), + (0x00E0, "\u{c0}"), + (0x00E1, "\u{c1}"), + (0x00E2, "\u{c2}"), + (0x00E3, "\u{c3}"), + (0x00E4, "\u{c4}"), + (0x00E5, "\u{c5}"), + (0x00E6, "\u{c6}"), + (0x00E7, "\u{c7}"), + (0x00E8, "\u{c8}"), + (0x00E9, "\u{c9}"), + (0x00EA, "\u{ca}"), + (0x00EB, "\u{cb}"), + (0x00EC, "\u{cc}"), + (0x00ED, "\u{cd}"), + (0x00EE, "\u{ce}"), + (0x00EF, "\u{cf}"), + (0x00F0, "\u{d0}"), + (0x00F1, "\u{d1}"), + (0x00F2, "\u{d2}"), + (0x00F3, "\u{d3}"), + (0x00F4, "\u{d4}"), + (0x00F5, "\u{d5}"), + (0x00F6, "\u{d6}"), + (0x00F8, "\u{d8}"), + (0x00F9, "\u{d9}"), + (0x00FA, "\u{da}"), + (0x00FB, "\u{db}"), + (0x00FC, "\u{dc}"), + (0x00FD, "\u{dd}"), + (0x00FE, "\u{de}"), + (0x00FF, "\u{178}"), + (0x0101, "\u{100}"), + (0x0103, "\u{102}"), + (0x0105, "\u{104}"), + (0x0107, "\u{106}"), + (0x0109, "\u{108}"), + (0x010B, "\u{10a}"), + (0x010D, "\u{10c}"), + (0x010F, "\u{10e}"), + (0x0111, "\u{110}"), + (0x0113, "\u{112}"), + (0x0115, "\u{114}"), + (0x0117, "\u{116}"), + (0x0119, "\u{118}"), + (0x011B, "\u{11a}"), + (0x011D, "\u{11c}"), + (0x011F, "\u{11e}"), + (0x0121, "\u{120}"), + (0x0123, "\u{122}"), + (0x0125, "\u{124}"), + (0x0127, "\u{126}"), + (0x0129, "\u{128}"), + (0x012B, "\u{12a}"), + (0x012D, "\u{12c}"), + (0x012F, "\u{12e}"), + (0x0131, "\u{49}"), + (0x0133, "\u{132}"), + (0x0135, "\u{134}"), + (0x0137, "\u{136}"), + (0x013A, "\u{139}"), + (0x013C, "\u{13b}"), + (0x013E, "\u{13d}"), + (0x0140, "\u{13f}"), + (0x0142, "\u{141}"), + (0x0144, "\u{143}"), + (0x0146, "\u{145}"), + (0x0148, "\u{147}"), + (0x0149, "\u{2bc}\u{4e}"), + (0x014B, "\u{14a}"), + (0x014D, "\u{14c}"), + (0x014F, "\u{14e}"), + (0x0151, "\u{150}"), + (0x0153, "\u{152}"), + (0x0155, "\u{154}"), + (0x0157, "\u{156}"), + (0x0159, "\u{158}"), + (0x015B, "\u{15a}"), + (0x015D, "\u{15c}"), + (0x015F, "\u{15e}"), + (0x0161, "\u{160}"), + (0x0163, "\u{162}"), + (0x0165, "\u{164}"), + (0x0167, "\u{166}"), + (0x0169, "\u{168}"), + (0x016B, "\u{16a}"), + (0x016D, "\u{16c}"), + (0x016F, "\u{16e}"), + (0x0171, "\u{170}"), + (0x0173, "\u{172}"), + (0x0175, "\u{174}"), + (0x0177, "\u{176}"), + (0x017A, "\u{179}"), + (0x017C, "\u{17b}"), + (0x017E, "\u{17d}"), + (0x017F, "\u{53}"), + (0x0180, "\u{243}"), + (0x0183, "\u{182}"), + (0x0185, "\u{184}"), + (0x0188, "\u{187}"), + (0x018C, "\u{18b}"), + (0x0192, "\u{191}"), + (0x0195, "\u{1f6}"), + (0x0199, "\u{198}"), + (0x019A, "\u{23d}"), + (0x019E, "\u{220}"), + (0x01A1, "\u{1a0}"), + (0x01A3, "\u{1a2}"), + (0x01A5, "\u{1a4}"), + (0x01A8, "\u{1a7}"), + (0x01AD, "\u{1ac}"), + (0x01B0, "\u{1af}"), + (0x01B4, "\u{1b3}"), + (0x01B6, "\u{1b5}"), + (0x01B9, "\u{1b8}"), + (0x01BD, "\u{1bc}"), + (0x01BF, "\u{1f7}"), + (0x01C5, "\u{1c4}"), + (0x01C6, "\u{1c4}"), + (0x01C8, "\u{1c7}"), + (0x01C9, "\u{1c7}"), + (0x01CB, "\u{1ca}"), + (0x01CC, "\u{1ca}"), + (0x01CE, "\u{1cd}"), + (0x01D0, "\u{1cf}"), + (0x01D2, "\u{1d1}"), + (0x01D4, "\u{1d3}"), + (0x01D6, "\u{1d5}"), + (0x01D8, "\u{1d7}"), + (0x01DA, "\u{1d9}"), + (0x01DC, "\u{1db}"), + (0x01DD, "\u{18e}"), + (0x01DF, "\u{1de}"), + (0x01E1, "\u{1e0}"), + (0x01E3, "\u{1e2}"), + (0x01E5, "\u{1e4}"), + (0x01E7, "\u{1e6}"), + (0x01E9, "\u{1e8}"), + (0x01EB, "\u{1ea}"), + (0x01ED, "\u{1ec}"), + (0x01EF, "\u{1ee}"), + (0x01F0, "\u{4a}\u{30c}"), + (0x01F2, "\u{1f1}"), + (0x01F3, "\u{1f1}"), + (0x01F5, "\u{1f4}"), + (0x01F9, "\u{1f8}"), + (0x01FB, "\u{1fa}"), + (0x01FD, "\u{1fc}"), + (0x01FF, "\u{1fe}"), + (0x0201, "\u{200}"), + (0x0203, "\u{202}"), + (0x0205, "\u{204}"), + (0x0207, "\u{206}"), + (0x0209, "\u{208}"), + (0x020B, "\u{20a}"), + (0x020D, "\u{20c}"), + (0x020F, "\u{20e}"), + (0x0211, "\u{210}"), + (0x0213, "\u{212}"), + (0x0215, "\u{214}"), + (0x0217, "\u{216}"), + (0x0219, "\u{218}"), + (0x021B, "\u{21a}"), + (0x021D, "\u{21c}"), + (0x021F, "\u{21e}"), + (0x0223, "\u{222}"), + (0x0225, "\u{224}"), + (0x0227, "\u{226}"), + (0x0229, "\u{228}"), + (0x022B, "\u{22a}"), + (0x022D, "\u{22c}"), + (0x022F, "\u{22e}"), + (0x0231, "\u{230}"), + (0x0233, "\u{232}"), + (0x023C, "\u{23b}"), + (0x023F, "\u{2c7e}"), + (0x0240, "\u{2c7f}"), + (0x0242, "\u{241}"), + (0x0247, "\u{246}"), + (0x0249, "\u{248}"), + (0x024B, "\u{24a}"), + (0x024D, "\u{24c}"), + (0x024F, "\u{24e}"), + (0x0250, "\u{2c6f}"), + (0x0251, "\u{2c6d}"), + (0x0252, "\u{2c70}"), + (0x0253, "\u{181}"), + (0x0254, "\u{186}"), + (0x0256, "\u{189}"), + (0x0257, "\u{18a}"), + (0x0259, "\u{18f}"), + (0x025B, "\u{190}"), + (0x025C, "\u{a7ab}"), + (0x0260, "\u{193}"), + (0x0261, "\u{a7ac}"), + (0x0263, "\u{194}"), + (0x0265, "\u{a78d}"), + (0x0266, "\u{a7aa}"), + (0x0268, "\u{197}"), + (0x0269, "\u{196}"), + (0x026A, "\u{a7ae}"), + (0x026B, "\u{2c62}"), + (0x026C, "\u{a7ad}"), + (0x026F, "\u{19c}"), + (0x0271, "\u{2c6e}"), + (0x0272, "\u{19d}"), + (0x0275, "\u{19f}"), + (0x027D, "\u{2c64}"), + (0x0280, "\u{1a6}"), + (0x0282, "\u{a7c5}"), + (0x0283, "\u{1a9}"), + (0x0287, "\u{a7b1}"), + (0x0288, "\u{1ae}"), + (0x0289, "\u{244}"), + (0x028A, "\u{1b1}"), + (0x028B, "\u{1b2}"), + (0x028C, "\u{245}"), + (0x0292, "\u{1b7}"), + (0x029D, "\u{a7b2}"), + (0x029E, "\u{a7b0}"), + (0x0345, "\u{399}"), + (0x0371, "\u{370}"), + (0x0373, "\u{372}"), + (0x0377, "\u{376}"), + (0x037B, "\u{3fd}"), + (0x037C, "\u{3fe}"), + (0x037D, "\u{3ff}"), + (0x0390, "\u{399}\u{308}\u{301}"), + (0x03AC, "\u{386}"), + (0x03AD, "\u{388}"), + (0x03AE, "\u{389}"), + (0x03AF, "\u{38a}"), + (0x03B0, "\u{3a5}\u{308}\u{301}"), + (0x03B1, "\u{391}"), + (0x03B2, "\u{392}"), + (0x03B3, "\u{393}"), + (0x03B4, "\u{394}"), + (0x03B5, "\u{395}"), + (0x03B6, "\u{396}"), + (0x03B7, "\u{397}"), + (0x03B8, "\u{398}"), + (0x03B9, "\u{399}"), + (0x03BA, "\u{39a}"), + (0x03BB, "\u{39b}"), + (0x03BC, "\u{39c}"), + (0x03BD, "\u{39d}"), + (0x03BE, "\u{39e}"), + (0x03BF, "\u{39f}"), + (0x03C0, "\u{3a0}"), + (0x03C1, "\u{3a1}"), + (0x03C2, "\u{3a3}"), + (0x03C3, "\u{3a3}"), + (0x03C4, "\u{3a4}"), + (0x03C5, "\u{3a5}"), + (0x03C6, "\u{3a6}"), + (0x03C7, "\u{3a7}"), + (0x03C8, "\u{3a8}"), + (0x03C9, "\u{3a9}"), + (0x03CA, "\u{3aa}"), + (0x03CB, "\u{3ab}"), + (0x03CC, "\u{38c}"), + (0x03CD, "\u{38e}"), + (0x03CE, "\u{38f}"), + (0x03D0, "\u{392}"), + (0x03D1, "\u{398}"), + (0x03D5, "\u{3a6}"), + (0x03D6, "\u{3a0}"), + (0x03D7, "\u{3cf}"), + (0x03D9, "\u{3d8}"), + (0x03DB, "\u{3da}"), + (0x03DD, "\u{3dc}"), + (0x03DF, "\u{3de}"), + (0x03E1, "\u{3e0}"), + (0x03E3, "\u{3e2}"), + (0x03E5, "\u{3e4}"), + (0x03E7, "\u{3e6}"), + (0x03E9, "\u{3e8}"), + (0x03EB, "\u{3ea}"), + (0x03ED, "\u{3ec}"), + (0x03EF, "\u{3ee}"), + (0x03F0, "\u{39a}"), + (0x03F1, "\u{3a1}"), + (0x03F2, "\u{3f9}"), + (0x03F3, "\u{37f}"), + (0x03F5, "\u{395}"), + (0x03F8, "\u{3f7}"), + (0x03FB, "\u{3fa}"), + (0x0430, "\u{410}"), + (0x0431, "\u{411}"), + (0x0432, "\u{412}"), + (0x0433, "\u{413}"), + (0x0434, "\u{414}"), + (0x0435, "\u{415}"), + (0x0436, "\u{416}"), + (0x0437, "\u{417}"), + (0x0438, "\u{418}"), + (0x0439, "\u{419}"), + (0x043A, "\u{41a}"), + (0x043B, "\u{41b}"), + (0x043C, "\u{41c}"), + (0x043D, "\u{41d}"), + (0x043E, "\u{41e}"), + (0x043F, "\u{41f}"), + (0x0440, "\u{420}"), + (0x0441, "\u{421}"), + (0x0442, "\u{422}"), + (0x0443, "\u{423}"), + (0x0444, "\u{424}"), + (0x0445, "\u{425}"), + (0x0446, "\u{426}"), + (0x0447, "\u{427}"), + (0x0448, "\u{428}"), + (0x0449, "\u{429}"), + (0x044A, "\u{42a}"), + (0x044B, "\u{42b}"), + (0x044C, "\u{42c}"), + (0x044D, "\u{42d}"), + (0x044E, "\u{42e}"), + (0x044F, "\u{42f}"), + (0x0450, "\u{400}"), + (0x0451, "\u{401}"), + (0x0452, "\u{402}"), + (0x0453, "\u{403}"), + (0x0454, "\u{404}"), + (0x0455, "\u{405}"), + (0x0456, "\u{406}"), + (0x0457, "\u{407}"), + (0x0458, "\u{408}"), + (0x0459, "\u{409}"), + (0x045A, "\u{40a}"), + (0x045B, "\u{40b}"), + (0x045C, "\u{40c}"), + (0x045D, "\u{40d}"), + (0x045E, "\u{40e}"), + (0x045F, "\u{40f}"), + (0x0461, "\u{460}"), + (0x0463, "\u{462}"), + (0x0465, "\u{464}"), + (0x0467, "\u{466}"), + (0x0469, "\u{468}"), + (0x046B, "\u{46a}"), + (0x046D, "\u{46c}"), + (0x046F, "\u{46e}"), + (0x0471, "\u{470}"), + (0x0473, "\u{472}"), + (0x0475, "\u{474}"), + (0x0477, "\u{476}"), + (0x0479, "\u{478}"), + (0x047B, "\u{47a}"), + (0x047D, "\u{47c}"), + (0x047F, "\u{47e}"), + (0x0481, "\u{480}"), + (0x048B, "\u{48a}"), + (0x048D, "\u{48c}"), + (0x048F, "\u{48e}"), + (0x0491, "\u{490}"), + (0x0493, "\u{492}"), + (0x0495, "\u{494}"), + (0x0497, "\u{496}"), + (0x0499, "\u{498}"), + (0x049B, "\u{49a}"), + (0x049D, "\u{49c}"), + (0x049F, "\u{49e}"), + (0x04A1, "\u{4a0}"), + (0x04A3, "\u{4a2}"), + (0x04A5, "\u{4a4}"), + (0x04A7, "\u{4a6}"), + (0x04A9, "\u{4a8}"), + (0x04AB, "\u{4aa}"), + (0x04AD, "\u{4ac}"), + (0x04AF, "\u{4ae}"), + (0x04B1, "\u{4b0}"), + (0x04B3, "\u{4b2}"), + (0x04B5, "\u{4b4}"), + (0x04B7, "\u{4b6}"), + (0x04B9, "\u{4b8}"), + (0x04BB, "\u{4ba}"), + (0x04BD, "\u{4bc}"), + (0x04BF, "\u{4be}"), + (0x04C2, "\u{4c1}"), + (0x04C4, "\u{4c3}"), + (0x04C6, "\u{4c5}"), + (0x04C8, "\u{4c7}"), + (0x04CA, "\u{4c9}"), + (0x04CC, "\u{4cb}"), + (0x04CE, "\u{4cd}"), + (0x04CF, "\u{4c0}"), + (0x04D1, "\u{4d0}"), + (0x04D3, "\u{4d2}"), + (0x04D5, "\u{4d4}"), + (0x04D7, "\u{4d6}"), + (0x04D9, "\u{4d8}"), + (0x04DB, "\u{4da}"), + (0x04DD, "\u{4dc}"), + (0x04DF, "\u{4de}"), + (0x04E1, "\u{4e0}"), + (0x04E3, "\u{4e2}"), + (0x04E5, "\u{4e4}"), + (0x04E7, "\u{4e6}"), + (0x04E9, "\u{4e8}"), + (0x04EB, "\u{4ea}"), + (0x04ED, "\u{4ec}"), + (0x04EF, "\u{4ee}"), + (0x04F1, "\u{4f0}"), + (0x04F3, "\u{4f2}"), + (0x04F5, "\u{4f4}"), + (0x04F7, "\u{4f6}"), + (0x04F9, "\u{4f8}"), + (0x04FB, "\u{4fa}"), + (0x04FD, "\u{4fc}"), + (0x04FF, "\u{4fe}"), + (0x0501, "\u{500}"), + (0x0503, "\u{502}"), + (0x0505, "\u{504}"), + (0x0507, "\u{506}"), + (0x0509, "\u{508}"), + (0x050B, "\u{50a}"), + (0x050D, "\u{50c}"), + (0x050F, "\u{50e}"), + (0x0511, "\u{510}"), + (0x0513, "\u{512}"), + (0x0515, "\u{514}"), + (0x0517, "\u{516}"), + (0x0519, "\u{518}"), + (0x051B, "\u{51a}"), + (0x051D, "\u{51c}"), + (0x051F, "\u{51e}"), + (0x0521, "\u{520}"), + (0x0523, "\u{522}"), + (0x0525, "\u{524}"), + (0x0527, "\u{526}"), + (0x0529, "\u{528}"), + (0x052B, "\u{52a}"), + (0x052D, "\u{52c}"), + (0x052F, "\u{52e}"), + (0x0561, "\u{531}"), + (0x0562, "\u{532}"), + (0x0563, "\u{533}"), + (0x0564, "\u{534}"), + (0x0565, "\u{535}"), + (0x0566, "\u{536}"), + (0x0567, "\u{537}"), + (0x0568, "\u{538}"), + (0x0569, "\u{539}"), + (0x056A, "\u{53a}"), + (0x056B, "\u{53b}"), + (0x056C, "\u{53c}"), + (0x056D, "\u{53d}"), + (0x056E, "\u{53e}"), + (0x056F, "\u{53f}"), + (0x0570, "\u{540}"), + (0x0571, "\u{541}"), + (0x0572, "\u{542}"), + (0x0573, "\u{543}"), + (0x0574, "\u{544}"), + (0x0575, "\u{545}"), + (0x0576, "\u{546}"), + (0x0577, "\u{547}"), + (0x0578, "\u{548}"), + (0x0579, "\u{549}"), + (0x057A, "\u{54a}"), + (0x057B, "\u{54b}"), + (0x057C, "\u{54c}"), + (0x057D, "\u{54d}"), + (0x057E, "\u{54e}"), + (0x057F, "\u{54f}"), + (0x0580, "\u{550}"), + (0x0581, "\u{551}"), + (0x0582, "\u{552}"), + (0x0583, "\u{553}"), + (0x0584, "\u{554}"), + (0x0585, "\u{555}"), + (0x0586, "\u{556}"), + (0x0587, "\u{535}\u{552}"), + (0x10D0, "\u{1c90}"), + (0x10D1, "\u{1c91}"), + (0x10D2, "\u{1c92}"), + (0x10D3, "\u{1c93}"), + (0x10D4, "\u{1c94}"), + (0x10D5, "\u{1c95}"), + (0x10D6, "\u{1c96}"), + (0x10D7, "\u{1c97}"), + (0x10D8, "\u{1c98}"), + (0x10D9, "\u{1c99}"), + (0x10DA, "\u{1c9a}"), + (0x10DB, "\u{1c9b}"), + (0x10DC, "\u{1c9c}"), + (0x10DD, "\u{1c9d}"), + (0x10DE, "\u{1c9e}"), + (0x10DF, "\u{1c9f}"), + (0x10E0, "\u{1ca0}"), + (0x10E1, "\u{1ca1}"), + (0x10E2, "\u{1ca2}"), + (0x10E3, "\u{1ca3}"), + (0x10E4, "\u{1ca4}"), + (0x10E5, "\u{1ca5}"), + (0x10E6, "\u{1ca6}"), + (0x10E7, "\u{1ca7}"), + (0x10E8, "\u{1ca8}"), + (0x10E9, "\u{1ca9}"), + (0x10EA, "\u{1caa}"), + (0x10EB, "\u{1cab}"), + (0x10EC, "\u{1cac}"), + (0x10ED, "\u{1cad}"), + (0x10EE, "\u{1cae}"), + (0x10EF, "\u{1caf}"), + (0x10F0, "\u{1cb0}"), + (0x10F1, "\u{1cb1}"), + (0x10F2, "\u{1cb2}"), + (0x10F3, "\u{1cb3}"), + (0x10F4, "\u{1cb4}"), + (0x10F5, "\u{1cb5}"), + (0x10F6, "\u{1cb6}"), + (0x10F7, "\u{1cb7}"), + (0x10F8, "\u{1cb8}"), + (0x10F9, "\u{1cb9}"), + (0x10FA, "\u{1cba}"), + (0x10FD, "\u{1cbd}"), + (0x10FE, "\u{1cbe}"), + (0x10FF, "\u{1cbf}"), + (0x13F8, "\u{13f0}"), + (0x13F9, "\u{13f1}"), + (0x13FA, "\u{13f2}"), + (0x13FB, "\u{13f3}"), + (0x13FC, "\u{13f4}"), + (0x13FD, "\u{13f5}"), + (0x1C80, "\u{412}"), + (0x1C81, "\u{414}"), + (0x1C82, "\u{41e}"), + (0x1C83, "\u{421}"), + (0x1C84, "\u{422}"), + (0x1C85, "\u{422}"), + (0x1C86, "\u{42a}"), + (0x1C87, "\u{462}"), + (0x1C88, "\u{a64a}"), + (0x1D79, "\u{a77d}"), + (0x1D7D, "\u{2c63}"), + (0x1D8E, "\u{a7c6}"), + (0x1E01, "\u{1e00}"), + (0x1E03, "\u{1e02}"), + (0x1E05, "\u{1e04}"), + (0x1E07, "\u{1e06}"), + (0x1E09, "\u{1e08}"), + (0x1E0B, "\u{1e0a}"), + (0x1E0D, "\u{1e0c}"), + (0x1E0F, "\u{1e0e}"), + (0x1E11, "\u{1e10}"), + (0x1E13, "\u{1e12}"), + (0x1E15, "\u{1e14}"), + (0x1E17, "\u{1e16}"), + (0x1E19, "\u{1e18}"), + (0x1E1B, "\u{1e1a}"), + (0x1E1D, "\u{1e1c}"), + (0x1E1F, "\u{1e1e}"), + (0x1E21, "\u{1e20}"), + (0x1E23, "\u{1e22}"), + (0x1E25, "\u{1e24}"), + (0x1E27, "\u{1e26}"), + (0x1E29, "\u{1e28}"), + (0x1E2B, "\u{1e2a}"), + (0x1E2D, "\u{1e2c}"), + (0x1E2F, "\u{1e2e}"), + (0x1E31, "\u{1e30}"), + (0x1E33, "\u{1e32}"), + (0x1E35, "\u{1e34}"), + (0x1E37, "\u{1e36}"), + (0x1E39, "\u{1e38}"), + (0x1E3B, "\u{1e3a}"), + (0x1E3D, "\u{1e3c}"), + (0x1E3F, "\u{1e3e}"), + (0x1E41, "\u{1e40}"), + (0x1E43, "\u{1e42}"), + (0x1E45, "\u{1e44}"), + (0x1E47, "\u{1e46}"), + (0x1E49, "\u{1e48}"), + (0x1E4B, "\u{1e4a}"), + (0x1E4D, "\u{1e4c}"), + (0x1E4F, "\u{1e4e}"), + (0x1E51, "\u{1e50}"), + (0x1E53, "\u{1e52}"), + (0x1E55, "\u{1e54}"), + (0x1E57, "\u{1e56}"), + (0x1E59, "\u{1e58}"), + (0x1E5B, "\u{1e5a}"), + (0x1E5D, "\u{1e5c}"), + (0x1E5F, "\u{1e5e}"), + (0x1E61, "\u{1e60}"), + (0x1E63, "\u{1e62}"), + (0x1E65, "\u{1e64}"), + (0x1E67, "\u{1e66}"), + (0x1E69, "\u{1e68}"), + (0x1E6B, "\u{1e6a}"), + (0x1E6D, "\u{1e6c}"), + (0x1E6F, "\u{1e6e}"), + (0x1E71, "\u{1e70}"), + (0x1E73, "\u{1e72}"), + (0x1E75, "\u{1e74}"), + (0x1E77, "\u{1e76}"), + (0x1E79, "\u{1e78}"), + (0x1E7B, "\u{1e7a}"), + (0x1E7D, "\u{1e7c}"), + (0x1E7F, "\u{1e7e}"), + (0x1E81, "\u{1e80}"), + (0x1E83, "\u{1e82}"), + (0x1E85, "\u{1e84}"), + (0x1E87, "\u{1e86}"), + (0x1E89, "\u{1e88}"), + (0x1E8B, "\u{1e8a}"), + (0x1E8D, "\u{1e8c}"), + (0x1E8F, "\u{1e8e}"), + (0x1E91, "\u{1e90}"), + (0x1E93, "\u{1e92}"), + (0x1E95, "\u{1e94}"), + (0x1E96, "\u{48}\u{331}"), + (0x1E97, "\u{54}\u{308}"), + (0x1E98, "\u{57}\u{30a}"), + (0x1E99, "\u{59}\u{30a}"), + (0x1E9A, "\u{41}\u{2be}"), + (0x1E9B, "\u{1e60}"), + (0x1EA1, "\u{1ea0}"), + (0x1EA3, "\u{1ea2}"), + (0x1EA5, "\u{1ea4}"), + (0x1EA7, "\u{1ea6}"), + (0x1EA9, "\u{1ea8}"), + (0x1EAB, "\u{1eaa}"), + (0x1EAD, "\u{1eac}"), + (0x1EAF, "\u{1eae}"), + (0x1EB1, "\u{1eb0}"), + (0x1EB3, "\u{1eb2}"), + (0x1EB5, "\u{1eb4}"), + (0x1EB7, "\u{1eb6}"), + (0x1EB9, "\u{1eb8}"), + (0x1EBB, "\u{1eba}"), + (0x1EBD, "\u{1ebc}"), + (0x1EBF, "\u{1ebe}"), + (0x1EC1, "\u{1ec0}"), + (0x1EC3, "\u{1ec2}"), + (0x1EC5, "\u{1ec4}"), + (0x1EC7, "\u{1ec6}"), + (0x1EC9, "\u{1ec8}"), + (0x1ECB, "\u{1eca}"), + (0x1ECD, "\u{1ecc}"), + (0x1ECF, "\u{1ece}"), + (0x1ED1, "\u{1ed0}"), + (0x1ED3, "\u{1ed2}"), + (0x1ED5, "\u{1ed4}"), + (0x1ED7, "\u{1ed6}"), + (0x1ED9, "\u{1ed8}"), + (0x1EDB, "\u{1eda}"), + (0x1EDD, "\u{1edc}"), + (0x1EDF, "\u{1ede}"), + (0x1EE1, "\u{1ee0}"), + (0x1EE3, "\u{1ee2}"), + (0x1EE5, "\u{1ee4}"), + (0x1EE7, "\u{1ee6}"), + (0x1EE9, "\u{1ee8}"), + (0x1EEB, "\u{1eea}"), + (0x1EED, "\u{1eec}"), + (0x1EEF, "\u{1eee}"), + (0x1EF1, "\u{1ef0}"), + (0x1EF3, "\u{1ef2}"), + (0x1EF5, "\u{1ef4}"), + (0x1EF7, "\u{1ef6}"), + (0x1EF9, "\u{1ef8}"), + (0x1EFB, "\u{1efa}"), + (0x1EFD, "\u{1efc}"), + (0x1EFF, "\u{1efe}"), + (0x1F00, "\u{1f08}"), + (0x1F01, "\u{1f09}"), + (0x1F02, "\u{1f0a}"), + (0x1F03, "\u{1f0b}"), + (0x1F04, "\u{1f0c}"), + (0x1F05, "\u{1f0d}"), + (0x1F06, "\u{1f0e}"), + (0x1F07, "\u{1f0f}"), + (0x1F10, "\u{1f18}"), + (0x1F11, "\u{1f19}"), + (0x1F12, "\u{1f1a}"), + (0x1F13, "\u{1f1b}"), + (0x1F14, "\u{1f1c}"), + (0x1F15, "\u{1f1d}"), + (0x1F20, "\u{1f28}"), + (0x1F21, "\u{1f29}"), + (0x1F22, "\u{1f2a}"), + (0x1F23, "\u{1f2b}"), + (0x1F24, "\u{1f2c}"), + (0x1F25, "\u{1f2d}"), + (0x1F26, "\u{1f2e}"), + (0x1F27, "\u{1f2f}"), + (0x1F30, "\u{1f38}"), + (0x1F31, "\u{1f39}"), + (0x1F32, "\u{1f3a}"), + (0x1F33, "\u{1f3b}"), + (0x1F34, "\u{1f3c}"), + (0x1F35, "\u{1f3d}"), + (0x1F36, "\u{1f3e}"), + (0x1F37, "\u{1f3f}"), + (0x1F40, "\u{1f48}"), + (0x1F41, "\u{1f49}"), + (0x1F42, "\u{1f4a}"), + (0x1F43, "\u{1f4b}"), + (0x1F44, "\u{1f4c}"), + (0x1F45, "\u{1f4d}"), + (0x1F50, "\u{3a5}\u{313}"), + (0x1F51, "\u{1f59}"), + (0x1F52, "\u{3a5}\u{313}\u{300}"), + (0x1F53, "\u{1f5b}"), + (0x1F54, "\u{3a5}\u{313}\u{301}"), + (0x1F55, "\u{1f5d}"), + (0x1F56, "\u{3a5}\u{313}\u{342}"), + (0x1F57, "\u{1f5f}"), + (0x1F60, "\u{1f68}"), + (0x1F61, "\u{1f69}"), + (0x1F62, "\u{1f6a}"), + (0x1F63, "\u{1f6b}"), + (0x1F64, "\u{1f6c}"), + (0x1F65, "\u{1f6d}"), + (0x1F66, "\u{1f6e}"), + (0x1F67, "\u{1f6f}"), + (0x1F70, "\u{1fba}"), + (0x1F71, "\u{1fbb}"), + (0x1F72, "\u{1fc8}"), + (0x1F73, "\u{1fc9}"), + (0x1F74, "\u{1fca}"), + (0x1F75, "\u{1fcb}"), + (0x1F76, "\u{1fda}"), + (0x1F77, "\u{1fdb}"), + (0x1F78, "\u{1ff8}"), + (0x1F79, "\u{1ff9}"), + (0x1F7A, "\u{1fea}"), + (0x1F7B, "\u{1feb}"), + (0x1F7C, "\u{1ffa}"), + (0x1F7D, "\u{1ffb}"), + (0x1F80, "\u{1f08}\u{399}"), + (0x1F81, "\u{1f09}\u{399}"), + (0x1F82, "\u{1f0a}\u{399}"), + (0x1F83, "\u{1f0b}\u{399}"), + (0x1F84, "\u{1f0c}\u{399}"), + (0x1F85, "\u{1f0d}\u{399}"), + (0x1F86, "\u{1f0e}\u{399}"), + (0x1F87, "\u{1f0f}\u{399}"), + (0x1F88, "\u{1f08}\u{399}"), + (0x1F89, "\u{1f09}\u{399}"), + (0x1F8A, "\u{1f0a}\u{399}"), + (0x1F8B, "\u{1f0b}\u{399}"), + (0x1F8C, "\u{1f0c}\u{399}"), + (0x1F8D, "\u{1f0d}\u{399}"), + (0x1F8E, "\u{1f0e}\u{399}"), + (0x1F8F, "\u{1f0f}\u{399}"), + (0x1F90, "\u{1f28}\u{399}"), + (0x1F91, "\u{1f29}\u{399}"), + (0x1F92, "\u{1f2a}\u{399}"), + (0x1F93, "\u{1f2b}\u{399}"), + (0x1F94, "\u{1f2c}\u{399}"), + (0x1F95, "\u{1f2d}\u{399}"), + (0x1F96, "\u{1f2e}\u{399}"), + (0x1F97, "\u{1f2f}\u{399}"), + (0x1F98, "\u{1f28}\u{399}"), + (0x1F99, "\u{1f29}\u{399}"), + (0x1F9A, "\u{1f2a}\u{399}"), + (0x1F9B, "\u{1f2b}\u{399}"), + (0x1F9C, "\u{1f2c}\u{399}"), + (0x1F9D, "\u{1f2d}\u{399}"), + (0x1F9E, "\u{1f2e}\u{399}"), + (0x1F9F, "\u{1f2f}\u{399}"), + (0x1FA0, "\u{1f68}\u{399}"), + (0x1FA1, "\u{1f69}\u{399}"), + (0x1FA2, "\u{1f6a}\u{399}"), + (0x1FA3, "\u{1f6b}\u{399}"), + (0x1FA4, "\u{1f6c}\u{399}"), + (0x1FA5, "\u{1f6d}\u{399}"), + (0x1FA6, "\u{1f6e}\u{399}"), + (0x1FA7, "\u{1f6f}\u{399}"), + (0x1FA8, "\u{1f68}\u{399}"), + (0x1FA9, "\u{1f69}\u{399}"), + (0x1FAA, "\u{1f6a}\u{399}"), + (0x1FAB, "\u{1f6b}\u{399}"), + (0x1FAC, "\u{1f6c}\u{399}"), + (0x1FAD, "\u{1f6d}\u{399}"), + (0x1FAE, "\u{1f6e}\u{399}"), + (0x1FAF, "\u{1f6f}\u{399}"), + (0x1FB0, "\u{1fb8}"), + (0x1FB1, "\u{1fb9}"), + (0x1FB2, "\u{1fba}\u{399}"), + (0x1FB3, "\u{391}\u{399}"), + (0x1FB4, "\u{386}\u{399}"), + (0x1FB6, "\u{391}\u{342}"), + (0x1FB7, "\u{391}\u{342}\u{399}"), + (0x1FBC, "\u{391}\u{399}"), + (0x1FBE, "\u{399}"), + (0x1FC2, "\u{1fca}\u{399}"), + (0x1FC3, "\u{397}\u{399}"), + (0x1FC4, "\u{389}\u{399}"), + (0x1FC6, "\u{397}\u{342}"), + (0x1FC7, "\u{397}\u{342}\u{399}"), + (0x1FCC, "\u{397}\u{399}"), + (0x1FD0, "\u{1fd8}"), + (0x1FD1, "\u{1fd9}"), + (0x1FD2, "\u{399}\u{308}\u{300}"), + (0x1FD3, "\u{399}\u{308}\u{301}"), + (0x1FD6, "\u{399}\u{342}"), + (0x1FD7, "\u{399}\u{308}\u{342}"), + (0x1FE0, "\u{1fe8}"), + (0x1FE1, "\u{1fe9}"), + (0x1FE2, "\u{3a5}\u{308}\u{300}"), + (0x1FE3, "\u{3a5}\u{308}\u{301}"), + (0x1FE4, "\u{3a1}\u{313}"), + (0x1FE5, "\u{1fec}"), + (0x1FE6, "\u{3a5}\u{342}"), + (0x1FE7, "\u{3a5}\u{308}\u{342}"), + (0x1FF2, "\u{1ffa}\u{399}"), + (0x1FF3, "\u{3a9}\u{399}"), + (0x1FF4, "\u{38f}\u{399}"), + (0x1FF6, "\u{3a9}\u{342}"), + (0x1FF7, "\u{3a9}\u{342}\u{399}"), + (0x1FFC, "\u{3a9}\u{399}"), + (0x214E, "\u{2132}"), + (0x2170, "\u{2160}"), + (0x2171, "\u{2161}"), + (0x2172, "\u{2162}"), + (0x2173, "\u{2163}"), + (0x2174, "\u{2164}"), + (0x2175, "\u{2165}"), + (0x2176, "\u{2166}"), + (0x2177, "\u{2167}"), + (0x2178, "\u{2168}"), + (0x2179, "\u{2169}"), + (0x217A, "\u{216a}"), + (0x217B, "\u{216b}"), + (0x217C, "\u{216c}"), + (0x217D, "\u{216d}"), + (0x217E, "\u{216e}"), + (0x217F, "\u{216f}"), + (0x2184, "\u{2183}"), + (0x24D0, "\u{24b6}"), + (0x24D1, "\u{24b7}"), + (0x24D2, "\u{24b8}"), + (0x24D3, "\u{24b9}"), + (0x24D4, "\u{24ba}"), + (0x24D5, "\u{24bb}"), + (0x24D6, "\u{24bc}"), + (0x24D7, "\u{24bd}"), + (0x24D8, "\u{24be}"), + (0x24D9, "\u{24bf}"), + (0x24DA, "\u{24c0}"), + (0x24DB, "\u{24c1}"), + (0x24DC, "\u{24c2}"), + (0x24DD, "\u{24c3}"), + (0x24DE, "\u{24c4}"), + (0x24DF, "\u{24c5}"), + (0x24E0, "\u{24c6}"), + (0x24E1, "\u{24c7}"), + (0x24E2, "\u{24c8}"), + (0x24E3, "\u{24c9}"), + (0x24E4, "\u{24ca}"), + (0x24E5, "\u{24cb}"), + (0x24E6, "\u{24cc}"), + (0x24E7, "\u{24cd}"), + (0x24E8, "\u{24ce}"), + (0x24E9, "\u{24cf}"), + (0x2C30, "\u{2c00}"), + (0x2C31, "\u{2c01}"), + (0x2C32, "\u{2c02}"), + (0x2C33, "\u{2c03}"), + (0x2C34, "\u{2c04}"), + (0x2C35, "\u{2c05}"), + (0x2C36, "\u{2c06}"), + (0x2C37, "\u{2c07}"), + (0x2C38, "\u{2c08}"), + (0x2C39, "\u{2c09}"), + (0x2C3A, "\u{2c0a}"), + (0x2C3B, "\u{2c0b}"), + (0x2C3C, "\u{2c0c}"), + (0x2C3D, "\u{2c0d}"), + (0x2C3E, "\u{2c0e}"), + (0x2C3F, "\u{2c0f}"), + (0x2C40, "\u{2c10}"), + (0x2C41, "\u{2c11}"), + (0x2C42, "\u{2c12}"), + (0x2C43, "\u{2c13}"), + (0x2C44, "\u{2c14}"), + (0x2C45, "\u{2c15}"), + (0x2C46, "\u{2c16}"), + (0x2C47, "\u{2c17}"), + (0x2C48, "\u{2c18}"), + (0x2C49, "\u{2c19}"), + (0x2C4A, "\u{2c1a}"), + (0x2C4B, "\u{2c1b}"), + (0x2C4C, "\u{2c1c}"), + (0x2C4D, "\u{2c1d}"), + (0x2C4E, "\u{2c1e}"), + (0x2C4F, "\u{2c1f}"), + (0x2C50, "\u{2c20}"), + (0x2C51, "\u{2c21}"), + (0x2C52, "\u{2c22}"), + (0x2C53, "\u{2c23}"), + (0x2C54, "\u{2c24}"), + (0x2C55, "\u{2c25}"), + (0x2C56, "\u{2c26}"), + (0x2C57, "\u{2c27}"), + (0x2C58, "\u{2c28}"), + (0x2C59, "\u{2c29}"), + (0x2C5A, "\u{2c2a}"), + (0x2C5B, "\u{2c2b}"), + (0x2C5C, "\u{2c2c}"), + (0x2C5D, "\u{2c2d}"), + (0x2C5E, "\u{2c2e}"), + (0x2C5F, "\u{2c2f}"), + (0x2C61, "\u{2c60}"), + (0x2C65, "\u{23a}"), + (0x2C66, "\u{23e}"), + (0x2C68, "\u{2c67}"), + (0x2C6A, "\u{2c69}"), + (0x2C6C, "\u{2c6b}"), + (0x2C73, "\u{2c72}"), + (0x2C76, "\u{2c75}"), + (0x2C81, "\u{2c80}"), + (0x2C83, "\u{2c82}"), + (0x2C85, "\u{2c84}"), + (0x2C87, "\u{2c86}"), + (0x2C89, "\u{2c88}"), + (0x2C8B, "\u{2c8a}"), + (0x2C8D, "\u{2c8c}"), + (0x2C8F, "\u{2c8e}"), + (0x2C91, "\u{2c90}"), + (0x2C93, "\u{2c92}"), + (0x2C95, "\u{2c94}"), + (0x2C97, "\u{2c96}"), + (0x2C99, "\u{2c98}"), + (0x2C9B, "\u{2c9a}"), + (0x2C9D, "\u{2c9c}"), + (0x2C9F, "\u{2c9e}"), + (0x2CA1, "\u{2ca0}"), + (0x2CA3, "\u{2ca2}"), + (0x2CA5, "\u{2ca4}"), + (0x2CA7, "\u{2ca6}"), + (0x2CA9, "\u{2ca8}"), + (0x2CAB, "\u{2caa}"), + (0x2CAD, "\u{2cac}"), + (0x2CAF, "\u{2cae}"), + (0x2CB1, "\u{2cb0}"), + (0x2CB3, "\u{2cb2}"), + (0x2CB5, "\u{2cb4}"), + (0x2CB7, "\u{2cb6}"), + (0x2CB9, "\u{2cb8}"), + (0x2CBB, "\u{2cba}"), + (0x2CBD, "\u{2cbc}"), + (0x2CBF, "\u{2cbe}"), + (0x2CC1, "\u{2cc0}"), + (0x2CC3, "\u{2cc2}"), + (0x2CC5, "\u{2cc4}"), + (0x2CC7, "\u{2cc6}"), + (0x2CC9, "\u{2cc8}"), + (0x2CCB, "\u{2cca}"), + (0x2CCD, "\u{2ccc}"), + (0x2CCF, "\u{2cce}"), + (0x2CD1, "\u{2cd0}"), + (0x2CD3, "\u{2cd2}"), + (0x2CD5, "\u{2cd4}"), + (0x2CD7, "\u{2cd6}"), + (0x2CD9, "\u{2cd8}"), + (0x2CDB, "\u{2cda}"), + (0x2CDD, "\u{2cdc}"), + (0x2CDF, "\u{2cde}"), + (0x2CE1, "\u{2ce0}"), + (0x2CE3, "\u{2ce2}"), + (0x2CEC, "\u{2ceb}"), + (0x2CEE, "\u{2ced}"), + (0x2CF3, "\u{2cf2}"), + (0x2D00, "\u{10a0}"), + (0x2D01, "\u{10a1}"), + (0x2D02, "\u{10a2}"), + (0x2D03, "\u{10a3}"), + (0x2D04, "\u{10a4}"), + (0x2D05, "\u{10a5}"), + (0x2D06, "\u{10a6}"), + (0x2D07, "\u{10a7}"), + (0x2D08, "\u{10a8}"), + (0x2D09, "\u{10a9}"), + (0x2D0A, "\u{10aa}"), + (0x2D0B, "\u{10ab}"), + (0x2D0C, "\u{10ac}"), + (0x2D0D, "\u{10ad}"), + (0x2D0E, "\u{10ae}"), + (0x2D0F, "\u{10af}"), + (0x2D10, "\u{10b0}"), + (0x2D11, "\u{10b1}"), + (0x2D12, "\u{10b2}"), + (0x2D13, "\u{10b3}"), + (0x2D14, "\u{10b4}"), + (0x2D15, "\u{10b5}"), + (0x2D16, "\u{10b6}"), + (0x2D17, "\u{10b7}"), + (0x2D18, "\u{10b8}"), + (0x2D19, "\u{10b9}"), + (0x2D1A, "\u{10ba}"), + (0x2D1B, "\u{10bb}"), + (0x2D1C, "\u{10bc}"), + (0x2D1D, "\u{10bd}"), + (0x2D1E, "\u{10be}"), + (0x2D1F, "\u{10bf}"), + (0x2D20, "\u{10c0}"), + (0x2D21, "\u{10c1}"), + (0x2D22, "\u{10c2}"), + (0x2D23, "\u{10c3}"), + (0x2D24, "\u{10c4}"), + (0x2D25, "\u{10c5}"), + (0x2D27, "\u{10c7}"), + (0x2D2D, "\u{10cd}"), + (0xA641, "\u{a640}"), + (0xA643, "\u{a642}"), + (0xA645, "\u{a644}"), + (0xA647, "\u{a646}"), + (0xA649, "\u{a648}"), + (0xA64B, "\u{a64a}"), + (0xA64D, "\u{a64c}"), + (0xA64F, "\u{a64e}"), + (0xA651, "\u{a650}"), + (0xA653, "\u{a652}"), + (0xA655, "\u{a654}"), + (0xA657, "\u{a656}"), + (0xA659, "\u{a658}"), + (0xA65B, "\u{a65a}"), + (0xA65D, "\u{a65c}"), + (0xA65F, "\u{a65e}"), + (0xA661, "\u{a660}"), + (0xA663, "\u{a662}"), + (0xA665, "\u{a664}"), + (0xA667, "\u{a666}"), + (0xA669, "\u{a668}"), + (0xA66B, "\u{a66a}"), + (0xA66D, "\u{a66c}"), + (0xA681, "\u{a680}"), + (0xA683, "\u{a682}"), + (0xA685, "\u{a684}"), + (0xA687, "\u{a686}"), + (0xA689, "\u{a688}"), + (0xA68B, "\u{a68a}"), + (0xA68D, "\u{a68c}"), + (0xA68F, "\u{a68e}"), + (0xA691, "\u{a690}"), + (0xA693, "\u{a692}"), + (0xA695, "\u{a694}"), + (0xA697, "\u{a696}"), + (0xA699, "\u{a698}"), + (0xA69B, "\u{a69a}"), + (0xA723, "\u{a722}"), + (0xA725, "\u{a724}"), + (0xA727, "\u{a726}"), + (0xA729, "\u{a728}"), + (0xA72B, "\u{a72a}"), + (0xA72D, "\u{a72c}"), + (0xA72F, "\u{a72e}"), + (0xA733, "\u{a732}"), + (0xA735, "\u{a734}"), + (0xA737, "\u{a736}"), + (0xA739, "\u{a738}"), + (0xA73B, "\u{a73a}"), + (0xA73D, "\u{a73c}"), + (0xA73F, "\u{a73e}"), + (0xA741, "\u{a740}"), + (0xA743, "\u{a742}"), + (0xA745, "\u{a744}"), + (0xA747, "\u{a746}"), + (0xA749, "\u{a748}"), + (0xA74B, "\u{a74a}"), + (0xA74D, "\u{a74c}"), + (0xA74F, "\u{a74e}"), + (0xA751, "\u{a750}"), + (0xA753, "\u{a752}"), + (0xA755, "\u{a754}"), + (0xA757, "\u{a756}"), + (0xA759, "\u{a758}"), + (0xA75B, "\u{a75a}"), + (0xA75D, "\u{a75c}"), + (0xA75F, "\u{a75e}"), + (0xA761, "\u{a760}"), + (0xA763, "\u{a762}"), + (0xA765, "\u{a764}"), + (0xA767, "\u{a766}"), + (0xA769, "\u{a768}"), + (0xA76B, "\u{a76a}"), + (0xA76D, "\u{a76c}"), + (0xA76F, "\u{a76e}"), + (0xA77A, "\u{a779}"), + (0xA77C, "\u{a77b}"), + (0xA77F, "\u{a77e}"), + (0xA781, "\u{a780}"), + (0xA783, "\u{a782}"), + (0xA785, "\u{a784}"), + (0xA787, "\u{a786}"), + (0xA78C, "\u{a78b}"), + (0xA791, "\u{a790}"), + (0xA793, "\u{a792}"), + (0xA794, "\u{a7c4}"), + (0xA797, "\u{a796}"), + (0xA799, "\u{a798}"), + (0xA79B, "\u{a79a}"), + (0xA79D, "\u{a79c}"), + (0xA79F, "\u{a79e}"), + (0xA7A1, "\u{a7a0}"), + (0xA7A3, "\u{a7a2}"), + (0xA7A5, "\u{a7a4}"), + (0xA7A7, "\u{a7a6}"), + (0xA7A9, "\u{a7a8}"), + (0xA7B5, "\u{a7b4}"), + (0xA7B7, "\u{a7b6}"), + (0xA7B9, "\u{a7b8}"), + (0xA7BB, "\u{a7ba}"), + (0xA7BD, "\u{a7bc}"), + (0xA7BF, "\u{a7be}"), + (0xA7C1, "\u{a7c0}"), + (0xA7C3, "\u{a7c2}"), + (0xA7C8, "\u{a7c7}"), + (0xA7CA, "\u{a7c9}"), + (0xA7D1, "\u{a7d0}"), + (0xA7D7, "\u{a7d6}"), + (0xA7D9, "\u{a7d8}"), + (0xA7F6, "\u{a7f5}"), + (0xAB53, "\u{a7b3}"), + (0xAB70, "\u{13a0}"), + (0xAB71, "\u{13a1}"), + (0xAB72, "\u{13a2}"), + (0xAB73, "\u{13a3}"), + (0xAB74, "\u{13a4}"), + (0xAB75, "\u{13a5}"), + (0xAB76, "\u{13a6}"), + (0xAB77, "\u{13a7}"), + (0xAB78, "\u{13a8}"), + (0xAB79, "\u{13a9}"), + (0xAB7A, "\u{13aa}"), + (0xAB7B, "\u{13ab}"), + (0xAB7C, "\u{13ac}"), + (0xAB7D, "\u{13ad}"), + (0xAB7E, "\u{13ae}"), + (0xAB7F, "\u{13af}"), + (0xAB80, "\u{13b0}"), + (0xAB81, "\u{13b1}"), + (0xAB82, "\u{13b2}"), + (0xAB83, "\u{13b3}"), + (0xAB84, "\u{13b4}"), + (0xAB85, "\u{13b5}"), + (0xAB86, "\u{13b6}"), + (0xAB87, "\u{13b7}"), + (0xAB88, "\u{13b8}"), + (0xAB89, "\u{13b9}"), + (0xAB8A, "\u{13ba}"), + (0xAB8B, "\u{13bb}"), + (0xAB8C, "\u{13bc}"), + (0xAB8D, "\u{13bd}"), + (0xAB8E, "\u{13be}"), + (0xAB8F, "\u{13bf}"), + (0xAB90, "\u{13c0}"), + (0xAB91, "\u{13c1}"), + (0xAB92, "\u{13c2}"), + (0xAB93, "\u{13c3}"), + (0xAB94, "\u{13c4}"), + (0xAB95, "\u{13c5}"), + (0xAB96, "\u{13c6}"), + (0xAB97, "\u{13c7}"), + (0xAB98, "\u{13c8}"), + (0xAB99, "\u{13c9}"), + (0xAB9A, "\u{13ca}"), + (0xAB9B, "\u{13cb}"), + (0xAB9C, "\u{13cc}"), + (0xAB9D, "\u{13cd}"), + (0xAB9E, "\u{13ce}"), + (0xAB9F, "\u{13cf}"), + (0xABA0, "\u{13d0}"), + (0xABA1, "\u{13d1}"), + (0xABA2, "\u{13d2}"), + (0xABA3, "\u{13d3}"), + (0xABA4, "\u{13d4}"), + (0xABA5, "\u{13d5}"), + (0xABA6, "\u{13d6}"), + (0xABA7, "\u{13d7}"), + (0xABA8, "\u{13d8}"), + (0xABA9, "\u{13d9}"), + (0xABAA, "\u{13da}"), + (0xABAB, "\u{13db}"), + (0xABAC, "\u{13dc}"), + (0xABAD, "\u{13dd}"), + (0xABAE, "\u{13de}"), + (0xABAF, "\u{13df}"), + (0xABB0, "\u{13e0}"), + (0xABB1, "\u{13e1}"), + (0xABB2, "\u{13e2}"), + (0xABB3, "\u{13e3}"), + (0xABB4, "\u{13e4}"), + (0xABB5, "\u{13e5}"), + (0xABB6, "\u{13e6}"), + (0xABB7, "\u{13e7}"), + (0xABB8, "\u{13e8}"), + (0xABB9, "\u{13e9}"), + (0xABBA, "\u{13ea}"), + (0xABBB, "\u{13eb}"), + (0xABBC, "\u{13ec}"), + (0xABBD, "\u{13ed}"), + (0xABBE, "\u{13ee}"), + (0xABBF, "\u{13ef}"), + (0xFB00, "\u{46}\u{46}"), + (0xFB01, "\u{46}\u{49}"), + (0xFB02, "\u{46}\u{4c}"), + (0xFB03, "\u{46}\u{46}\u{49}"), + (0xFB04, "\u{46}\u{46}\u{4c}"), + (0xFB05, "\u{53}\u{54}"), + (0xFB06, "\u{53}\u{54}"), + (0xFB13, "\u{544}\u{546}"), + (0xFB14, "\u{544}\u{535}"), + (0xFB15, "\u{544}\u{53b}"), + (0xFB16, "\u{54e}\u{546}"), + (0xFB17, "\u{544}\u{53d}"), + (0xFF41, "\u{ff21}"), + (0xFF42, "\u{ff22}"), + (0xFF43, "\u{ff23}"), + (0xFF44, "\u{ff24}"), + (0xFF45, "\u{ff25}"), + (0xFF46, "\u{ff26}"), + (0xFF47, "\u{ff27}"), + (0xFF48, "\u{ff28}"), + (0xFF49, "\u{ff29}"), + (0xFF4A, "\u{ff2a}"), + (0xFF4B, "\u{ff2b}"), + (0xFF4C, "\u{ff2c}"), + (0xFF4D, "\u{ff2d}"), + (0xFF4E, "\u{ff2e}"), + (0xFF4F, "\u{ff2f}"), + (0xFF50, "\u{ff30}"), + (0xFF51, "\u{ff31}"), + (0xFF52, "\u{ff32}"), + (0xFF53, "\u{ff33}"), + (0xFF54, "\u{ff34}"), + (0xFF55, "\u{ff35}"), + (0xFF56, "\u{ff36}"), + (0xFF57, "\u{ff37}"), + (0xFF58, "\u{ff38}"), + (0xFF59, "\u{ff39}"), + (0xFF5A, "\u{ff3a}"), + (0x10428, "\u{10400}"), + (0x10429, "\u{10401}"), + (0x1042A, "\u{10402}"), + (0x1042B, "\u{10403}"), + (0x1042C, "\u{10404}"), + (0x1042D, "\u{10405}"), + (0x1042E, "\u{10406}"), + (0x1042F, "\u{10407}"), + (0x10430, "\u{10408}"), + (0x10431, "\u{10409}"), + (0x10432, "\u{1040a}"), + (0x10433, "\u{1040b}"), + (0x10434, "\u{1040c}"), + (0x10435, "\u{1040d}"), + (0x10436, "\u{1040e}"), + (0x10437, "\u{1040f}"), + (0x10438, "\u{10410}"), + (0x10439, "\u{10411}"), + (0x1043A, "\u{10412}"), + (0x1043B, "\u{10413}"), + (0x1043C, "\u{10414}"), + (0x1043D, "\u{10415}"), + (0x1043E, "\u{10416}"), + (0x1043F, "\u{10417}"), + (0x10440, "\u{10418}"), + (0x10441, "\u{10419}"), + (0x10442, "\u{1041a}"), + (0x10443, "\u{1041b}"), + (0x10444, "\u{1041c}"), + (0x10445, "\u{1041d}"), + (0x10446, "\u{1041e}"), + (0x10447, "\u{1041f}"), + (0x10448, "\u{10420}"), + (0x10449, "\u{10421}"), + (0x1044A, "\u{10422}"), + (0x1044B, "\u{10423}"), + (0x1044C, "\u{10424}"), + (0x1044D, "\u{10425}"), + (0x1044E, "\u{10426}"), + (0x1044F, "\u{10427}"), + (0x104D8, "\u{104b0}"), + (0x104D9, "\u{104b1}"), + (0x104DA, "\u{104b2}"), + (0x104DB, "\u{104b3}"), + (0x104DC, "\u{104b4}"), + (0x104DD, "\u{104b5}"), + (0x104DE, "\u{104b6}"), + (0x104DF, "\u{104b7}"), + (0x104E0, "\u{104b8}"), + (0x104E1, "\u{104b9}"), + (0x104E2, "\u{104ba}"), + (0x104E3, "\u{104bb}"), + (0x104E4, "\u{104bc}"), + (0x104E5, "\u{104bd}"), + (0x104E6, "\u{104be}"), + (0x104E7, "\u{104bf}"), + (0x104E8, "\u{104c0}"), + (0x104E9, "\u{104c1}"), + (0x104EA, "\u{104c2}"), + (0x104EB, "\u{104c3}"), + (0x104EC, "\u{104c4}"), + (0x104ED, "\u{104c5}"), + (0x104EE, "\u{104c6}"), + (0x104EF, "\u{104c7}"), + (0x104F0, "\u{104c8}"), + (0x104F1, "\u{104c9}"), + (0x104F2, "\u{104ca}"), + (0x104F3, "\u{104cb}"), + (0x104F4, "\u{104cc}"), + (0x104F5, "\u{104cd}"), + (0x104F6, "\u{104ce}"), + (0x104F7, "\u{104cf}"), + (0x104F8, "\u{104d0}"), + (0x104F9, "\u{104d1}"), + (0x104FA, "\u{104d2}"), + (0x104FB, "\u{104d3}"), + (0x10597, "\u{10570}"), + (0x10598, "\u{10571}"), + (0x10599, "\u{10572}"), + (0x1059A, "\u{10573}"), + (0x1059B, "\u{10574}"), + (0x1059C, "\u{10575}"), + (0x1059D, "\u{10576}"), + (0x1059E, "\u{10577}"), + (0x1059F, "\u{10578}"), + (0x105A0, "\u{10579}"), + (0x105A1, "\u{1057a}"), + (0x105A3, "\u{1057c}"), + (0x105A4, "\u{1057d}"), + (0x105A5, "\u{1057e}"), + (0x105A6, "\u{1057f}"), + (0x105A7, "\u{10580}"), + (0x105A8, "\u{10581}"), + (0x105A9, "\u{10582}"), + (0x105AA, "\u{10583}"), + (0x105AB, "\u{10584}"), + (0x105AC, "\u{10585}"), + (0x105AD, "\u{10586}"), + (0x105AE, "\u{10587}"), + (0x105AF, "\u{10588}"), + (0x105B0, "\u{10589}"), + (0x105B1, "\u{1058a}"), + (0x105B3, "\u{1058c}"), + (0x105B4, "\u{1058d}"), + (0x105B5, "\u{1058e}"), + (0x105B6, "\u{1058f}"), + (0x105B7, "\u{10590}"), + (0x105B8, "\u{10591}"), + (0x105B9, "\u{10592}"), + (0x105BB, "\u{10594}"), + (0x105BC, "\u{10595}"), + (0x10CC0, "\u{10c80}"), + (0x10CC1, "\u{10c81}"), + (0x10CC2, "\u{10c82}"), + (0x10CC3, "\u{10c83}"), + (0x10CC4, "\u{10c84}"), + (0x10CC5, "\u{10c85}"), + (0x10CC6, "\u{10c86}"), + (0x10CC7, "\u{10c87}"), + (0x10CC8, "\u{10c88}"), + (0x10CC9, "\u{10c89}"), + (0x10CCA, "\u{10c8a}"), + (0x10CCB, "\u{10c8b}"), + (0x10CCC, "\u{10c8c}"), + (0x10CCD, "\u{10c8d}"), + (0x10CCE, "\u{10c8e}"), + (0x10CCF, "\u{10c8f}"), + (0x10CD0, "\u{10c90}"), + (0x10CD1, "\u{10c91}"), + (0x10CD2, "\u{10c92}"), + (0x10CD3, "\u{10c93}"), + (0x10CD4, "\u{10c94}"), + (0x10CD5, "\u{10c95}"), + (0x10CD6, "\u{10c96}"), + (0x10CD7, "\u{10c97}"), + (0x10CD8, "\u{10c98}"), + (0x10CD9, "\u{10c99}"), + (0x10CDA, "\u{10c9a}"), + (0x10CDB, "\u{10c9b}"), + (0x10CDC, "\u{10c9c}"), + (0x10CDD, "\u{10c9d}"), + (0x10CDE, "\u{10c9e}"), + (0x10CDF, "\u{10c9f}"), + (0x10CE0, "\u{10ca0}"), + (0x10CE1, "\u{10ca1}"), + (0x10CE2, "\u{10ca2}"), + (0x10CE3, "\u{10ca3}"), + (0x10CE4, "\u{10ca4}"), + (0x10CE5, "\u{10ca5}"), + (0x10CE6, "\u{10ca6}"), + (0x10CE7, "\u{10ca7}"), + (0x10CE8, "\u{10ca8}"), + (0x10CE9, "\u{10ca9}"), + (0x10CEA, "\u{10caa}"), + (0x10CEB, "\u{10cab}"), + (0x10CEC, "\u{10cac}"), + (0x10CED, "\u{10cad}"), + (0x10CEE, "\u{10cae}"), + (0x10CEF, "\u{10caf}"), + (0x10CF0, "\u{10cb0}"), + (0x10CF1, "\u{10cb1}"), + (0x10CF2, "\u{10cb2}"), + (0x118C0, "\u{118a0}"), + (0x118C1, "\u{118a1}"), + (0x118C2, "\u{118a2}"), + (0x118C3, "\u{118a3}"), + (0x118C4, "\u{118a4}"), + (0x118C5, "\u{118a5}"), + (0x118C6, "\u{118a6}"), + (0x118C7, "\u{118a7}"), + (0x118C8, "\u{118a8}"), + (0x118C9, "\u{118a9}"), + (0x118CA, "\u{118aa}"), + (0x118CB, "\u{118ab}"), + (0x118CC, "\u{118ac}"), + (0x118CD, "\u{118ad}"), + (0x118CE, "\u{118ae}"), + (0x118CF, "\u{118af}"), + (0x118D0, "\u{118b0}"), + (0x118D1, "\u{118b1}"), + (0x118D2, "\u{118b2}"), + (0x118D3, "\u{118b3}"), + (0x118D4, "\u{118b4}"), + (0x118D5, "\u{118b5}"), + (0x118D6, "\u{118b6}"), + (0x118D7, "\u{118b7}"), + (0x118D8, "\u{118b8}"), + (0x118D9, "\u{118b9}"), + (0x118DA, "\u{118ba}"), + (0x118DB, "\u{118bb}"), + (0x118DC, "\u{118bc}"), + (0x118DD, "\u{118bd}"), + (0x118DE, "\u{118be}"), + (0x118DF, "\u{118bf}"), + (0x16E60, "\u{16e40}"), + (0x16E61, "\u{16e41}"), + (0x16E62, "\u{16e42}"), + (0x16E63, "\u{16e43}"), + (0x16E64, "\u{16e44}"), + (0x16E65, "\u{16e45}"), + (0x16E66, "\u{16e46}"), + (0x16E67, "\u{16e47}"), + (0x16E68, "\u{16e48}"), + (0x16E69, "\u{16e49}"), + (0x16E6A, "\u{16e4a}"), + (0x16E6B, "\u{16e4b}"), + (0x16E6C, "\u{16e4c}"), + (0x16E6D, "\u{16e4d}"), + (0x16E6E, "\u{16e4e}"), + (0x16E6F, "\u{16e4f}"), + (0x16E70, "\u{16e50}"), + (0x16E71, "\u{16e51}"), + (0x16E72, "\u{16e52}"), + (0x16E73, "\u{16e53}"), + (0x16E74, "\u{16e54}"), + (0x16E75, "\u{16e55}"), + (0x16E76, "\u{16e56}"), + (0x16E77, "\u{16e57}"), + (0x16E78, "\u{16e58}"), + (0x16E79, "\u{16e59}"), + (0x16E7A, "\u{16e5a}"), + (0x16E7B, "\u{16e5b}"), + (0x16E7C, "\u{16e5c}"), + (0x16E7D, "\u{16e5d}"), + (0x16E7E, "\u{16e5e}"), + (0x16E7F, "\u{16e5f}"), + (0x1E922, "\u{1e900}"), + (0x1E923, "\u{1e901}"), + (0x1E924, "\u{1e902}"), + (0x1E925, "\u{1e903}"), + (0x1E926, "\u{1e904}"), + (0x1E927, "\u{1e905}"), + (0x1E928, "\u{1e906}"), + (0x1E929, "\u{1e907}"), + (0x1E92A, "\u{1e908}"), + (0x1E92B, "\u{1e909}"), + (0x1E92C, "\u{1e90a}"), + (0x1E92D, "\u{1e90b}"), + (0x1E92E, "\u{1e90c}"), + (0x1E92F, "\u{1e90d}"), + (0x1E930, "\u{1e90e}"), + (0x1E931, "\u{1e90f}"), + (0x1E932, "\u{1e910}"), + (0x1E933, "\u{1e911}"), + (0x1E934, "\u{1e912}"), + (0x1E935, "\u{1e913}"), + (0x1E936, "\u{1e914}"), + (0x1E937, "\u{1e915}"), + (0x1E938, "\u{1e916}"), + (0x1E939, "\u{1e917}"), + (0x1E93A, "\u{1e918}"), + (0x1E93B, "\u{1e919}"), + (0x1E93C, "\u{1e91a}"), + (0x1E93D, "\u{1e91b}"), + (0x1E93E, "\u{1e91c}"), + (0x1E93F, "\u{1e91d}"), + (0x1E940, "\u{1e91e}"), + (0x1E941, "\u{1e91f}"), + (0x1E942, "\u{1e920}"), + (0x1E943, "\u{1e921}"), +] diff --git a/crates/sqlbuild-core/src/text/upper_mappings/unicode_16_0_0.in b/crates/sqlbuild-core/src/text/upper_mappings/unicode_16_0_0.in new file mode 100644 index 0000000000..4375565041 --- /dev/null +++ b/crates/sqlbuild-core/src/text/upper_mappings/unicode_16_0_0.in @@ -0,0 +1,1556 @@ +// Generated by `scripts/generate_python_char_table.py`; do not edit. +// Every character `str.upper()` changes in Unicode 16.0.0, in code point order. +&[ + (0x0061, "\u{41}"), + (0x0062, "\u{42}"), + (0x0063, "\u{43}"), + (0x0064, "\u{44}"), + (0x0065, "\u{45}"), + (0x0066, "\u{46}"), + (0x0067, "\u{47}"), + (0x0068, "\u{48}"), + (0x0069, "\u{49}"), + (0x006A, "\u{4a}"), + (0x006B, "\u{4b}"), + (0x006C, "\u{4c}"), + (0x006D, "\u{4d}"), + (0x006E, "\u{4e}"), + (0x006F, "\u{4f}"), + (0x0070, "\u{50}"), + (0x0071, "\u{51}"), + (0x0072, "\u{52}"), + (0x0073, "\u{53}"), + (0x0074, "\u{54}"), + (0x0075, "\u{55}"), + (0x0076, "\u{56}"), + (0x0077, "\u{57}"), + (0x0078, "\u{58}"), + (0x0079, "\u{59}"), + (0x007A, "\u{5a}"), + (0x00B5, "\u{39c}"), + (0x00DF, "\u{53}\u{53}"), + (0x00E0, "\u{c0}"), + (0x00E1, "\u{c1}"), + (0x00E2, "\u{c2}"), + (0x00E3, "\u{c3}"), + (0x00E4, "\u{c4}"), + (0x00E5, "\u{c5}"), + (0x00E6, "\u{c6}"), + (0x00E7, "\u{c7}"), + (0x00E8, "\u{c8}"), + (0x00E9, "\u{c9}"), + (0x00EA, "\u{ca}"), + (0x00EB, "\u{cb}"), + (0x00EC, "\u{cc}"), + (0x00ED, "\u{cd}"), + (0x00EE, "\u{ce}"), + (0x00EF, "\u{cf}"), + (0x00F0, "\u{d0}"), + (0x00F1, "\u{d1}"), + (0x00F2, "\u{d2}"), + (0x00F3, "\u{d3}"), + (0x00F4, "\u{d4}"), + (0x00F5, "\u{d5}"), + (0x00F6, "\u{d6}"), + (0x00F8, "\u{d8}"), + (0x00F9, "\u{d9}"), + (0x00FA, "\u{da}"), + (0x00FB, "\u{db}"), + (0x00FC, "\u{dc}"), + (0x00FD, "\u{dd}"), + (0x00FE, "\u{de}"), + (0x00FF, "\u{178}"), + (0x0101, "\u{100}"), + (0x0103, "\u{102}"), + (0x0105, "\u{104}"), + (0x0107, "\u{106}"), + (0x0109, "\u{108}"), + (0x010B, "\u{10a}"), + (0x010D, "\u{10c}"), + (0x010F, "\u{10e}"), + (0x0111, "\u{110}"), + (0x0113, "\u{112}"), + (0x0115, "\u{114}"), + (0x0117, "\u{116}"), + (0x0119, "\u{118}"), + (0x011B, "\u{11a}"), + (0x011D, "\u{11c}"), + (0x011F, "\u{11e}"), + (0x0121, "\u{120}"), + (0x0123, "\u{122}"), + (0x0125, "\u{124}"), + (0x0127, "\u{126}"), + (0x0129, "\u{128}"), + (0x012B, "\u{12a}"), + (0x012D, "\u{12c}"), + (0x012F, "\u{12e}"), + (0x0131, "\u{49}"), + (0x0133, "\u{132}"), + (0x0135, "\u{134}"), + (0x0137, "\u{136}"), + (0x013A, "\u{139}"), + (0x013C, "\u{13b}"), + (0x013E, "\u{13d}"), + (0x0140, "\u{13f}"), + (0x0142, "\u{141}"), + (0x0144, "\u{143}"), + (0x0146, "\u{145}"), + (0x0148, "\u{147}"), + (0x0149, "\u{2bc}\u{4e}"), + (0x014B, "\u{14a}"), + (0x014D, "\u{14c}"), + (0x014F, "\u{14e}"), + (0x0151, "\u{150}"), + (0x0153, "\u{152}"), + (0x0155, "\u{154}"), + (0x0157, "\u{156}"), + (0x0159, "\u{158}"), + (0x015B, "\u{15a}"), + (0x015D, "\u{15c}"), + (0x015F, "\u{15e}"), + (0x0161, "\u{160}"), + (0x0163, "\u{162}"), + (0x0165, "\u{164}"), + (0x0167, "\u{166}"), + (0x0169, "\u{168}"), + (0x016B, "\u{16a}"), + (0x016D, "\u{16c}"), + (0x016F, "\u{16e}"), + (0x0171, "\u{170}"), + (0x0173, "\u{172}"), + (0x0175, "\u{174}"), + (0x0177, "\u{176}"), + (0x017A, "\u{179}"), + (0x017C, "\u{17b}"), + (0x017E, "\u{17d}"), + (0x017F, "\u{53}"), + (0x0180, "\u{243}"), + (0x0183, "\u{182}"), + (0x0185, "\u{184}"), + (0x0188, "\u{187}"), + (0x018C, "\u{18b}"), + (0x0192, "\u{191}"), + (0x0195, "\u{1f6}"), + (0x0199, "\u{198}"), + (0x019A, "\u{23d}"), + (0x019B, "\u{a7dc}"), + (0x019E, "\u{220}"), + (0x01A1, "\u{1a0}"), + (0x01A3, "\u{1a2}"), + (0x01A5, "\u{1a4}"), + (0x01A8, "\u{1a7}"), + (0x01AD, "\u{1ac}"), + (0x01B0, "\u{1af}"), + (0x01B4, "\u{1b3}"), + (0x01B6, "\u{1b5}"), + (0x01B9, "\u{1b8}"), + (0x01BD, "\u{1bc}"), + (0x01BF, "\u{1f7}"), + (0x01C5, "\u{1c4}"), + (0x01C6, "\u{1c4}"), + (0x01C8, "\u{1c7}"), + (0x01C9, "\u{1c7}"), + (0x01CB, "\u{1ca}"), + (0x01CC, "\u{1ca}"), + (0x01CE, "\u{1cd}"), + (0x01D0, "\u{1cf}"), + (0x01D2, "\u{1d1}"), + (0x01D4, "\u{1d3}"), + (0x01D6, "\u{1d5}"), + (0x01D8, "\u{1d7}"), + (0x01DA, "\u{1d9}"), + (0x01DC, "\u{1db}"), + (0x01DD, "\u{18e}"), + (0x01DF, "\u{1de}"), + (0x01E1, "\u{1e0}"), + (0x01E3, "\u{1e2}"), + (0x01E5, "\u{1e4}"), + (0x01E7, "\u{1e6}"), + (0x01E9, "\u{1e8}"), + (0x01EB, "\u{1ea}"), + (0x01ED, "\u{1ec}"), + (0x01EF, "\u{1ee}"), + (0x01F0, "\u{4a}\u{30c}"), + (0x01F2, "\u{1f1}"), + (0x01F3, "\u{1f1}"), + (0x01F5, "\u{1f4}"), + (0x01F9, "\u{1f8}"), + (0x01FB, "\u{1fa}"), + (0x01FD, "\u{1fc}"), + (0x01FF, "\u{1fe}"), + (0x0201, "\u{200}"), + (0x0203, "\u{202}"), + (0x0205, "\u{204}"), + (0x0207, "\u{206}"), + (0x0209, "\u{208}"), + (0x020B, "\u{20a}"), + (0x020D, "\u{20c}"), + (0x020F, "\u{20e}"), + (0x0211, "\u{210}"), + (0x0213, "\u{212}"), + (0x0215, "\u{214}"), + (0x0217, "\u{216}"), + (0x0219, "\u{218}"), + (0x021B, "\u{21a}"), + (0x021D, "\u{21c}"), + (0x021F, "\u{21e}"), + (0x0223, "\u{222}"), + (0x0225, "\u{224}"), + (0x0227, "\u{226}"), + (0x0229, "\u{228}"), + (0x022B, "\u{22a}"), + (0x022D, "\u{22c}"), + (0x022F, "\u{22e}"), + (0x0231, "\u{230}"), + (0x0233, "\u{232}"), + (0x023C, "\u{23b}"), + (0x023F, "\u{2c7e}"), + (0x0240, "\u{2c7f}"), + (0x0242, "\u{241}"), + (0x0247, "\u{246}"), + (0x0249, "\u{248}"), + (0x024B, "\u{24a}"), + (0x024D, "\u{24c}"), + (0x024F, "\u{24e}"), + (0x0250, "\u{2c6f}"), + (0x0251, "\u{2c6d}"), + (0x0252, "\u{2c70}"), + (0x0253, "\u{181}"), + (0x0254, "\u{186}"), + (0x0256, "\u{189}"), + (0x0257, "\u{18a}"), + (0x0259, "\u{18f}"), + (0x025B, "\u{190}"), + (0x025C, "\u{a7ab}"), + (0x0260, "\u{193}"), + (0x0261, "\u{a7ac}"), + (0x0263, "\u{194}"), + (0x0264, "\u{a7cb}"), + (0x0265, "\u{a78d}"), + (0x0266, "\u{a7aa}"), + (0x0268, "\u{197}"), + (0x0269, "\u{196}"), + (0x026A, "\u{a7ae}"), + (0x026B, "\u{2c62}"), + (0x026C, "\u{a7ad}"), + (0x026F, "\u{19c}"), + (0x0271, "\u{2c6e}"), + (0x0272, "\u{19d}"), + (0x0275, "\u{19f}"), + (0x027D, "\u{2c64}"), + (0x0280, "\u{1a6}"), + (0x0282, "\u{a7c5}"), + (0x0283, "\u{1a9}"), + (0x0287, "\u{a7b1}"), + (0x0288, "\u{1ae}"), + (0x0289, "\u{244}"), + (0x028A, "\u{1b1}"), + (0x028B, "\u{1b2}"), + (0x028C, "\u{245}"), + (0x0292, "\u{1b7}"), + (0x029D, "\u{a7b2}"), + (0x029E, "\u{a7b0}"), + (0x0345, "\u{399}"), + (0x0371, "\u{370}"), + (0x0373, "\u{372}"), + (0x0377, "\u{376}"), + (0x037B, "\u{3fd}"), + (0x037C, "\u{3fe}"), + (0x037D, "\u{3ff}"), + (0x0390, "\u{399}\u{308}\u{301}"), + (0x03AC, "\u{386}"), + (0x03AD, "\u{388}"), + (0x03AE, "\u{389}"), + (0x03AF, "\u{38a}"), + (0x03B0, "\u{3a5}\u{308}\u{301}"), + (0x03B1, "\u{391}"), + (0x03B2, "\u{392}"), + (0x03B3, "\u{393}"), + (0x03B4, "\u{394}"), + (0x03B5, "\u{395}"), + (0x03B6, "\u{396}"), + (0x03B7, "\u{397}"), + (0x03B8, "\u{398}"), + (0x03B9, "\u{399}"), + (0x03BA, "\u{39a}"), + (0x03BB, "\u{39b}"), + (0x03BC, "\u{39c}"), + (0x03BD, "\u{39d}"), + (0x03BE, "\u{39e}"), + (0x03BF, "\u{39f}"), + (0x03C0, "\u{3a0}"), + (0x03C1, "\u{3a1}"), + (0x03C2, "\u{3a3}"), + (0x03C3, "\u{3a3}"), + (0x03C4, "\u{3a4}"), + (0x03C5, "\u{3a5}"), + (0x03C6, "\u{3a6}"), + (0x03C7, "\u{3a7}"), + (0x03C8, "\u{3a8}"), + (0x03C9, "\u{3a9}"), + (0x03CA, "\u{3aa}"), + (0x03CB, "\u{3ab}"), + (0x03CC, "\u{38c}"), + (0x03CD, "\u{38e}"), + (0x03CE, "\u{38f}"), + (0x03D0, "\u{392}"), + (0x03D1, "\u{398}"), + (0x03D5, "\u{3a6}"), + (0x03D6, "\u{3a0}"), + (0x03D7, "\u{3cf}"), + (0x03D9, "\u{3d8}"), + (0x03DB, "\u{3da}"), + (0x03DD, "\u{3dc}"), + (0x03DF, "\u{3de}"), + (0x03E1, "\u{3e0}"), + (0x03E3, "\u{3e2}"), + (0x03E5, "\u{3e4}"), + (0x03E7, "\u{3e6}"), + (0x03E9, "\u{3e8}"), + (0x03EB, "\u{3ea}"), + (0x03ED, "\u{3ec}"), + (0x03EF, "\u{3ee}"), + (0x03F0, "\u{39a}"), + (0x03F1, "\u{3a1}"), + (0x03F2, "\u{3f9}"), + (0x03F3, "\u{37f}"), + (0x03F5, "\u{395}"), + (0x03F8, "\u{3f7}"), + (0x03FB, "\u{3fa}"), + (0x0430, "\u{410}"), + (0x0431, "\u{411}"), + (0x0432, "\u{412}"), + (0x0433, "\u{413}"), + (0x0434, "\u{414}"), + (0x0435, "\u{415}"), + (0x0436, "\u{416}"), + (0x0437, "\u{417}"), + (0x0438, "\u{418}"), + (0x0439, "\u{419}"), + (0x043A, "\u{41a}"), + (0x043B, "\u{41b}"), + (0x043C, "\u{41c}"), + (0x043D, "\u{41d}"), + (0x043E, "\u{41e}"), + (0x043F, "\u{41f}"), + (0x0440, "\u{420}"), + (0x0441, "\u{421}"), + (0x0442, "\u{422}"), + (0x0443, "\u{423}"), + (0x0444, "\u{424}"), + (0x0445, "\u{425}"), + (0x0446, "\u{426}"), + (0x0447, "\u{427}"), + (0x0448, "\u{428}"), + (0x0449, "\u{429}"), + (0x044A, "\u{42a}"), + (0x044B, "\u{42b}"), + (0x044C, "\u{42c}"), + (0x044D, "\u{42d}"), + (0x044E, "\u{42e}"), + (0x044F, "\u{42f}"), + (0x0450, "\u{400}"), + (0x0451, "\u{401}"), + (0x0452, "\u{402}"), + (0x0453, "\u{403}"), + (0x0454, "\u{404}"), + (0x0455, "\u{405}"), + (0x0456, "\u{406}"), + (0x0457, "\u{407}"), + (0x0458, "\u{408}"), + (0x0459, "\u{409}"), + (0x045A, "\u{40a}"), + (0x045B, "\u{40b}"), + (0x045C, "\u{40c}"), + (0x045D, "\u{40d}"), + (0x045E, "\u{40e}"), + (0x045F, "\u{40f}"), + (0x0461, "\u{460}"), + (0x0463, "\u{462}"), + (0x0465, "\u{464}"), + (0x0467, "\u{466}"), + (0x0469, "\u{468}"), + (0x046B, "\u{46a}"), + (0x046D, "\u{46c}"), + (0x046F, "\u{46e}"), + (0x0471, "\u{470}"), + (0x0473, "\u{472}"), + (0x0475, "\u{474}"), + (0x0477, "\u{476}"), + (0x0479, "\u{478}"), + (0x047B, "\u{47a}"), + (0x047D, "\u{47c}"), + (0x047F, "\u{47e}"), + (0x0481, "\u{480}"), + (0x048B, "\u{48a}"), + (0x048D, "\u{48c}"), + (0x048F, "\u{48e}"), + (0x0491, "\u{490}"), + (0x0493, "\u{492}"), + (0x0495, "\u{494}"), + (0x0497, "\u{496}"), + (0x0499, "\u{498}"), + (0x049B, "\u{49a}"), + (0x049D, "\u{49c}"), + (0x049F, "\u{49e}"), + (0x04A1, "\u{4a0}"), + (0x04A3, "\u{4a2}"), + (0x04A5, "\u{4a4}"), + (0x04A7, "\u{4a6}"), + (0x04A9, "\u{4a8}"), + (0x04AB, "\u{4aa}"), + (0x04AD, "\u{4ac}"), + (0x04AF, "\u{4ae}"), + (0x04B1, "\u{4b0}"), + (0x04B3, "\u{4b2}"), + (0x04B5, "\u{4b4}"), + (0x04B7, "\u{4b6}"), + (0x04B9, "\u{4b8}"), + (0x04BB, "\u{4ba}"), + (0x04BD, "\u{4bc}"), + (0x04BF, "\u{4be}"), + (0x04C2, "\u{4c1}"), + (0x04C4, "\u{4c3}"), + (0x04C6, "\u{4c5}"), + (0x04C8, "\u{4c7}"), + (0x04CA, "\u{4c9}"), + (0x04CC, "\u{4cb}"), + (0x04CE, "\u{4cd}"), + (0x04CF, "\u{4c0}"), + (0x04D1, "\u{4d0}"), + (0x04D3, "\u{4d2}"), + (0x04D5, "\u{4d4}"), + (0x04D7, "\u{4d6}"), + (0x04D9, "\u{4d8}"), + (0x04DB, "\u{4da}"), + (0x04DD, "\u{4dc}"), + (0x04DF, "\u{4de}"), + (0x04E1, "\u{4e0}"), + (0x04E3, "\u{4e2}"), + (0x04E5, "\u{4e4}"), + (0x04E7, "\u{4e6}"), + (0x04E9, "\u{4e8}"), + (0x04EB, "\u{4ea}"), + (0x04ED, "\u{4ec}"), + (0x04EF, "\u{4ee}"), + (0x04F1, "\u{4f0}"), + (0x04F3, "\u{4f2}"), + (0x04F5, "\u{4f4}"), + (0x04F7, "\u{4f6}"), + (0x04F9, "\u{4f8}"), + (0x04FB, "\u{4fa}"), + (0x04FD, "\u{4fc}"), + (0x04FF, "\u{4fe}"), + (0x0501, "\u{500}"), + (0x0503, "\u{502}"), + (0x0505, "\u{504}"), + (0x0507, "\u{506}"), + (0x0509, "\u{508}"), + (0x050B, "\u{50a}"), + (0x050D, "\u{50c}"), + (0x050F, "\u{50e}"), + (0x0511, "\u{510}"), + (0x0513, "\u{512}"), + (0x0515, "\u{514}"), + (0x0517, "\u{516}"), + (0x0519, "\u{518}"), + (0x051B, "\u{51a}"), + (0x051D, "\u{51c}"), + (0x051F, "\u{51e}"), + (0x0521, "\u{520}"), + (0x0523, "\u{522}"), + (0x0525, "\u{524}"), + (0x0527, "\u{526}"), + (0x0529, "\u{528}"), + (0x052B, "\u{52a}"), + (0x052D, "\u{52c}"), + (0x052F, "\u{52e}"), + (0x0561, "\u{531}"), + (0x0562, "\u{532}"), + (0x0563, "\u{533}"), + (0x0564, "\u{534}"), + (0x0565, "\u{535}"), + (0x0566, "\u{536}"), + (0x0567, "\u{537}"), + (0x0568, "\u{538}"), + (0x0569, "\u{539}"), + (0x056A, "\u{53a}"), + (0x056B, "\u{53b}"), + (0x056C, "\u{53c}"), + (0x056D, "\u{53d}"), + (0x056E, "\u{53e}"), + (0x056F, "\u{53f}"), + (0x0570, "\u{540}"), + (0x0571, "\u{541}"), + (0x0572, "\u{542}"), + (0x0573, "\u{543}"), + (0x0574, "\u{544}"), + (0x0575, "\u{545}"), + (0x0576, "\u{546}"), + (0x0577, "\u{547}"), + (0x0578, "\u{548}"), + (0x0579, "\u{549}"), + (0x057A, "\u{54a}"), + (0x057B, "\u{54b}"), + (0x057C, "\u{54c}"), + (0x057D, "\u{54d}"), + (0x057E, "\u{54e}"), + (0x057F, "\u{54f}"), + (0x0580, "\u{550}"), + (0x0581, "\u{551}"), + (0x0582, "\u{552}"), + (0x0583, "\u{553}"), + (0x0584, "\u{554}"), + (0x0585, "\u{555}"), + (0x0586, "\u{556}"), + (0x0587, "\u{535}\u{552}"), + (0x10D0, "\u{1c90}"), + (0x10D1, "\u{1c91}"), + (0x10D2, "\u{1c92}"), + (0x10D3, "\u{1c93}"), + (0x10D4, "\u{1c94}"), + (0x10D5, "\u{1c95}"), + (0x10D6, "\u{1c96}"), + (0x10D7, "\u{1c97}"), + (0x10D8, "\u{1c98}"), + (0x10D9, "\u{1c99}"), + (0x10DA, "\u{1c9a}"), + (0x10DB, "\u{1c9b}"), + (0x10DC, "\u{1c9c}"), + (0x10DD, "\u{1c9d}"), + (0x10DE, "\u{1c9e}"), + (0x10DF, "\u{1c9f}"), + (0x10E0, "\u{1ca0}"), + (0x10E1, "\u{1ca1}"), + (0x10E2, "\u{1ca2}"), + (0x10E3, "\u{1ca3}"), + (0x10E4, "\u{1ca4}"), + (0x10E5, "\u{1ca5}"), + (0x10E6, "\u{1ca6}"), + (0x10E7, "\u{1ca7}"), + (0x10E8, "\u{1ca8}"), + (0x10E9, "\u{1ca9}"), + (0x10EA, "\u{1caa}"), + (0x10EB, "\u{1cab}"), + (0x10EC, "\u{1cac}"), + (0x10ED, "\u{1cad}"), + (0x10EE, "\u{1cae}"), + (0x10EF, "\u{1caf}"), + (0x10F0, "\u{1cb0}"), + (0x10F1, "\u{1cb1}"), + (0x10F2, "\u{1cb2}"), + (0x10F3, "\u{1cb3}"), + (0x10F4, "\u{1cb4}"), + (0x10F5, "\u{1cb5}"), + (0x10F6, "\u{1cb6}"), + (0x10F7, "\u{1cb7}"), + (0x10F8, "\u{1cb8}"), + (0x10F9, "\u{1cb9}"), + (0x10FA, "\u{1cba}"), + (0x10FD, "\u{1cbd}"), + (0x10FE, "\u{1cbe}"), + (0x10FF, "\u{1cbf}"), + (0x13F8, "\u{13f0}"), + (0x13F9, "\u{13f1}"), + (0x13FA, "\u{13f2}"), + (0x13FB, "\u{13f3}"), + (0x13FC, "\u{13f4}"), + (0x13FD, "\u{13f5}"), + (0x1C80, "\u{412}"), + (0x1C81, "\u{414}"), + (0x1C82, "\u{41e}"), + (0x1C83, "\u{421}"), + (0x1C84, "\u{422}"), + (0x1C85, "\u{422}"), + (0x1C86, "\u{42a}"), + (0x1C87, "\u{462}"), + (0x1C88, "\u{a64a}"), + (0x1C8A, "\u{1c89}"), + (0x1D79, "\u{a77d}"), + (0x1D7D, "\u{2c63}"), + (0x1D8E, "\u{a7c6}"), + (0x1E01, "\u{1e00}"), + (0x1E03, "\u{1e02}"), + (0x1E05, "\u{1e04}"), + (0x1E07, "\u{1e06}"), + (0x1E09, "\u{1e08}"), + (0x1E0B, "\u{1e0a}"), + (0x1E0D, "\u{1e0c}"), + (0x1E0F, "\u{1e0e}"), + (0x1E11, "\u{1e10}"), + (0x1E13, "\u{1e12}"), + (0x1E15, "\u{1e14}"), + (0x1E17, "\u{1e16}"), + (0x1E19, "\u{1e18}"), + (0x1E1B, "\u{1e1a}"), + (0x1E1D, "\u{1e1c}"), + (0x1E1F, "\u{1e1e}"), + (0x1E21, "\u{1e20}"), + (0x1E23, "\u{1e22}"), + (0x1E25, "\u{1e24}"), + (0x1E27, "\u{1e26}"), + (0x1E29, "\u{1e28}"), + (0x1E2B, "\u{1e2a}"), + (0x1E2D, "\u{1e2c}"), + (0x1E2F, "\u{1e2e}"), + (0x1E31, "\u{1e30}"), + (0x1E33, "\u{1e32}"), + (0x1E35, "\u{1e34}"), + (0x1E37, "\u{1e36}"), + (0x1E39, "\u{1e38}"), + (0x1E3B, "\u{1e3a}"), + (0x1E3D, "\u{1e3c}"), + (0x1E3F, "\u{1e3e}"), + (0x1E41, "\u{1e40}"), + (0x1E43, "\u{1e42}"), + (0x1E45, "\u{1e44}"), + (0x1E47, "\u{1e46}"), + (0x1E49, "\u{1e48}"), + (0x1E4B, "\u{1e4a}"), + (0x1E4D, "\u{1e4c}"), + (0x1E4F, "\u{1e4e}"), + (0x1E51, "\u{1e50}"), + (0x1E53, "\u{1e52}"), + (0x1E55, "\u{1e54}"), + (0x1E57, "\u{1e56}"), + (0x1E59, "\u{1e58}"), + (0x1E5B, "\u{1e5a}"), + (0x1E5D, "\u{1e5c}"), + (0x1E5F, "\u{1e5e}"), + (0x1E61, "\u{1e60}"), + (0x1E63, "\u{1e62}"), + (0x1E65, "\u{1e64}"), + (0x1E67, "\u{1e66}"), + (0x1E69, "\u{1e68}"), + (0x1E6B, "\u{1e6a}"), + (0x1E6D, "\u{1e6c}"), + (0x1E6F, "\u{1e6e}"), + (0x1E71, "\u{1e70}"), + (0x1E73, "\u{1e72}"), + (0x1E75, "\u{1e74}"), + (0x1E77, "\u{1e76}"), + (0x1E79, "\u{1e78}"), + (0x1E7B, "\u{1e7a}"), + (0x1E7D, "\u{1e7c}"), + (0x1E7F, "\u{1e7e}"), + (0x1E81, "\u{1e80}"), + (0x1E83, "\u{1e82}"), + (0x1E85, "\u{1e84}"), + (0x1E87, "\u{1e86}"), + (0x1E89, "\u{1e88}"), + (0x1E8B, "\u{1e8a}"), + (0x1E8D, "\u{1e8c}"), + (0x1E8F, "\u{1e8e}"), + (0x1E91, "\u{1e90}"), + (0x1E93, "\u{1e92}"), + (0x1E95, "\u{1e94}"), + (0x1E96, "\u{48}\u{331}"), + (0x1E97, "\u{54}\u{308}"), + (0x1E98, "\u{57}\u{30a}"), + (0x1E99, "\u{59}\u{30a}"), + (0x1E9A, "\u{41}\u{2be}"), + (0x1E9B, "\u{1e60}"), + (0x1EA1, "\u{1ea0}"), + (0x1EA3, "\u{1ea2}"), + (0x1EA5, "\u{1ea4}"), + (0x1EA7, "\u{1ea6}"), + (0x1EA9, "\u{1ea8}"), + (0x1EAB, "\u{1eaa}"), + (0x1EAD, "\u{1eac}"), + (0x1EAF, "\u{1eae}"), + (0x1EB1, "\u{1eb0}"), + (0x1EB3, "\u{1eb2}"), + (0x1EB5, "\u{1eb4}"), + (0x1EB7, "\u{1eb6}"), + (0x1EB9, "\u{1eb8}"), + (0x1EBB, "\u{1eba}"), + (0x1EBD, "\u{1ebc}"), + (0x1EBF, "\u{1ebe}"), + (0x1EC1, "\u{1ec0}"), + (0x1EC3, "\u{1ec2}"), + (0x1EC5, "\u{1ec4}"), + (0x1EC7, "\u{1ec6}"), + (0x1EC9, "\u{1ec8}"), + (0x1ECB, "\u{1eca}"), + (0x1ECD, "\u{1ecc}"), + (0x1ECF, "\u{1ece}"), + (0x1ED1, "\u{1ed0}"), + (0x1ED3, "\u{1ed2}"), + (0x1ED5, "\u{1ed4}"), + (0x1ED7, "\u{1ed6}"), + (0x1ED9, "\u{1ed8}"), + (0x1EDB, "\u{1eda}"), + (0x1EDD, "\u{1edc}"), + (0x1EDF, "\u{1ede}"), + (0x1EE1, "\u{1ee0}"), + (0x1EE3, "\u{1ee2}"), + (0x1EE5, "\u{1ee4}"), + (0x1EE7, "\u{1ee6}"), + (0x1EE9, "\u{1ee8}"), + (0x1EEB, "\u{1eea}"), + (0x1EED, "\u{1eec}"), + (0x1EEF, "\u{1eee}"), + (0x1EF1, "\u{1ef0}"), + (0x1EF3, "\u{1ef2}"), + (0x1EF5, "\u{1ef4}"), + (0x1EF7, "\u{1ef6}"), + (0x1EF9, "\u{1ef8}"), + (0x1EFB, "\u{1efa}"), + (0x1EFD, "\u{1efc}"), + (0x1EFF, "\u{1efe}"), + (0x1F00, "\u{1f08}"), + (0x1F01, "\u{1f09}"), + (0x1F02, "\u{1f0a}"), + (0x1F03, "\u{1f0b}"), + (0x1F04, "\u{1f0c}"), + (0x1F05, "\u{1f0d}"), + (0x1F06, "\u{1f0e}"), + (0x1F07, "\u{1f0f}"), + (0x1F10, "\u{1f18}"), + (0x1F11, "\u{1f19}"), + (0x1F12, "\u{1f1a}"), + (0x1F13, "\u{1f1b}"), + (0x1F14, "\u{1f1c}"), + (0x1F15, "\u{1f1d}"), + (0x1F20, "\u{1f28}"), + (0x1F21, "\u{1f29}"), + (0x1F22, "\u{1f2a}"), + (0x1F23, "\u{1f2b}"), + (0x1F24, "\u{1f2c}"), + (0x1F25, "\u{1f2d}"), + (0x1F26, "\u{1f2e}"), + (0x1F27, "\u{1f2f}"), + (0x1F30, "\u{1f38}"), + (0x1F31, "\u{1f39}"), + (0x1F32, "\u{1f3a}"), + (0x1F33, "\u{1f3b}"), + (0x1F34, "\u{1f3c}"), + (0x1F35, "\u{1f3d}"), + (0x1F36, "\u{1f3e}"), + (0x1F37, "\u{1f3f}"), + (0x1F40, "\u{1f48}"), + (0x1F41, "\u{1f49}"), + (0x1F42, "\u{1f4a}"), + (0x1F43, "\u{1f4b}"), + (0x1F44, "\u{1f4c}"), + (0x1F45, "\u{1f4d}"), + (0x1F50, "\u{3a5}\u{313}"), + (0x1F51, "\u{1f59}"), + (0x1F52, "\u{3a5}\u{313}\u{300}"), + (0x1F53, "\u{1f5b}"), + (0x1F54, "\u{3a5}\u{313}\u{301}"), + (0x1F55, "\u{1f5d}"), + (0x1F56, "\u{3a5}\u{313}\u{342}"), + (0x1F57, "\u{1f5f}"), + (0x1F60, "\u{1f68}"), + (0x1F61, "\u{1f69}"), + (0x1F62, "\u{1f6a}"), + (0x1F63, "\u{1f6b}"), + (0x1F64, "\u{1f6c}"), + (0x1F65, "\u{1f6d}"), + (0x1F66, "\u{1f6e}"), + (0x1F67, "\u{1f6f}"), + (0x1F70, "\u{1fba}"), + (0x1F71, "\u{1fbb}"), + (0x1F72, "\u{1fc8}"), + (0x1F73, "\u{1fc9}"), + (0x1F74, "\u{1fca}"), + (0x1F75, "\u{1fcb}"), + (0x1F76, "\u{1fda}"), + (0x1F77, "\u{1fdb}"), + (0x1F78, "\u{1ff8}"), + (0x1F79, "\u{1ff9}"), + (0x1F7A, "\u{1fea}"), + (0x1F7B, "\u{1feb}"), + (0x1F7C, "\u{1ffa}"), + (0x1F7D, "\u{1ffb}"), + (0x1F80, "\u{1f08}\u{399}"), + (0x1F81, "\u{1f09}\u{399}"), + (0x1F82, "\u{1f0a}\u{399}"), + (0x1F83, "\u{1f0b}\u{399}"), + (0x1F84, "\u{1f0c}\u{399}"), + (0x1F85, "\u{1f0d}\u{399}"), + (0x1F86, "\u{1f0e}\u{399}"), + (0x1F87, "\u{1f0f}\u{399}"), + (0x1F88, "\u{1f08}\u{399}"), + (0x1F89, "\u{1f09}\u{399}"), + (0x1F8A, "\u{1f0a}\u{399}"), + (0x1F8B, "\u{1f0b}\u{399}"), + (0x1F8C, "\u{1f0c}\u{399}"), + (0x1F8D, "\u{1f0d}\u{399}"), + (0x1F8E, "\u{1f0e}\u{399}"), + (0x1F8F, "\u{1f0f}\u{399}"), + (0x1F90, "\u{1f28}\u{399}"), + (0x1F91, "\u{1f29}\u{399}"), + (0x1F92, "\u{1f2a}\u{399}"), + (0x1F93, "\u{1f2b}\u{399}"), + (0x1F94, "\u{1f2c}\u{399}"), + (0x1F95, "\u{1f2d}\u{399}"), + (0x1F96, "\u{1f2e}\u{399}"), + (0x1F97, "\u{1f2f}\u{399}"), + (0x1F98, "\u{1f28}\u{399}"), + (0x1F99, "\u{1f29}\u{399}"), + (0x1F9A, "\u{1f2a}\u{399}"), + (0x1F9B, "\u{1f2b}\u{399}"), + (0x1F9C, "\u{1f2c}\u{399}"), + (0x1F9D, "\u{1f2d}\u{399}"), + (0x1F9E, "\u{1f2e}\u{399}"), + (0x1F9F, "\u{1f2f}\u{399}"), + (0x1FA0, "\u{1f68}\u{399}"), + (0x1FA1, "\u{1f69}\u{399}"), + (0x1FA2, "\u{1f6a}\u{399}"), + (0x1FA3, "\u{1f6b}\u{399}"), + (0x1FA4, "\u{1f6c}\u{399}"), + (0x1FA5, "\u{1f6d}\u{399}"), + (0x1FA6, "\u{1f6e}\u{399}"), + (0x1FA7, "\u{1f6f}\u{399}"), + (0x1FA8, "\u{1f68}\u{399}"), + (0x1FA9, "\u{1f69}\u{399}"), + (0x1FAA, "\u{1f6a}\u{399}"), + (0x1FAB, "\u{1f6b}\u{399}"), + (0x1FAC, "\u{1f6c}\u{399}"), + (0x1FAD, "\u{1f6d}\u{399}"), + (0x1FAE, "\u{1f6e}\u{399}"), + (0x1FAF, "\u{1f6f}\u{399}"), + (0x1FB0, "\u{1fb8}"), + (0x1FB1, "\u{1fb9}"), + (0x1FB2, "\u{1fba}\u{399}"), + (0x1FB3, "\u{391}\u{399}"), + (0x1FB4, "\u{386}\u{399}"), + (0x1FB6, "\u{391}\u{342}"), + (0x1FB7, "\u{391}\u{342}\u{399}"), + (0x1FBC, "\u{391}\u{399}"), + (0x1FBE, "\u{399}"), + (0x1FC2, "\u{1fca}\u{399}"), + (0x1FC3, "\u{397}\u{399}"), + (0x1FC4, "\u{389}\u{399}"), + (0x1FC6, "\u{397}\u{342}"), + (0x1FC7, "\u{397}\u{342}\u{399}"), + (0x1FCC, "\u{397}\u{399}"), + (0x1FD0, "\u{1fd8}"), + (0x1FD1, "\u{1fd9}"), + (0x1FD2, "\u{399}\u{308}\u{300}"), + (0x1FD3, "\u{399}\u{308}\u{301}"), + (0x1FD6, "\u{399}\u{342}"), + (0x1FD7, "\u{399}\u{308}\u{342}"), + (0x1FE0, "\u{1fe8}"), + (0x1FE1, "\u{1fe9}"), + (0x1FE2, "\u{3a5}\u{308}\u{300}"), + (0x1FE3, "\u{3a5}\u{308}\u{301}"), + (0x1FE4, "\u{3a1}\u{313}"), + (0x1FE5, "\u{1fec}"), + (0x1FE6, "\u{3a5}\u{342}"), + (0x1FE7, "\u{3a5}\u{308}\u{342}"), + (0x1FF2, "\u{1ffa}\u{399}"), + (0x1FF3, "\u{3a9}\u{399}"), + (0x1FF4, "\u{38f}\u{399}"), + (0x1FF6, "\u{3a9}\u{342}"), + (0x1FF7, "\u{3a9}\u{342}\u{399}"), + (0x1FFC, "\u{3a9}\u{399}"), + (0x214E, "\u{2132}"), + (0x2170, "\u{2160}"), + (0x2171, "\u{2161}"), + (0x2172, "\u{2162}"), + (0x2173, "\u{2163}"), + (0x2174, "\u{2164}"), + (0x2175, "\u{2165}"), + (0x2176, "\u{2166}"), + (0x2177, "\u{2167}"), + (0x2178, "\u{2168}"), + (0x2179, "\u{2169}"), + (0x217A, "\u{216a}"), + (0x217B, "\u{216b}"), + (0x217C, "\u{216c}"), + (0x217D, "\u{216d}"), + (0x217E, "\u{216e}"), + (0x217F, "\u{216f}"), + (0x2184, "\u{2183}"), + (0x24D0, "\u{24b6}"), + (0x24D1, "\u{24b7}"), + (0x24D2, "\u{24b8}"), + (0x24D3, "\u{24b9}"), + (0x24D4, "\u{24ba}"), + (0x24D5, "\u{24bb}"), + (0x24D6, "\u{24bc}"), + (0x24D7, "\u{24bd}"), + (0x24D8, "\u{24be}"), + (0x24D9, "\u{24bf}"), + (0x24DA, "\u{24c0}"), + (0x24DB, "\u{24c1}"), + (0x24DC, "\u{24c2}"), + (0x24DD, "\u{24c3}"), + (0x24DE, "\u{24c4}"), + (0x24DF, "\u{24c5}"), + (0x24E0, "\u{24c6}"), + (0x24E1, "\u{24c7}"), + (0x24E2, "\u{24c8}"), + (0x24E3, "\u{24c9}"), + (0x24E4, "\u{24ca}"), + (0x24E5, "\u{24cb}"), + (0x24E6, "\u{24cc}"), + (0x24E7, "\u{24cd}"), + (0x24E8, "\u{24ce}"), + (0x24E9, "\u{24cf}"), + (0x2C30, "\u{2c00}"), + (0x2C31, "\u{2c01}"), + (0x2C32, "\u{2c02}"), + (0x2C33, "\u{2c03}"), + (0x2C34, "\u{2c04}"), + (0x2C35, "\u{2c05}"), + (0x2C36, "\u{2c06}"), + (0x2C37, "\u{2c07}"), + (0x2C38, "\u{2c08}"), + (0x2C39, "\u{2c09}"), + (0x2C3A, "\u{2c0a}"), + (0x2C3B, "\u{2c0b}"), + (0x2C3C, "\u{2c0c}"), + (0x2C3D, "\u{2c0d}"), + (0x2C3E, "\u{2c0e}"), + (0x2C3F, "\u{2c0f}"), + (0x2C40, "\u{2c10}"), + (0x2C41, "\u{2c11}"), + (0x2C42, "\u{2c12}"), + (0x2C43, "\u{2c13}"), + (0x2C44, "\u{2c14}"), + (0x2C45, "\u{2c15}"), + (0x2C46, "\u{2c16}"), + (0x2C47, "\u{2c17}"), + (0x2C48, "\u{2c18}"), + (0x2C49, "\u{2c19}"), + (0x2C4A, "\u{2c1a}"), + (0x2C4B, "\u{2c1b}"), + (0x2C4C, "\u{2c1c}"), + (0x2C4D, "\u{2c1d}"), + (0x2C4E, "\u{2c1e}"), + (0x2C4F, "\u{2c1f}"), + (0x2C50, "\u{2c20}"), + (0x2C51, "\u{2c21}"), + (0x2C52, "\u{2c22}"), + (0x2C53, "\u{2c23}"), + (0x2C54, "\u{2c24}"), + (0x2C55, "\u{2c25}"), + (0x2C56, "\u{2c26}"), + (0x2C57, "\u{2c27}"), + (0x2C58, "\u{2c28}"), + (0x2C59, "\u{2c29}"), + (0x2C5A, "\u{2c2a}"), + (0x2C5B, "\u{2c2b}"), + (0x2C5C, "\u{2c2c}"), + (0x2C5D, "\u{2c2d}"), + (0x2C5E, "\u{2c2e}"), + (0x2C5F, "\u{2c2f}"), + (0x2C61, "\u{2c60}"), + (0x2C65, "\u{23a}"), + (0x2C66, "\u{23e}"), + (0x2C68, "\u{2c67}"), + (0x2C6A, "\u{2c69}"), + (0x2C6C, "\u{2c6b}"), + (0x2C73, "\u{2c72}"), + (0x2C76, "\u{2c75}"), + (0x2C81, "\u{2c80}"), + (0x2C83, "\u{2c82}"), + (0x2C85, "\u{2c84}"), + (0x2C87, "\u{2c86}"), + (0x2C89, "\u{2c88}"), + (0x2C8B, "\u{2c8a}"), + (0x2C8D, "\u{2c8c}"), + (0x2C8F, "\u{2c8e}"), + (0x2C91, "\u{2c90}"), + (0x2C93, "\u{2c92}"), + (0x2C95, "\u{2c94}"), + (0x2C97, "\u{2c96}"), + (0x2C99, "\u{2c98}"), + (0x2C9B, "\u{2c9a}"), + (0x2C9D, "\u{2c9c}"), + (0x2C9F, "\u{2c9e}"), + (0x2CA1, "\u{2ca0}"), + (0x2CA3, "\u{2ca2}"), + (0x2CA5, "\u{2ca4}"), + (0x2CA7, "\u{2ca6}"), + (0x2CA9, "\u{2ca8}"), + (0x2CAB, "\u{2caa}"), + (0x2CAD, "\u{2cac}"), + (0x2CAF, "\u{2cae}"), + (0x2CB1, "\u{2cb0}"), + (0x2CB3, "\u{2cb2}"), + (0x2CB5, "\u{2cb4}"), + (0x2CB7, "\u{2cb6}"), + (0x2CB9, "\u{2cb8}"), + (0x2CBB, "\u{2cba}"), + (0x2CBD, "\u{2cbc}"), + (0x2CBF, "\u{2cbe}"), + (0x2CC1, "\u{2cc0}"), + (0x2CC3, "\u{2cc2}"), + (0x2CC5, "\u{2cc4}"), + (0x2CC7, "\u{2cc6}"), + (0x2CC9, "\u{2cc8}"), + (0x2CCB, "\u{2cca}"), + (0x2CCD, "\u{2ccc}"), + (0x2CCF, "\u{2cce}"), + (0x2CD1, "\u{2cd0}"), + (0x2CD3, "\u{2cd2}"), + (0x2CD5, "\u{2cd4}"), + (0x2CD7, "\u{2cd6}"), + (0x2CD9, "\u{2cd8}"), + (0x2CDB, "\u{2cda}"), + (0x2CDD, "\u{2cdc}"), + (0x2CDF, "\u{2cde}"), + (0x2CE1, "\u{2ce0}"), + (0x2CE3, "\u{2ce2}"), + (0x2CEC, "\u{2ceb}"), + (0x2CEE, "\u{2ced}"), + (0x2CF3, "\u{2cf2}"), + (0x2D00, "\u{10a0}"), + (0x2D01, "\u{10a1}"), + (0x2D02, "\u{10a2}"), + (0x2D03, "\u{10a3}"), + (0x2D04, "\u{10a4}"), + (0x2D05, "\u{10a5}"), + (0x2D06, "\u{10a6}"), + (0x2D07, "\u{10a7}"), + (0x2D08, "\u{10a8}"), + (0x2D09, "\u{10a9}"), + (0x2D0A, "\u{10aa}"), + (0x2D0B, "\u{10ab}"), + (0x2D0C, "\u{10ac}"), + (0x2D0D, "\u{10ad}"), + (0x2D0E, "\u{10ae}"), + (0x2D0F, "\u{10af}"), + (0x2D10, "\u{10b0}"), + (0x2D11, "\u{10b1}"), + (0x2D12, "\u{10b2}"), + (0x2D13, "\u{10b3}"), + (0x2D14, "\u{10b4}"), + (0x2D15, "\u{10b5}"), + (0x2D16, "\u{10b6}"), + (0x2D17, "\u{10b7}"), + (0x2D18, "\u{10b8}"), + (0x2D19, "\u{10b9}"), + (0x2D1A, "\u{10ba}"), + (0x2D1B, "\u{10bb}"), + (0x2D1C, "\u{10bc}"), + (0x2D1D, "\u{10bd}"), + (0x2D1E, "\u{10be}"), + (0x2D1F, "\u{10bf}"), + (0x2D20, "\u{10c0}"), + (0x2D21, "\u{10c1}"), + (0x2D22, "\u{10c2}"), + (0x2D23, "\u{10c3}"), + (0x2D24, "\u{10c4}"), + (0x2D25, "\u{10c5}"), + (0x2D27, "\u{10c7}"), + (0x2D2D, "\u{10cd}"), + (0xA641, "\u{a640}"), + (0xA643, "\u{a642}"), + (0xA645, "\u{a644}"), + (0xA647, "\u{a646}"), + (0xA649, "\u{a648}"), + (0xA64B, "\u{a64a}"), + (0xA64D, "\u{a64c}"), + (0xA64F, "\u{a64e}"), + (0xA651, "\u{a650}"), + (0xA653, "\u{a652}"), + (0xA655, "\u{a654}"), + (0xA657, "\u{a656}"), + (0xA659, "\u{a658}"), + (0xA65B, "\u{a65a}"), + (0xA65D, "\u{a65c}"), + (0xA65F, "\u{a65e}"), + (0xA661, "\u{a660}"), + (0xA663, "\u{a662}"), + (0xA665, "\u{a664}"), + (0xA667, "\u{a666}"), + (0xA669, "\u{a668}"), + (0xA66B, "\u{a66a}"), + (0xA66D, "\u{a66c}"), + (0xA681, "\u{a680}"), + (0xA683, "\u{a682}"), + (0xA685, "\u{a684}"), + (0xA687, "\u{a686}"), + (0xA689, "\u{a688}"), + (0xA68B, "\u{a68a}"), + (0xA68D, "\u{a68c}"), + (0xA68F, "\u{a68e}"), + (0xA691, "\u{a690}"), + (0xA693, "\u{a692}"), + (0xA695, "\u{a694}"), + (0xA697, "\u{a696}"), + (0xA699, "\u{a698}"), + (0xA69B, "\u{a69a}"), + (0xA723, "\u{a722}"), + (0xA725, "\u{a724}"), + (0xA727, "\u{a726}"), + (0xA729, "\u{a728}"), + (0xA72B, "\u{a72a}"), + (0xA72D, "\u{a72c}"), + (0xA72F, "\u{a72e}"), + (0xA733, "\u{a732}"), + (0xA735, "\u{a734}"), + (0xA737, "\u{a736}"), + (0xA739, "\u{a738}"), + (0xA73B, "\u{a73a}"), + (0xA73D, "\u{a73c}"), + (0xA73F, "\u{a73e}"), + (0xA741, "\u{a740}"), + (0xA743, "\u{a742}"), + (0xA745, "\u{a744}"), + (0xA747, "\u{a746}"), + (0xA749, "\u{a748}"), + (0xA74B, "\u{a74a}"), + (0xA74D, "\u{a74c}"), + (0xA74F, "\u{a74e}"), + (0xA751, "\u{a750}"), + (0xA753, "\u{a752}"), + (0xA755, "\u{a754}"), + (0xA757, "\u{a756}"), + (0xA759, "\u{a758}"), + (0xA75B, "\u{a75a}"), + (0xA75D, "\u{a75c}"), + (0xA75F, "\u{a75e}"), + (0xA761, "\u{a760}"), + (0xA763, "\u{a762}"), + (0xA765, "\u{a764}"), + (0xA767, "\u{a766}"), + (0xA769, "\u{a768}"), + (0xA76B, "\u{a76a}"), + (0xA76D, "\u{a76c}"), + (0xA76F, "\u{a76e}"), + (0xA77A, "\u{a779}"), + (0xA77C, "\u{a77b}"), + (0xA77F, "\u{a77e}"), + (0xA781, "\u{a780}"), + (0xA783, "\u{a782}"), + (0xA785, "\u{a784}"), + (0xA787, "\u{a786}"), + (0xA78C, "\u{a78b}"), + (0xA791, "\u{a790}"), + (0xA793, "\u{a792}"), + (0xA794, "\u{a7c4}"), + (0xA797, "\u{a796}"), + (0xA799, "\u{a798}"), + (0xA79B, "\u{a79a}"), + (0xA79D, "\u{a79c}"), + (0xA79F, "\u{a79e}"), + (0xA7A1, "\u{a7a0}"), + (0xA7A3, "\u{a7a2}"), + (0xA7A5, "\u{a7a4}"), + (0xA7A7, "\u{a7a6}"), + (0xA7A9, "\u{a7a8}"), + (0xA7B5, "\u{a7b4}"), + (0xA7B7, "\u{a7b6}"), + (0xA7B9, "\u{a7b8}"), + (0xA7BB, "\u{a7ba}"), + (0xA7BD, "\u{a7bc}"), + (0xA7BF, "\u{a7be}"), + (0xA7C1, "\u{a7c0}"), + (0xA7C3, "\u{a7c2}"), + (0xA7C8, "\u{a7c7}"), + (0xA7CA, "\u{a7c9}"), + (0xA7CD, "\u{a7cc}"), + (0xA7D1, "\u{a7d0}"), + (0xA7D7, "\u{a7d6}"), + (0xA7D9, "\u{a7d8}"), + (0xA7DB, "\u{a7da}"), + (0xA7F6, "\u{a7f5}"), + (0xAB53, "\u{a7b3}"), + (0xAB70, "\u{13a0}"), + (0xAB71, "\u{13a1}"), + (0xAB72, "\u{13a2}"), + (0xAB73, "\u{13a3}"), + (0xAB74, "\u{13a4}"), + (0xAB75, "\u{13a5}"), + (0xAB76, "\u{13a6}"), + (0xAB77, "\u{13a7}"), + (0xAB78, "\u{13a8}"), + (0xAB79, "\u{13a9}"), + (0xAB7A, "\u{13aa}"), + (0xAB7B, "\u{13ab}"), + (0xAB7C, "\u{13ac}"), + (0xAB7D, "\u{13ad}"), + (0xAB7E, "\u{13ae}"), + (0xAB7F, "\u{13af}"), + (0xAB80, "\u{13b0}"), + (0xAB81, "\u{13b1}"), + (0xAB82, "\u{13b2}"), + (0xAB83, "\u{13b3}"), + (0xAB84, "\u{13b4}"), + (0xAB85, "\u{13b5}"), + (0xAB86, "\u{13b6}"), + (0xAB87, "\u{13b7}"), + (0xAB88, "\u{13b8}"), + (0xAB89, "\u{13b9}"), + (0xAB8A, "\u{13ba}"), + (0xAB8B, "\u{13bb}"), + (0xAB8C, "\u{13bc}"), + (0xAB8D, "\u{13bd}"), + (0xAB8E, "\u{13be}"), + (0xAB8F, "\u{13bf}"), + (0xAB90, "\u{13c0}"), + (0xAB91, "\u{13c1}"), + (0xAB92, "\u{13c2}"), + (0xAB93, "\u{13c3}"), + (0xAB94, "\u{13c4}"), + (0xAB95, "\u{13c5}"), + (0xAB96, "\u{13c6}"), + (0xAB97, "\u{13c7}"), + (0xAB98, "\u{13c8}"), + (0xAB99, "\u{13c9}"), + (0xAB9A, "\u{13ca}"), + (0xAB9B, "\u{13cb}"), + (0xAB9C, "\u{13cc}"), + (0xAB9D, "\u{13cd}"), + (0xAB9E, "\u{13ce}"), + (0xAB9F, "\u{13cf}"), + (0xABA0, "\u{13d0}"), + (0xABA1, "\u{13d1}"), + (0xABA2, "\u{13d2}"), + (0xABA3, "\u{13d3}"), + (0xABA4, "\u{13d4}"), + (0xABA5, "\u{13d5}"), + (0xABA6, "\u{13d6}"), + (0xABA7, "\u{13d7}"), + (0xABA8, "\u{13d8}"), + (0xABA9, "\u{13d9}"), + (0xABAA, "\u{13da}"), + (0xABAB, "\u{13db}"), + (0xABAC, "\u{13dc}"), + (0xABAD, "\u{13dd}"), + (0xABAE, "\u{13de}"), + (0xABAF, "\u{13df}"), + (0xABB0, "\u{13e0}"), + (0xABB1, "\u{13e1}"), + (0xABB2, "\u{13e2}"), + (0xABB3, "\u{13e3}"), + (0xABB4, "\u{13e4}"), + (0xABB5, "\u{13e5}"), + (0xABB6, "\u{13e6}"), + (0xABB7, "\u{13e7}"), + (0xABB8, "\u{13e8}"), + (0xABB9, "\u{13e9}"), + (0xABBA, "\u{13ea}"), + (0xABBB, "\u{13eb}"), + (0xABBC, "\u{13ec}"), + (0xABBD, "\u{13ed}"), + (0xABBE, "\u{13ee}"), + (0xABBF, "\u{13ef}"), + (0xFB00, "\u{46}\u{46}"), + (0xFB01, "\u{46}\u{49}"), + (0xFB02, "\u{46}\u{4c}"), + (0xFB03, "\u{46}\u{46}\u{49}"), + (0xFB04, "\u{46}\u{46}\u{4c}"), + (0xFB05, "\u{53}\u{54}"), + (0xFB06, "\u{53}\u{54}"), + (0xFB13, "\u{544}\u{546}"), + (0xFB14, "\u{544}\u{535}"), + (0xFB15, "\u{544}\u{53b}"), + (0xFB16, "\u{54e}\u{546}"), + (0xFB17, "\u{544}\u{53d}"), + (0xFF41, "\u{ff21}"), + (0xFF42, "\u{ff22}"), + (0xFF43, "\u{ff23}"), + (0xFF44, "\u{ff24}"), + (0xFF45, "\u{ff25}"), + (0xFF46, "\u{ff26}"), + (0xFF47, "\u{ff27}"), + (0xFF48, "\u{ff28}"), + (0xFF49, "\u{ff29}"), + (0xFF4A, "\u{ff2a}"), + (0xFF4B, "\u{ff2b}"), + (0xFF4C, "\u{ff2c}"), + (0xFF4D, "\u{ff2d}"), + (0xFF4E, "\u{ff2e}"), + (0xFF4F, "\u{ff2f}"), + (0xFF50, "\u{ff30}"), + (0xFF51, "\u{ff31}"), + (0xFF52, "\u{ff32}"), + (0xFF53, "\u{ff33}"), + (0xFF54, "\u{ff34}"), + (0xFF55, "\u{ff35}"), + (0xFF56, "\u{ff36}"), + (0xFF57, "\u{ff37}"), + (0xFF58, "\u{ff38}"), + (0xFF59, "\u{ff39}"), + (0xFF5A, "\u{ff3a}"), + (0x10428, "\u{10400}"), + (0x10429, "\u{10401}"), + (0x1042A, "\u{10402}"), + (0x1042B, "\u{10403}"), + (0x1042C, "\u{10404}"), + (0x1042D, "\u{10405}"), + (0x1042E, "\u{10406}"), + (0x1042F, "\u{10407}"), + (0x10430, "\u{10408}"), + (0x10431, "\u{10409}"), + (0x10432, "\u{1040a}"), + (0x10433, "\u{1040b}"), + (0x10434, "\u{1040c}"), + (0x10435, "\u{1040d}"), + (0x10436, "\u{1040e}"), + (0x10437, "\u{1040f}"), + (0x10438, "\u{10410}"), + (0x10439, "\u{10411}"), + (0x1043A, "\u{10412}"), + (0x1043B, "\u{10413}"), + (0x1043C, "\u{10414}"), + (0x1043D, "\u{10415}"), + (0x1043E, "\u{10416}"), + (0x1043F, "\u{10417}"), + (0x10440, "\u{10418}"), + (0x10441, "\u{10419}"), + (0x10442, "\u{1041a}"), + (0x10443, "\u{1041b}"), + (0x10444, "\u{1041c}"), + (0x10445, "\u{1041d}"), + (0x10446, "\u{1041e}"), + (0x10447, "\u{1041f}"), + (0x10448, "\u{10420}"), + (0x10449, "\u{10421}"), + (0x1044A, "\u{10422}"), + (0x1044B, "\u{10423}"), + (0x1044C, "\u{10424}"), + (0x1044D, "\u{10425}"), + (0x1044E, "\u{10426}"), + (0x1044F, "\u{10427}"), + (0x104D8, "\u{104b0}"), + (0x104D9, "\u{104b1}"), + (0x104DA, "\u{104b2}"), + (0x104DB, "\u{104b3}"), + (0x104DC, "\u{104b4}"), + (0x104DD, "\u{104b5}"), + (0x104DE, "\u{104b6}"), + (0x104DF, "\u{104b7}"), + (0x104E0, "\u{104b8}"), + (0x104E1, "\u{104b9}"), + (0x104E2, "\u{104ba}"), + (0x104E3, "\u{104bb}"), + (0x104E4, "\u{104bc}"), + (0x104E5, "\u{104bd}"), + (0x104E6, "\u{104be}"), + (0x104E7, "\u{104bf}"), + (0x104E8, "\u{104c0}"), + (0x104E9, "\u{104c1}"), + (0x104EA, "\u{104c2}"), + (0x104EB, "\u{104c3}"), + (0x104EC, "\u{104c4}"), + (0x104ED, "\u{104c5}"), + (0x104EE, "\u{104c6}"), + (0x104EF, "\u{104c7}"), + (0x104F0, "\u{104c8}"), + (0x104F1, "\u{104c9}"), + (0x104F2, "\u{104ca}"), + (0x104F3, "\u{104cb}"), + (0x104F4, "\u{104cc}"), + (0x104F5, "\u{104cd}"), + (0x104F6, "\u{104ce}"), + (0x104F7, "\u{104cf}"), + (0x104F8, "\u{104d0}"), + (0x104F9, "\u{104d1}"), + (0x104FA, "\u{104d2}"), + (0x104FB, "\u{104d3}"), + (0x10597, "\u{10570}"), + (0x10598, "\u{10571}"), + (0x10599, "\u{10572}"), + (0x1059A, "\u{10573}"), + (0x1059B, "\u{10574}"), + (0x1059C, "\u{10575}"), + (0x1059D, "\u{10576}"), + (0x1059E, "\u{10577}"), + (0x1059F, "\u{10578}"), + (0x105A0, "\u{10579}"), + (0x105A1, "\u{1057a}"), + (0x105A3, "\u{1057c}"), + (0x105A4, "\u{1057d}"), + (0x105A5, "\u{1057e}"), + (0x105A6, "\u{1057f}"), + (0x105A7, "\u{10580}"), + (0x105A8, "\u{10581}"), + (0x105A9, "\u{10582}"), + (0x105AA, "\u{10583}"), + (0x105AB, "\u{10584}"), + (0x105AC, "\u{10585}"), + (0x105AD, "\u{10586}"), + (0x105AE, "\u{10587}"), + (0x105AF, "\u{10588}"), + (0x105B0, "\u{10589}"), + (0x105B1, "\u{1058a}"), + (0x105B3, "\u{1058c}"), + (0x105B4, "\u{1058d}"), + (0x105B5, "\u{1058e}"), + (0x105B6, "\u{1058f}"), + (0x105B7, "\u{10590}"), + (0x105B8, "\u{10591}"), + (0x105B9, "\u{10592}"), + (0x105BB, "\u{10594}"), + (0x105BC, "\u{10595}"), + (0x10CC0, "\u{10c80}"), + (0x10CC1, "\u{10c81}"), + (0x10CC2, "\u{10c82}"), + (0x10CC3, "\u{10c83}"), + (0x10CC4, "\u{10c84}"), + (0x10CC5, "\u{10c85}"), + (0x10CC6, "\u{10c86}"), + (0x10CC7, "\u{10c87}"), + (0x10CC8, "\u{10c88}"), + (0x10CC9, "\u{10c89}"), + (0x10CCA, "\u{10c8a}"), + (0x10CCB, "\u{10c8b}"), + (0x10CCC, "\u{10c8c}"), + (0x10CCD, "\u{10c8d}"), + (0x10CCE, "\u{10c8e}"), + (0x10CCF, "\u{10c8f}"), + (0x10CD0, "\u{10c90}"), + (0x10CD1, "\u{10c91}"), + (0x10CD2, "\u{10c92}"), + (0x10CD3, "\u{10c93}"), + (0x10CD4, "\u{10c94}"), + (0x10CD5, "\u{10c95}"), + (0x10CD6, "\u{10c96}"), + (0x10CD7, "\u{10c97}"), + (0x10CD8, "\u{10c98}"), + (0x10CD9, "\u{10c99}"), + (0x10CDA, "\u{10c9a}"), + (0x10CDB, "\u{10c9b}"), + (0x10CDC, "\u{10c9c}"), + (0x10CDD, "\u{10c9d}"), + (0x10CDE, "\u{10c9e}"), + (0x10CDF, "\u{10c9f}"), + (0x10CE0, "\u{10ca0}"), + (0x10CE1, "\u{10ca1}"), + (0x10CE2, "\u{10ca2}"), + (0x10CE3, "\u{10ca3}"), + (0x10CE4, "\u{10ca4}"), + (0x10CE5, "\u{10ca5}"), + (0x10CE6, "\u{10ca6}"), + (0x10CE7, "\u{10ca7}"), + (0x10CE8, "\u{10ca8}"), + (0x10CE9, "\u{10ca9}"), + (0x10CEA, "\u{10caa}"), + (0x10CEB, "\u{10cab}"), + (0x10CEC, "\u{10cac}"), + (0x10CED, "\u{10cad}"), + (0x10CEE, "\u{10cae}"), + (0x10CEF, "\u{10caf}"), + (0x10CF0, "\u{10cb0}"), + (0x10CF1, "\u{10cb1}"), + (0x10CF2, "\u{10cb2}"), + (0x10D70, "\u{10d50}"), + (0x10D71, "\u{10d51}"), + (0x10D72, "\u{10d52}"), + (0x10D73, "\u{10d53}"), + (0x10D74, "\u{10d54}"), + (0x10D75, "\u{10d55}"), + (0x10D76, "\u{10d56}"), + (0x10D77, "\u{10d57}"), + (0x10D78, "\u{10d58}"), + (0x10D79, "\u{10d59}"), + (0x10D7A, "\u{10d5a}"), + (0x10D7B, "\u{10d5b}"), + (0x10D7C, "\u{10d5c}"), + (0x10D7D, "\u{10d5d}"), + (0x10D7E, "\u{10d5e}"), + (0x10D7F, "\u{10d5f}"), + (0x10D80, "\u{10d60}"), + (0x10D81, "\u{10d61}"), + (0x10D82, "\u{10d62}"), + (0x10D83, "\u{10d63}"), + (0x10D84, "\u{10d64}"), + (0x10D85, "\u{10d65}"), + (0x118C0, "\u{118a0}"), + (0x118C1, "\u{118a1}"), + (0x118C2, "\u{118a2}"), + (0x118C3, "\u{118a3}"), + (0x118C4, "\u{118a4}"), + (0x118C5, "\u{118a5}"), + (0x118C6, "\u{118a6}"), + (0x118C7, "\u{118a7}"), + (0x118C8, "\u{118a8}"), + (0x118C9, "\u{118a9}"), + (0x118CA, "\u{118aa}"), + (0x118CB, "\u{118ab}"), + (0x118CC, "\u{118ac}"), + (0x118CD, "\u{118ad}"), + (0x118CE, "\u{118ae}"), + (0x118CF, "\u{118af}"), + (0x118D0, "\u{118b0}"), + (0x118D1, "\u{118b1}"), + (0x118D2, "\u{118b2}"), + (0x118D3, "\u{118b3}"), + (0x118D4, "\u{118b4}"), + (0x118D5, "\u{118b5}"), + (0x118D6, "\u{118b6}"), + (0x118D7, "\u{118b7}"), + (0x118D8, "\u{118b8}"), + (0x118D9, "\u{118b9}"), + (0x118DA, "\u{118ba}"), + (0x118DB, "\u{118bb}"), + (0x118DC, "\u{118bc}"), + (0x118DD, "\u{118bd}"), + (0x118DE, "\u{118be}"), + (0x118DF, "\u{118bf}"), + (0x16E60, "\u{16e40}"), + (0x16E61, "\u{16e41}"), + (0x16E62, "\u{16e42}"), + (0x16E63, "\u{16e43}"), + (0x16E64, "\u{16e44}"), + (0x16E65, "\u{16e45}"), + (0x16E66, "\u{16e46}"), + (0x16E67, "\u{16e47}"), + (0x16E68, "\u{16e48}"), + (0x16E69, "\u{16e49}"), + (0x16E6A, "\u{16e4a}"), + (0x16E6B, "\u{16e4b}"), + (0x16E6C, "\u{16e4c}"), + (0x16E6D, "\u{16e4d}"), + (0x16E6E, "\u{16e4e}"), + (0x16E6F, "\u{16e4f}"), + (0x16E70, "\u{16e50}"), + (0x16E71, "\u{16e51}"), + (0x16E72, "\u{16e52}"), + (0x16E73, "\u{16e53}"), + (0x16E74, "\u{16e54}"), + (0x16E75, "\u{16e55}"), + (0x16E76, "\u{16e56}"), + (0x16E77, "\u{16e57}"), + (0x16E78, "\u{16e58}"), + (0x16E79, "\u{16e59}"), + (0x16E7A, "\u{16e5a}"), + (0x16E7B, "\u{16e5b}"), + (0x16E7C, "\u{16e5c}"), + (0x16E7D, "\u{16e5d}"), + (0x16E7E, "\u{16e5e}"), + (0x16E7F, "\u{16e5f}"), + (0x1E922, "\u{1e900}"), + (0x1E923, "\u{1e901}"), + (0x1E924, "\u{1e902}"), + (0x1E925, "\u{1e903}"), + (0x1E926, "\u{1e904}"), + (0x1E927, "\u{1e905}"), + (0x1E928, "\u{1e906}"), + (0x1E929, "\u{1e907}"), + (0x1E92A, "\u{1e908}"), + (0x1E92B, "\u{1e909}"), + (0x1E92C, "\u{1e90a}"), + (0x1E92D, "\u{1e90b}"), + (0x1E92E, "\u{1e90c}"), + (0x1E92F, "\u{1e90d}"), + (0x1E930, "\u{1e90e}"), + (0x1E931, "\u{1e90f}"), + (0x1E932, "\u{1e910}"), + (0x1E933, "\u{1e911}"), + (0x1E934, "\u{1e912}"), + (0x1E935, "\u{1e913}"), + (0x1E936, "\u{1e914}"), + (0x1E937, "\u{1e915}"), + (0x1E938, "\u{1e916}"), + (0x1E939, "\u{1e917}"), + (0x1E93A, "\u{1e918}"), + (0x1E93B, "\u{1e919}"), + (0x1E93C, "\u{1e91a}"), + (0x1E93D, "\u{1e91b}"), + (0x1E93E, "\u{1e91c}"), + (0x1E93F, "\u{1e91d}"), + (0x1E940, "\u{1e91e}"), + (0x1E941, "\u{1e91f}"), + (0x1E942, "\u{1e920}"), + (0x1E943, "\u{1e921}"), +] diff --git a/crates/sqlbuild-python/src/bindings/_helpers/analysis/explicit_references.rs b/crates/sqlbuild-python/src/bindings/_helpers/analysis/explicit_references.rs new file mode 100644 index 0000000000..23790b3674 --- /dev/null +++ b/crates/sqlbuild-python/src/bindings/_helpers/analysis/explicit_references.rs @@ -0,0 +1,59 @@ +//! Compile's explicit-reference checks over plain project facts, run natively. + +use pyo3::prelude::{Bound, PyModule, PyModuleMethods, PyResult, Python}; +use pyo3::{pyfunction, wrap_pyfunction}; +use serde_json::{Value, json}; +use sqlbuild_analysis::explicit_references::errors::ReferenceFailure; +use sqlbuild_analysis::explicit_references::main::check_explicit_references::check_explicit_references; +use sqlbuild_analysis::explicit_references::models::{ReferenceReport, ReferenceRequest}; +use sqlbuild_core::panics::main::native_failure::native_failure; + +use crate::bindings::_helpers::boundary::panics::compiler_error; +use crate::bindings::types::CompilerDetach; + +const EXPLICIT_REFERENCES_CONTEXT: &str = "native explicit-reference checks"; + +/// Python's audit-gate, hook-read and Python-SQL checks: `{report}` or `{raise}` JSON. +#[pyfunction] +fn check_native_explicit_references(py: Python<'_>, request_json: &str) -> PyResult { + let request: ReferenceRequest = serde_json::from_str(request_json).map_err(|error| { + compiler_error(native_failure( + EXPLICIT_REFERENCES_CONTEXT, + &error.to_string(), + )) + })?; + let outcome: Value = match py + .compiler_detach(|| Ok(check_explicit_references(&request))) + .map_err(compiler_error)? + { + Ok(report) => json!({ "report": report_value(&report)? }), + Err(ReferenceFailure::CompileInput(message)) => json!({ "raise": message }), + Err(ReferenceFailure::UnknownDialect(message)) => return Err(compiler_error(message)), + Err(ReferenceFailure::Internal(reason)) => { + return Err(compiler_error(native_failure( + EXPLICIT_REFERENCES_CONTEXT, + &reason, + ))); + } + }; + serde_json::to_string(&outcome).map_err(|error| { + compiler_error(native_failure( + EXPLICIT_REFERENCES_CONTEXT, + &error.to_string(), + )) + }) +} + +fn report_value(report: &ReferenceReport) -> PyResult { + serde_json::to_value(report).map_err(|error| { + compiler_error(native_failure( + EXPLICIT_REFERENCES_CONTEXT, + &error.to_string(), + )) + }) +} + +pub(crate) fn register(module: &Bound<'_, PyModule>) -> PyResult<()> { + module.add_function(wrap_pyfunction!(check_native_explicit_references, module)?)?; + Ok(()) +} diff --git a/crates/sqlbuild-python/src/bindings/_helpers/analysis/mod.rs b/crates/sqlbuild-python/src/bindings/_helpers/analysis/mod.rs index 762d17f3ef..952f5ba328 100644 --- a/crates/sqlbuild-python/src/bindings/_helpers/analysis/mod.rs +++ b/crates/sqlbuild-python/src/bindings/_helpers/analysis/mod.rs @@ -1,7 +1,9 @@ mod catalog; pub(crate) mod conversions; +pub(crate) mod explicit_references; pub(crate) mod normalization; pub(crate) mod normalization_results; mod positions; pub(crate) mod queries; +pub(crate) mod relation_names; pub(crate) mod sql_tests; diff --git a/crates/sqlbuild-python/src/bindings/_helpers/analysis/queries.rs b/crates/sqlbuild-python/src/bindings/_helpers/analysis/queries.rs index c824541f2f..6a7ccfa676 100644 --- a/crates/sqlbuild-python/src/bindings/_helpers/analysis/queries.rs +++ b/crates/sqlbuild-python/src/bindings/_helpers/analysis/queries.rs @@ -71,6 +71,8 @@ fn analyze_project_queries_compact_json(py: Python<'_>, request_json: &str) -> P } pub(crate) fn register(module: &Bound<'_, PyModule>) -> PyResult<()> { + crate::bindings::_helpers::analysis::relation_names::register(module)?; + crate::bindings::_helpers::analysis::explicit_references::register(module)?; module.add_function(wrap_pyfunction!(query_fingerprint, module)?)?; module.add_function(wrap_pyfunction!(schema_validation_json, module)?)?; module.add_function(wrap_pyfunction!(schema_validations_json, module)?)?; diff --git a/crates/sqlbuild-python/src/bindings/_helpers/analysis/relation_names.rs b/crates/sqlbuild-python/src/bindings/_helpers/analysis/relation_names.rs new file mode 100644 index 0000000000..8e33cf14cf --- /dev/null +++ b/crates/sqlbuild-python/src/bindings/_helpers/analysis/relation_names.rs @@ -0,0 +1,55 @@ +//! Relations named in SQL and temporary tables it creates, for hard-coded name checks. + +use pyo3::prelude::{Bound, PyModule, PyModuleMethods, PyResult, Python}; +use pyo3::{PyErr, pyfunction, wrap_pyfunction}; +use sqlbuild_analysis::relation_names::errors::RelationNamesFailure; +use sqlbuild_analysis::relation_names::main::extract_relation_names::extract_relation_names; +use sqlbuild_analysis::relation_names::models::{ExtractedRelations, RelationName}; +use sqlbuild_core::panics::main::native_failure::native_failure; + +use crate::bindings::_helpers::boundary::panics::compiler_error; +use crate::bindings::types::CompilerDetach; + +const RELATION_NAMES_CONTEXT: &str = "native relation name extraction"; + +/// `(name, schema, database)`. +type RelationRow = (String, Option, Option); + +/// Python's `extract_relation_names_impl`: `(relations, temporary names)` or None if unparseable. +#[pyfunction] +#[pyo3(signature = (sql, dialect))] +fn extract_sql_relation_names( + py: Python<'_>, + sql: &str, + dialect: Option<&str>, +) -> PyResult, Vec)>> { + let extracted = py + .compiler_detach(|| Ok(extract_relation_names(sql, dialect))) + .map_err(compiler_error)? + .map_err(relation_names_error)?; + Ok(extracted.map( + |ExtractedRelations { + relations, + temporary, + }| { (relations.into_iter().map(relation_row).collect(), temporary) }, + )) +} + +fn relation_row(relation: RelationName) -> RelationRow { + (relation.name, relation.schema, relation.database) +} + +/// An unknown dialect as the wheel's `ValueError`; anything else as an internal failure. +fn relation_names_error(failure: RelationNamesFailure) -> PyErr { + match failure { + RelationNamesFailure::UnknownDialect(message) => compiler_error(message), + RelationNamesFailure::Internal(reason) => { + compiler_error(native_failure(RELATION_NAMES_CONTEXT, &reason)) + } + } +} + +pub(crate) fn register(module: &Bound<'_, PyModule>) -> PyResult<()> { + module.add_function(wrap_pyfunction!(extract_sql_relation_names, module)?)?; + Ok(()) +} diff --git a/crates/sqlbuild-python/src/bindings/_helpers/analysis/sql_tests.rs b/crates/sqlbuild-python/src/bindings/_helpers/analysis/sql_tests.rs index 2599db889d..179c323596 100644 --- a/crates/sqlbuild-python/src/bindings/_helpers/analysis/sql_tests.rs +++ b/crates/sqlbuild-python/src/bindings/_helpers/analysis/sql_tests.rs @@ -4,10 +4,14 @@ use pyo3::prelude::{Bound, PyModule, PyModuleMethods, PyResult, Python}; use pyo3::{pyfunction, wrap_pyfunction}; use sqlbuild_sqltext::sql_scan::models::LexicalSyntax; -use crate::bindings::_helpers::boundary::panics::value_error; +use sqlbuild_core::panics::main::native_failure::native_failure; + +use crate::bindings::_helpers::boundary::panics::{compiler_error, value_error}; use crate::bindings::_helpers::sqltext::lexical_syntax::LexicalSyntaxInput; use crate::bindings::types::CompilerDetach; +const HELPER_READS_CONTEXT: &str = "native SQL-test helper reads"; + #[pyfunction] fn render_sql_test_comparisons_json(py: Python<'_>, request_json: &str) -> PyResult { py.compiler_detach(|| { @@ -16,24 +20,6 @@ fn render_sql_test_comparisons_json(py: Python<'_>, request_json: &str) -> PyRes .map_err(value_error) } -#[pyfunction] -fn plan_and_render_sql_tests_json(py: Python<'_>, request_json: &str) -> PyResult { - py.compiler_detach(|| { - sqlbuild_analysis::compiler::main::sql_test_planning::plan_and_render_json(request_json) - }) - .map_err(value_error) -} - -#[pyfunction] -fn resolve_sql_test_chains_json(py: Python<'_>, request_json: &str) -> PyResult { - py.compiler_detach(|| { - sqlbuild_analysis::compiler::main::sql_test_chain_resolution::resolve_chains_json( - request_json, - ) - }) - .map_err(value_error) -} - #[pyfunction] fn render_sql_test_difference_sample_json(py: Python<'_>, request_json: &str) -> PyResult { py.compiler_detach(|| { @@ -87,12 +73,27 @@ fn function_type_error( .map_err(value_error) } +/// Python's `_parsed_reads`: the helper keys a CTE body reads, or None if it does not parse. +#[pyfunction] +fn sql_test_helper_reads( + py: Python<'_>, + sql: &str, + keys: Vec, +) -> PyResult>> { + py.compiler_detach(|| { + sqlbuild_analysis::assembly::analysis_session::main::sql_test_helper_reads::sql_test_helper_reads( + sql, &keys, + ) + .map_err(|reason| native_failure(HELPER_READS_CONTEXT, &reason)) + }) + .map_err(compiler_error) +} + pub(crate) fn register(module: &Bound<'_, PyModule>) -> PyResult<()> { + module.add_function(wrap_pyfunction!(sql_test_helper_reads, module)?)?; module.add_function(wrap_pyfunction!(function_type_error, module)?)?; module.add_function(wrap_pyfunction!(extract_sql_scenario_json, module)?)?; module.add_function(wrap_pyfunction!(render_sql_test_comparisons_json, module)?)?; - module.add_function(wrap_pyfunction!(plan_and_render_sql_tests_json, module)?)?; - module.add_function(wrap_pyfunction!(resolve_sql_test_chains_json, module)?)?; module.add_function(wrap_pyfunction!( render_sql_test_difference_sample_json, module diff --git a/crates/sqlbuild-python/src/bindings/_helpers/analysis_session/mod.rs b/crates/sqlbuild-python/src/bindings/_helpers/analysis_session/mod.rs index feba290be6..11eaaf57b5 100644 --- a/crates/sqlbuild-python/src/bindings/_helpers/analysis_session/mod.rs +++ b/crates/sqlbuild-python/src/bindings/_helpers/analysis_session/mod.rs @@ -1,3 +1,5 @@ +pub(crate) mod nullability_rules; pub(crate) mod oracle; +pub(crate) mod query_columns; pub(crate) mod registration; pub(crate) mod session; diff --git a/crates/sqlbuild-python/src/bindings/_helpers/analysis_session/nullability_rules.rs b/crates/sqlbuild-python/src/bindings/_helpers/analysis_session/nullability_rules.rs new file mode 100644 index 0000000000..16562c1969 --- /dev/null +++ b/crates/sqlbuild-python/src/bindings/_helpers/analysis_session/nullability_rules.rs @@ -0,0 +1,57 @@ +//! Project-local adapter nullability rules, run by calling the adapter's own Python rule. + +use std::sync::{Arc, Mutex, PoisonError}; + +use pyo3::prelude::{Py, PyAny, PyAnyMethods, PyDictMethods, PyErr, Python}; +use pyo3::types::{PyDict, PyTuple}; +use sqlbuild_analysis::assembly::analysis_session::models::NullabilityCallback; + +/// The first exception an adapter rule raised, which the session re-raises to Python. +pub(crate) type RuleFailure = Arc>>; + +const NULLABILITIES: [&str; 3] = ["non_null", "nullable", "unknown"]; +const RULE_RAISED: &str = "an adapter nullability rule raised"; + +/// The callback calling `rules[name](tuple(InferredNullability(value) for value in args))`. +pub(crate) fn nullability_callback( + rules: Py, + nullability: Py, + failure: RuleFailure, +) -> NullabilityCallback { + NullabilityCallback(Arc::new(move |name: &str, arguments: &[&'static str]| { + Python::attach(|python| { + let called = || -> Result<&'static str, PyErr> { + let enum_type = nullability.bind(python); + let rule = rules + .bind(python) + .get_item(name)? + .ok_or_else(|| pyo3::exceptions::PyKeyError::new_err(name.to_owned()))?; + let values = arguments + .iter() + .map(|value| enum_type.call1((*value,))) + .collect::, _>>()?; + let result = rule.call1((PyTuple::new(python, values)?,))?; + let value: String = enum_type.call1((result,))?.getattr("value")?.extract()?; + Ok(NULLABILITIES + .into_iter() + .find(|known| *known == value) + .unwrap_or("unknown")) + }; + called().map_err(|error| { + let mut slot = failure.lock().unwrap_or_else(PoisonError::into_inner); + if slot.is_none() { + *slot = Some(error); + } + RULE_RAISED.to_owned() + }) + }) + })) +} + +/// Take the exception an adapter rule raised, if any. +pub(crate) fn raised(failure: &RuleFailure) -> Option { + failure + .lock() + .unwrap_or_else(PoisonError::into_inner) + .take() +} diff --git a/crates/sqlbuild-python/src/bindings/_helpers/analysis_session/query_columns.rs b/crates/sqlbuild-python/src/bindings/_helpers/analysis_session/query_columns.rs new file mode 100644 index 0000000000..abd40f0195 --- /dev/null +++ b/crates/sqlbuild-python/src/bindings/_helpers/analysis_session/query_columns.rs @@ -0,0 +1,151 @@ +//! Python's per-query column analysis outside the session, run natively. + +use pyo3::prelude::{Bound, Py, PyAny, PyModule, PyModuleMethods, PyRef, PyResult, Python}; +use pyo3::types::PyDict; +use pyo3::{PyErr, pyfunction, wrap_pyfunction}; +use sqlbuild_analysis::assembly::analysis_session::errors::QueryColumnsFailure; +use sqlbuild_analysis::assembly::analysis_session::main::projection_facts::projection_facts; +use sqlbuild_analysis::assembly::analysis_session::main::query_columns::query_columns; +use sqlbuild_analysis::assembly::analysis_session::models::{ + ColumnFact, ProjectionFacts, QueryColumns, QueryColumnsInput, QueryColumnsMode, + QueryColumnsRequest, +}; +use sqlbuild_analysis::assembly::analysis_session::types::{Pairs, Shapes}; +use sqlbuild_core::panics::main::native_failure::native_failure; + +use crate::bindings::_helpers::analysis_session::nullability_rules::{ + RuleFailure, nullability_callback, raised, +}; +use crate::bindings::_helpers::boundary::panics::compiler_error; +use crate::bindings::models::ProjectCatalog; +use crate::bindings::types::CompilerDetach; + +const QUERY_COLUMNS_CONTEXT: &str = "native query column analysis"; +const PROJECTION_FACTS_CONTEXT: &str = "native fixture projection facts"; + +/// `(sql, placeholders, analysis names, lineage references, recover CTE facts, mode)`. +type QueryRow = ( + String, + Pairs, + Vec, + Vec<(String, String, String)>, + bool, + String, +); +/// `(dialect, return types, rules, types, nullability, queries, normalization dialect)`. +type RequestRow = (String, Pairs, Pairs, Shapes, Shapes, Vec, String); +/// `([(name, type)], NULL literal names, quoted names)`. +type ProjectionFactsRow = (Vec<(String, String)>, Vec, Vec); +/// `(succeeded, [(name, type, nullability)] or None, has star)`. +type ColumnsRow = (bool, Option, String)>>, bool); + +/// Each query's columns, as Python's analysis outside the session inferred them. +#[pyfunction] +#[pyo3(signature = (catalog, request, adapter_rules=None))] +fn infer_query_columns( + py: Python<'_>, + catalog: Option>, + request: RequestRow, + adapter_rules: Option<(Py, Py)>, +) -> PyResult> { + let ( + dialect, + function_return_types, + nullability_rules, + types, + nullability, + queries, + normalization_dialect, + ) = request; + let queries: Vec = queries + .into_iter() + .map(query_input) + .collect::>() + .map_err(|reason| compiler_error(native_failure(QUERY_COLUMNS_CONTEXT, &reason)))?; + let rule_failure: RuleFailure = RuleFailure::default(); + let request = QueryColumnsRequest { + dialect, + normalization_dialect, + function_return_types, + nullability_rules: Some(nullability_rules), + nullability_callback: adapter_rules.map(|(rules, nullability)| { + nullability_callback(rules, nullability, rule_failure.clone()) + }), + types, + nullability, + queries, + }; + let catalog = catalog.as_ref().map(|catalog| &catalog.inner); + let columns = py.compiler_detach(|| Ok(query_columns(catalog, &request))); + if let Some(error) = raised(&rule_failure) { + return Err(error); + } + Ok(columns + .map_err(|reason| compiler_error(native_failure(QUERY_COLUMNS_CONTEXT, &reason)))? + .map_err(query_columns_error)? + .into_iter() + .map(columns_row) + .collect()) +} + +/// A normalization rejection as Python's `ValueError`; anything else as an internal failure. +fn query_columns_error(failure: QueryColumnsFailure) -> PyErr { + match failure { + QueryColumnsFailure::Normalization(message) => compiler_error(message), + QueryColumnsFailure::Internal(reason) => { + compiler_error(native_failure(QUERY_COLUMNS_CONTEXT, &reason)) + } + } +} + +fn query_input(row: QueryRow) -> Result { + let (sql, placeholders, analysis_names, lineage_references, recover_cte_facts, mode) = row; + let mode: QueryColumnsMode = match mode.as_str() { + "batch" => QueryColumnsMode::Batch, + "reanalysis" => QueryColumnsMode::Reanalysis, + "parse" => QueryColumnsMode::Parse, + "legacy" => QueryColumnsMode::Legacy, + _ => return Err("an unknown query column analysis mode".to_owned()), + }; + Ok(QueryColumnsInput { + sql, + placeholders, + analysis_names, + lineage_references, + recover_cte_facts, + mode, + }) +} + +fn columns_row(columns: QueryColumns) -> ColumnsRow { + ( + columns.succeeded, + columns + .columns + .map(|columns| columns.into_iter().map(column_row).collect()), + columns.has_star, + ) +} + +/// Python's `_simple_projection_facts`: `(types, NULL literal names, quoted names)`, casefolded. +#[pyfunction] +fn fixture_projection_facts( + py: Python<'_>, + sql: &str, + dialect: Option<&str>, +) -> PyResult { + let facts: ProjectionFacts = py + .compiler_detach(|| projection_facts(sql, dialect)) + .map_err(|reason| compiler_error(native_failure(PROJECTION_FACTS_CONTEXT, &reason)))?; + Ok((facts.types, facts.null_literal_names, facts.quoted_names)) +} + +pub(crate) fn register(module: &Bound<'_, PyModule>) -> PyResult<()> { + module.add_function(wrap_pyfunction!(infer_query_columns, module)?)?; + module.add_function(wrap_pyfunction!(fixture_projection_facts, module)?)?; + Ok(()) +} + +fn column_row(column: ColumnFact) -> (String, Option, String) { + (column.name, column.data_type, column.nullability) +} diff --git a/crates/sqlbuild-python/src/bindings/_helpers/analysis_session/registration.rs b/crates/sqlbuild-python/src/bindings/_helpers/analysis_session/registration.rs index 426d0f43eb..6e72b49d20 100644 --- a/crates/sqlbuild-python/src/bindings/_helpers/analysis_session/registration.rs +++ b/crates/sqlbuild-python/src/bindings/_helpers/analysis_session/registration.rs @@ -2,9 +2,10 @@ use pyo3::prelude::{Bound, PyModule, PyResult}; -use crate::bindings::_helpers::analysis_session::{oracle, session}; +use crate::bindings::_helpers::analysis_session::{oracle, query_columns, session}; pub(crate) fn register(module: &Bound<'_, PyModule>) -> PyResult<()> { session::register(module)?; + query_columns::register(module)?; oracle::register(module) } diff --git a/crates/sqlbuild-python/src/bindings/_helpers/analysis_session/session.rs b/crates/sqlbuild-python/src/bindings/_helpers/analysis_session/session.rs index 0489bfe983..65a1324edc 100644 --- a/crates/sqlbuild-python/src/bindings/_helpers/analysis_session/session.rs +++ b/crates/sqlbuild-python/src/bindings/_helpers/analysis_session/session.rs @@ -1,6 +1,7 @@ //! The native model analysis session and expression-source shapes for the preview engine. -use pyo3::prelude::{Bound, PyModule, PyModuleMethods, PyRef, PyResult, Python}; +use pyo3::prelude::{Bound, Py, PyAny, PyErr, PyModule, PyModuleMethods, PyRef, PyResult, Python}; +use pyo3::types::PyDict; use pyo3::{pyclass, pyfunction, pymethods, wrap_pyfunction}; use sqlbuild_analysis::assembly::analysis_session::main::attach_analysis_cache::attach_analysis_cache; use sqlbuild_analysis::assembly::analysis_session::main::expression_shapes::expression_shapes; @@ -8,24 +9,29 @@ use sqlbuild_analysis::assembly::analysis_session::main::finish_analysis_session use sqlbuild_analysis::assembly::analysis_session::main::finished_fact_models::finished_fact_models; use sqlbuild_analysis::assembly::analysis_session::main::prove_dynamic_contracts::prove_dynamic_contracts; use sqlbuild_analysis::assembly::analysis_session::main::prove_finished_dynamic_contracts::prove_finished_dynamic_contracts; -use sqlbuild_analysis::assembly::analysis_session::main::provide_deferred_analyses::provide_deferred_analyses; use sqlbuild_analysis::assembly::analysis_session::main::run_analysis_session::run_analysis_session; use sqlbuild_analysis::assembly::analysis_session::main::session_sharing::session_sharing; use sqlbuild_analysis::assembly::analysis_session::main::start_analysis_session::start_analysis_session; use sqlbuild_analysis::assembly::analysis_session::main::take_analysis_cache::take_analysis_cache; use sqlbuild_analysis::assembly::analysis_session::models::{ - AnalysisCacheStats, AnalysisSession, ColumnFact, Deferral, DeferredAnalysis, DynamicFamily, - ExpressionShape, ExpressionShapeRequest, FinishedSession, LineageFacts, LineageRow, - ModelOutcome, ModelReference, ModelRequest, PivotBatchRequest, PivotModel, PivotOutcome, - PivotTables, SessionOutcome, SessionRequest, SessionStep, + AnalysisCacheStats, AnalysisSession, ColumnFact, DynamicFamily, ExpressionShape, + ExpressionShapeRequest, FinishedSession, LineageFacts, LineageRow, ModelOutcome, + ModelReference, ModelRequest, PivotBatchRequest, PivotModel, PivotOutcome, PivotTables, + SessionOutcome, SessionRequest, SessionStep, }; use sqlbuild_analysis::assembly::analysis_session::types::{Pairs, Shapes}; use sqlbuild_analysis::semantic_validation::types::DiagnosticRow; use sqlbuild_cache::store::models::NativeStore; +use sqlbuild_core::constants::PANIC_MESSAGE; use sqlbuild_core::panics::main::catch_compiler_panic::catch_compiler_panic; +use sqlbuild_core::panics::main::is_compiler_panic::is_compiler_panic; +use sqlbuild_core::panics::main::native_failure::native_failure; use std::path::PathBuf; +use crate::bindings::_helpers::analysis_session::nullability_rules::{ + RuleFailure, nullability_callback, raised, +}; use crate::bindings::_helpers::boundary::panics::compiler_error; use crate::bindings::_helpers::cache::native_store::{open_store, save_store}; use crate::bindings::models::ProjectCatalog; @@ -65,27 +71,8 @@ type RequestRow = ( Vec<(String, Vec)>, Vec, ); -/// `(kind, model, cleaned_sql, schemas, binding diagnostics, lineage)`. -type DeferralRow = ( - &'static str, - usize, - Option, - Shapes, - Vec, - Option>, -); -/// `(publications, deferrals, failures)`. -type StepRow = (Shapes, Vec, Vec); -/// `(model, succeeded, columns, has_star, star_resolved, binding diagnostics, validated)`. -type DeferredRow = ( - usize, - bool, - Option>, - bool, - bool, - Vec, - bool, -); +/// `(publications, failures)`. +type StepRow = (Shapes, Vec); /// One model's analysis, lineage source and cleaned SQL. type OutcomeRow = ( bool, @@ -125,17 +112,20 @@ type CacheStatsRow = (usize, usize, usize, Option); /// `(models, catalog schema additions, analysis-shape names, dynamic pivot proofs)`. type FinishRow = (Vec, Shapes, Vec, Vec); -/// One compile's native model analysis; any failure hands the whole analysis back to Python. +/// One compile's native model analysis; an internal failure raises `NativeCompilerError`. #[pyclass(module = "sqlbuild._native")] pub(crate) struct NativeModelAnalysisSession { inner: Option, finished: Option, - failure: Option, sharing: (usize, usize), cache_path: Option, cache_stats: Option, + rule_failure: RuleFailure, } +/// What an internal native failure of the session names. +const SESSION_CONTEXT: &str = "native model analysis"; +const SHAPES_CONTEXT: &str = "native expression-source shapes"; /// The native store kind holding finished model analyses. const MODEL_ANALYSIS_STORE_KIND: &str = "model-analyses"; @@ -145,17 +135,20 @@ impl NativeModelAnalysisSession { self.finished.as_ref() } - /// Keep `result`'s value, or end the session and keep its failure for Python's debug log. - fn kept(&mut self, result: Result) -> Option { - match result { - Ok(value) => Some(value), - Err(error) => { - self.inner = None; - self.failure = Some(error); - None - } - } + /// The running session, or `NativeCompilerError` once it has failed or finished. + fn running(&mut self) -> PyResult { + self.inner + .take() + .ok_or_else(|| internal_error("the session is not running")) + } +} + +/// An internal native failure of the session as `NativeCompilerError`. +fn internal_error(reason: &str) -> PyErr { + if is_compiler_panic(reason) && reason != PANIC_MESSAGE { + return compiler_error(reason); } + compiler_error(native_failure(SESSION_CONTEXT, reason)) } #[pymethods] @@ -169,37 +162,28 @@ impl NativeModelAnalysisSession { .unwrap_or_default() } - /// Advance; None means Python must analyse every model, no deferrals means done. - fn run(&mut self, py: Python<'_>) -> Option { - let mut session: AnalysisSession = self.inner.take()?; + /// Analyse every model. + fn run(&mut self, py: Python<'_>) -> PyResult { + let mut session: AnalysisSession = self.running()?; let result: Result<(AnalysisSession, SessionStep), String> = py.compiler_detach(move || { run_analysis_session(&mut session).map(|step| (session, step)) }); - let (session, step) = self.kept(result)?; + if let Some(error) = raised(&self.rule_failure) { + return Err(error); + } + let (session, step) = result.map_err(|reason| internal_error(&reason))?; self.sharing = session_sharing(&session); self.inner = Some(session); - Some(step_row(step)) + Ok(step_row(step)) } - /// Answer the last step's deferrals; False means Python must analyse every model. - fn provide(&mut self, results: Vec) -> bool { - let Some(mut session) = self.inner.take() else { - return false; - }; - let answers: Vec = results.into_iter().map(deferred_analysis).collect(); - let provided: Result<(), String> = - catch_compiler_panic(|| provide_deferred_analyses(&mut session, answers)); - self.inner = Some(session); - self.kept(provided).is_some() - } - - /// Every model's outcome once done, or None for Python; saves the cache best-effort. - fn finish(&mut self, py: Python<'_>) -> Option { - let mut session: AnalysisSession = self.inner.take()?; + /// Every model's outcome; saves the cache best-effort. + fn finish(&mut self, py: Python<'_>) -> PyResult { + let mut session: AnalysisSession = self.running()?; let cache: Option<(NativeStore, AnalysisCacheStats)> = take_analysis_cache(&mut session); - let outcome = catch_compiler_panic(|| finish_analysis_session(session)); - let (outcome, finished) = self.kept(outcome)?; + let (outcome, finished) = catch_compiler_panic(|| finish_analysis_session(session)) + .map_err(|reason| internal_error(&reason))?; self.finished = Some(finished); if let (Some((store, stats)), Some(path)) = (cache, self.cache_path.as_ref()) { let saved: Option = save_store(py, &store, path, &[]) @@ -207,7 +191,7 @@ impl NativeModelAnalysisSession { .map(|error| error.to_string()); self.cache_stats = Some((stats.hits, stats.misses, stats.stored, saved)); } - Some(finish_row(outcome)) + Ok(finish_row(outcome)) } /// The analysis cache's `(hits, misses, stored, failure)`; None without a cache. @@ -216,24 +200,21 @@ impl NativeModelAnalysisSession { self.cache_stats.clone() } - /// Each model's dynamic pivot proof from the finished session's tables, or None for Python. + /// Each model's dynamic pivot proof from the finished session's tables. fn prove_dynamic_contracts( &self, py: Python<'_>, models: Vec, - ) -> Option> { - let session: &FinishedSession = self.finished.as_ref()?; + ) -> PyResult> { + let session: &FinishedSession = self + .finished + .as_ref() + .ok_or_else(|| internal_error("the session has not finished"))?; let models: Vec = models.into_iter().map(pivot_model).collect(); - match py.compiler_detach(|| prove_finished_dynamic_contracts(session, &models)) { - Ok(outcomes) => Some(outcomes.into_iter().map(contract_row).collect()), - Err(_) => None, - } - } - - /// Why the session handed the analysis back to Python, when it did. - #[getter] - fn failure(&self) -> Option { - self.failure.clone() + let outcomes: Vec = py + .compiler_detach(|| prove_finished_dynamic_contracts(session, &models)) + .map_err(|reason| internal_error(&reason))?; + Ok(outcomes.into_iter().map(contract_row).collect()) } /// `(shared members, shared members re-analysed alone)` as of the last step. @@ -243,23 +224,24 @@ impl NativeModelAnalysisSession { } } -/// Start a session on `catalog`, or None where Python must analyse. +/// Start a session on `catalog`. #[pyfunction] -#[pyo3(signature = (catalog, request, cache=None))] +#[pyo3(signature = (catalog, request, cache=None, adapter_rules=None))] fn start_model_analysis_session( - py: Python<'_>, catalog: PyRef<'_, ProjectCatalog>, request: RequestRow, cache: Option<(PathBuf, String)>, -) -> PyResult> { - let request: SessionRequest = session_request(request); + adapter_rules: Option<(Py, Py)>, +) -> PyResult { + let py: Python<'_> = catalog.py(); + let mut request: SessionRequest = session_request(request); + let rule_failure: RuleFailure = RuleFailure::default(); + request.nullability_callback = adapter_rules + .map(|(rules, nullability)| nullability_callback(rules, nullability, rule_failure.clone())); let catalog = &catalog.inner; - let session: Option = py - .compiler_detach(|| Ok(start_analysis_session(request, catalog))) - .map_err(compiler_error)?; - let Some(mut session) = session else { - return Ok(None); - }; + let mut session: AnalysisSession = py + .compiler_detach(|| start_analysis_session(request, catalog)) + .map_err(|reason| internal_error(&reason))?; let mut cache_path: Option = None; let mut cache_stats: Option = None; if let Some((path, environment)) = cache { @@ -271,43 +253,51 @@ fn start_model_analysis_session( Err(error) => cache_stats = Some((0, 0, 0, Some(error.to_string()))), } } - Ok(Some(NativeModelAnalysisSession { + Ok(NativeModelAnalysisSession { inner: Some(session), finished: None, - failure: None, sharing: (0, 0), cache_path, cache_stats, - })) + rule_failure, + }) } -/// Each expression's shape, with `False` where Python must infer it. +/// Each expression's shape, `None` where it has none; adapter rules run as in the session. #[pyfunction] +#[pyo3(signature = (catalog, request, adapter_rules=None))] fn infer_expression_source_shapes( py: Python<'_>, catalog: PyRef<'_, ProjectCatalog>, - request: (String, bool, Pairs, Vec), -) -> (Vec<(bool, Option)>, Option) { - let (dialect, case_sensitive_shapes, function_return_types, expressions) = request; + request: (String, bool, Pairs, Option, Vec), + adapter_rules: Option<(Py, Py)>, +) -> PyResult>> { + let (dialect, case_sensitive_shapes, function_return_types, nullability_rules, expressions) = + request; + let rule_failure: RuleFailure = RuleFailure::default(); let request = ExpressionShapeRequest { dialect, case_sensitive_shapes, function_return_types, + nullability_rules, + nullability_callback: adapter_rules.map(|(rules, nullability)| { + nullability_callback(rules, nullability, rule_failure.clone()) + }), expressions, }; let catalog = &catalog.inner; - match py.compiler_detach(|| expression_shapes(catalog, &request)) { - Ok(shapes) => (shapes.into_iter().map(expression_shape_row).collect(), None), - Err(error) => (Vec::new(), Some(error)), - } -} - -fn expression_shape_row(shape: ExpressionShape) -> (bool, Option) { - match shape { - ExpressionShape::Inferred(shape) => (true, Some(shape)), - ExpressionShape::Absent => (true, None), - ExpressionShape::Deferred => (false, None), + let shapes = py.compiler_detach(|| expression_shapes(catalog, &request)); + if let Some(error) = raised(&rule_failure) { + return Err(error); } + Ok(shapes + .map_err(|reason| compiler_error(native_failure(SHAPES_CONTEXT, &reason)))? + .into_iter() + .map(|shape| match shape { + ExpressionShape::Inferred(pairs) => Some(pairs), + ExpressionShape::Absent => None, + }) + .collect()) } fn session_request(request: RequestRow) -> SessionRequest { @@ -329,6 +319,7 @@ fn session_request(request: RequestRow) -> SessionRequest { case_sensitive_shapes, function_return_types, nullability_rules, + nullability_callback: None, rich_type_inference, column_types, column_nullability, @@ -375,56 +366,7 @@ fn model_request(row: ModelRow) -> ModelRequest { } fn step_row(step: SessionStep) -> StepRow { - ( - step.publications, - step.deferrals.into_iter().map(deferral_row).collect(), - step.failures, - ) -} - -fn deferral_row(deferral: Deferral) -> DeferralRow { - let kind: &'static str = deferral.kind(); - match deferral { - Deferral::Analysis { - model, - cleaned_sql, - binding_schema, - binding_diagnostics, - lineage, - } => ( - kind, - model, - Some(cleaned_sql), - binding_schema, - binding_diagnostics, - lineage.map(lineage_items), - ), - Deferral::Enrichment { - model, - input_schemas, - } => (kind, model, None, input_schemas, Vec::new(), None), - } -} - -fn deferred_analysis(row: DeferredRow) -> DeferredAnalysis { - let (model, analysis_succeeded, columns, has_star, star_resolved, diagnostics, validated) = row; - DeferredAnalysis { - model, - analysis_succeeded, - columns: columns.map(|columns| columns.into_iter().map(column_fact).collect()), - has_star, - star_resolved, - binding_diagnostics: diagnostics, - binding_validated: validated, - } -} - -fn column_fact((name, data_type, nullability): ColumnRow) -> ColumnFact { - ColumnFact { - name, - data_type, - nullability, - } + (step.publications, step.failures) } fn column_row(column: ColumnFact) -> ColumnRow { @@ -478,7 +420,6 @@ fn dynamic_family(row: FamilyRow) -> DynamicFamily { fn contract_row(outcome: PivotOutcome) -> ContractRow { match outcome { PivotOutcome::Absent => ("absent", None), - PivotOutcome::Deferred => ("deferred", None), PivotOutcome::Proof(proof) => ( "proof", Some(( @@ -497,8 +438,6 @@ fn outcome_row(outcome: ModelOutcome) -> OutcomeRow { let analysis = outcome.analysis; let (source, lineage) = match analysis.lineage { LineageFacts::Native(rows) => ("native", lineage_items(rows)), - LineageFacts::PythonAnalysis => ("analysis", Vec::new()), - LineageFacts::PythonEnrichment => ("enrichment", Vec::new()), LineageFacts::NativeFacts(rows) => ("facts", lineage_items(rows)), }; ( @@ -516,12 +455,12 @@ fn outcome_row(outcome: ModelOutcome) -> OutcomeRow { ) } -/// Each model's dynamic pivot proof outside any session, or None for Python's proofs. +/// Each model's dynamic pivot proof outside any session. #[pyfunction] fn prove_dynamic_column_contracts( py: Python<'_>, request: PivotRequestRow, -) -> Option> { +) -> PyResult> { let (dialect, column_types, authoritative_types, column_nullability, by_table, models) = request; let request = PivotBatchRequest { @@ -534,10 +473,10 @@ fn prove_dynamic_column_contracts( }, models: models.into_iter().map(pivot_model).collect(), }; - match py.compiler_detach(|| prove_dynamic_contracts(&request)) { - Ok(outcomes) => Some(outcomes.into_iter().map(contract_row).collect()), - Err(_) => None, - } + let outcomes: Vec = py + .compiler_detach(|| prove_dynamic_contracts(&request)) + .map_err(|reason| internal_error(&reason))?; + Ok(outcomes.into_iter().map(contract_row).collect()) } fn pivot_model(row: PivotModelRow) -> PivotModel { diff --git a/crates/sqlbuild-python/src/bindings/_helpers/boundary/mod.rs b/crates/sqlbuild-python/src/bindings/_helpers/boundary/mod.rs index 0a21932dc9..8069dd72e2 100644 --- a/crates/sqlbuild-python/src/bindings/_helpers/boundary/mod.rs +++ b/crates/sqlbuild-python/src/bindings/_helpers/boundary/mod.rs @@ -2,3 +2,4 @@ mod allocator; pub(crate) mod config_values; pub(crate) mod oracles; pub(crate) mod panics; +pub(crate) mod python_runtime; diff --git a/crates/sqlbuild-python/src/bindings/_helpers/boundary/python_runtime.rs b/crates/sqlbuild-python/src/bindings/_helpers/boundary/python_runtime.rs new file mode 100644 index 0000000000..313979971b --- /dev/null +++ b/crates/sqlbuild-python/src/bindings/_helpers/boundary/python_runtime.rs @@ -0,0 +1,22 @@ +//! Record the running Python's string semantics for native text helpers. + +use pyo3::prelude::{PyAnyMethods, PyResult, Python}; +use sqlbuild_core::text::main::python_text::python_text; +use sqlbuild_core::text::main::set_active_python_text::set_active_python_text; + +/// Select the running Python's `str` semantics; an unsupported Python fails at discovery instead. +pub(crate) fn record_python_text(python: Python<'_>) -> PyResult<()> { + let version: (u8, u8) = python + .import("sys")? + .getattr("version_info")? + .extract::<(u8, u8, u8, String, u8)>() + .map(|(major, minor, ..)| (major, minor))?; + let unicode_version: String = python + .import("unicodedata")? + .getattr("unidata_version")? + .extract()?; + if let Some(text) = python_text(version, &unicode_version) { + set_active_python_text(text); + } + Ok(()) +} diff --git a/crates/sqlbuild-python/src/bindings/_helpers/contracts/model_contracts.rs b/crates/sqlbuild-python/src/bindings/_helpers/contracts/model_contracts.rs index ba39f3fa24..7f41ace49c 100644 --- a/crates/sqlbuild-python/src/bindings/_helpers/contracts/model_contracts.rs +++ b/crates/sqlbuild-python/src/bindings/_helpers/contracts/model_contracts.rs @@ -5,12 +5,15 @@ use pyo3::{pyfunction, wrap_pyfunction}; use sqlbuild_analysis::contracts::main::evaluate_model_contracts::evaluate_model_contracts; use sqlbuild_analysis::contracts::main::promotion_conflicts::promotion_conflicts; use sqlbuild_analysis::contracts::models::{ - ContractDeferral, ContractDiagnostic, ContractModel, ContractOutcome, ContractRequest, - ContractSchema, ContractSeverity, DeclaredColumn, DeclaredColumnFamily, DynamicContractProof, - InferredOutputColumn, PromotionConflict, PromotionModel, PromotionRequest, + ContractDiagnostic, ContractModel, ContractRequest, ContractSchema, ContractSeverity, + DeclaredColumn, DeclaredColumnFamily, DynamicContractProof, InferredOutputColumn, + PromotionConflict, PromotionModel, PromotionRequest, }; +use sqlbuild_analysis::type_system::errors::TypeNormalizationError; + use crate::bindings::_helpers::boundary::panics::compiler_error; +use crate::bindings::_helpers::type_system::normalization::normalization_error; use crate::bindings::types::CompilerDetach; /// `(name, type, not_null, declared_in_named_schema)`. @@ -40,27 +43,29 @@ type DiagnosticRow = ( Option<(String, String)>, String, ); -/// `(deferral_kind, diagnostics)`. -type OutcomeRow = (Option<&'static str>, Vec); /// `(name, contract, materialized, incremental_mode)`. type PromotionModelRow = (String, Option, Option, Option); -/// Evaluate every model's column contract; deferred models carry their deferral kind. +/// Evaluate every model's column contract, raising Python's type normalization error. #[pyfunction] fn evaluate_native_model_contracts( py: Python<'_>, request: (String, bool, Vec), -) -> PyResult> { +) -> PyResult>> { let (dialect, implicit_column_contracts, models) = request; let request = ContractRequest { dialect, implicit_column_contracts, models: models.into_iter().map(contract_model).collect(), }; - let outcomes: Vec = py + let outcomes: Result>, TypeNormalizationError> = py .compiler_detach(|| Ok(evaluate_model_contracts(&request))) .map_err(compiler_error)?; - Ok(outcomes.into_iter().map(outcome_row).collect()) + Ok(outcomes + .map_err(|error| normalization_error(py, &error))? + .into_iter() + .map(|diagnostics| diagnostics.into_iter().map(diagnostic_row).collect()) + .collect()) } /// The K011 conflicts of enforced contracts under immediate table promotion. @@ -160,14 +165,6 @@ fn contract_schema( } } -fn outcome_row(outcome: ContractOutcome) -> OutcomeRow { - let (deferral, diagnostics) = outcome.into_parts(); - ( - deferral.map(ContractDeferral::as_str), - diagnostics.into_iter().map(diagnostic_row).collect(), - ) -} - fn diagnostic_row(diagnostic: ContractDiagnostic) -> DiagnosticRow { let (declared_index, output_column) = diagnostic.location.into_parts(); ( diff --git a/crates/sqlbuild-python/src/bindings/_helpers/lineage/fast_lineage.rs b/crates/sqlbuild-python/src/bindings/_helpers/lineage/fast_lineage.rs index 7d20c1eba4..1bea7093f1 100644 --- a/crates/sqlbuild-python/src/bindings/_helpers/lineage/fast_lineage.rs +++ b/crates/sqlbuild-python/src/bindings/_helpers/lineage/fast_lineage.rs @@ -25,11 +25,11 @@ type LineageRequestInput = ( /// `(status, columns, has_star, detail)`; see `FastLineageOutcome::into_parts`. type OutcomeRow = (&'static str, Vec, bool, Option); -/// Build fast lineage for the requested models on `catalog`'s analysis pool. +/// Build fast lineage for the requested models on `catalog`'s analysis pool, if any. #[pyfunction] fn build_fast_column_lineage( py: Python<'_>, - catalog: PyRef<'_, ProjectCatalog>, + catalog: Option>, request: LineageRequestInput, ) -> PyResult> { let (dialect, schema, models) = request; @@ -43,7 +43,8 @@ fn build_fast_column_lineage( schema, models, }; - let catalog: &validation::ProjectCatalog = &catalog.inner; + let catalog: Option<&validation::ProjectCatalog> = + catalog.as_ref().map(|catalog| &catalog.inner); let outcomes: Vec = py .compiler_detach(|| build_fast_lineage(&request, catalog)) .map_err(compiler_error)?; diff --git a/crates/sqlbuild-python/src/bindings/_helpers/project_assembly/resources.rs b/crates/sqlbuild-python/src/bindings/_helpers/project_assembly/resources.rs index 48d24695f1..9e1646f00c 100644 --- a/crates/sqlbuild-python/src/bindings/_helpers/project_assembly/resources.rs +++ b/crates/sqlbuild-python/src/bindings/_helpers/project_assembly/resources.rs @@ -1,22 +1,44 @@ //! Python's resource assembly facts for one project, computed natively for the preview engine. +use std::collections::HashMap; + +use pyo3::exceptions::PyValueError; use pyo3::prelude::{Bound, PyModule, PyModuleMethods, PyResult, Python}; -use pyo3::{pyfunction, wrap_pyfunction}; +use pyo3::types::{PyString, PyStringMethods}; +use pyo3::{PyErr, pyfunction, wrap_pyfunction}; use sqlbuild_analysis::assembly::analysis_session::types::Pairs; +use sqlbuild_analysis::assembly::project::errors::AssemblyError; use sqlbuild_analysis::assembly::project::main::assemble_project_resources::assemble_project_resources; use sqlbuild_analysis::assembly::project::main::check_sql_syntax::check_sql_syntax; +use sqlbuild_analysis::assembly::project::main::sql_syntax_error::sql_syntax_error as check_syntax_error; use sqlbuild_analysis::assembly::project::models::{ - AuditFacts, InputRead, ModelFacts, Namespace, ProjectRequest, ProjectResources, Reference, - SeedDefaults, SeedFacts, SourceFacts, SyntaxCheck, TargetNamespace, Variable, + AuditFacts, FunctionFacts, InputRead, ModelFacts, Namespace, OpaqueRender, OpaqueVariable, + ProjectRequest, ProjectResources, Reference, ResourceFailure, ResourceSlot, SeedDefaults, + SeedFacts, SourceFacts, SyntaxCheck, SyntaxFailure, SyntaxMode, TargetNamespace, Variable, }; use sqlbuild_analysis::assembly::project::types::ObjectKey; +use sqlbuild_core::panics::main::native_failure::native_failure; use sqlbuild_model_config::templates::models::Scalar; +use crate::bindings::_helpers::boundary::panics::compiler_error; use crate::bindings::types::CompilerDetach; +const PROJECT_ASSEMBLY_CONTEXT: &str = "native project assembly"; +const SYNTAX_CHECK_CONTEXT: &str = "native SQL syntax check"; + const TEXT_VARIABLE: &str = "text"; const BOOLEAN_VARIABLE: &str = "bool"; const NONE_VARIABLE: &str = "none"; +const OPAQUE_VARIABLE: &str = "opaque"; +const RENDERED_TEXT: &str = "text"; +const RENDER_REJECTED: &str = "rejected"; +const RENDER_RAISES: &str = "raises"; +const SOURCE_SLOT: &str = "source"; +const SEED_SLOT: &str = "seed"; +const AUDIT_SLOT: &str = "audit"; +const COMPILE_INPUT_ERROR: &str = "compile_input"; +const VALUE_ERROR: &str = "value"; +const HELD_ERROR: &str = "held"; const TRUE_TEXT: &str = "1"; const ENVIRONMENT_READ: &str = "env"; const CONTEXT_READ: &str = "ctx"; @@ -32,14 +54,31 @@ type DefaultsRow = ( Option, Option, ); -/// `(name, kind, text)`; kind `text` (also exact ints), `bool`, `none` or anything else. -type VariableRow = (String, String, String); -/// `(references, [(sql, placeholders)])`. -type ModelRow = (Vec, Vec<(String, Pairs)>); +/// `(name, kind, text, render)`: kind `text`, `bool`, `none` or `opaque` with a render pair. +type VariableRow = (String, String, String, Option<(String, String)>); +/// `(resource list, index, error class, message, help, held exception index)`. +type FailureRow = ( + &'static str, + usize, + &'static str, + String, + Option, + Option, +); +/// `(name, directory, tags, references, [(sql, placeholders)])`. +type ModelRow = ( + String, + String, + Vec, + Vec, + Vec<(String, Pairs)>, +); /// `(name, managed, database, schema)`. type SourceRow = (String, bool, Option, Option); -/// `(name, database, schema)`. -type SeedRow = (String, Option, Option); +/// `(name, tags, database, schema)`. +type SeedRow = (String, Vec, Option, Option); +/// `(kind, name, tags, references)`. +type FunctionRow = (String, String, Vec, Vec); /// `(references, attached (kind, name))`. type AuditRow = (Vec, Option<(String, String)>); /// The dialect, target, defaults, variables, environment and resources one project assembles. @@ -52,7 +91,7 @@ type RequestRow = ( Vec, Vec, Vec, - Vec>, + Vec, Vec, ); /// `(database, schema, logical database, logical schema)`. @@ -70,39 +109,74 @@ type ResourcesRow = ( Vec>, Vec>, Vec<(&'static str, String)>, + Vec, + Option, ); -/// The project's resource facts, or None with the reason Python must assemble it. +/// The project's resource facts up to the resource Python's assembly raises at. #[pyfunction] -fn assemble_project_resource_facts( - py: Python<'_>, - request: RequestRow, -) -> (Option, Option) { - let request: ProjectRequest = project_request(request); - match py.compiler_detach(|| assemble_project_resources(&request)) { - Ok(resources) => (Some(resources_row(resources)), None), - Err(reason) => (None, Some(reason)), +fn assemble_project_resource_facts(py: Python<'_>, request: RequestRow) -> PyResult { + let request: ProjectRequest = project_request(request)?; + let resources: ProjectResources = py + .compiler_detach(|| assemble_project_resources(&request)) + .map_err(|reason| compiler_error(native_failure(PROJECT_ASSEMBLY_CONTEXT, &reason)))?; + resources_row(resources) +} + +/// Python's syntax error message for one SQL string, None where it parses. +#[pyfunction] +#[pyo3(signature = (sql, placeholders, dialect, parse_one=false))] +fn sql_syntax_error( + sql: &Bound<'_, PyString>, + placeholders: Option>, + dialect: Option, + parse_one: bool, +) -> PyResult> { + let py: Python<'_> = sql.py(); + let check = SyntaxCheck { + sql: sql.to_str()?.to_owned(), + placeholders: placeholders.unwrap_or_default().into_iter().collect(), + }; + let dialect: String = dialect + .filter(|dialect| !dialect.is_empty()) + .unwrap_or_else(|| "generic".to_owned()); + let mode = if parse_one { + SyntaxMode::Parse + } else { + SyntaxMode::Validate + }; + py.compiler_detach(|| Ok(check_syntax_error(&check, &dialect, mode))) + .map_err(compiler_error)? + .map_err(syntax_value_error) +} + +/// The `ValueError` Python's syntax validation raises before parsing. +fn syntax_value_error(failure: SyntaxFailure) -> PyErr { + match failure { + SyntaxFailure::Normalization(message) => PyValueError::new_err(message), + SyntaxFailure::UnknownDialect(name) => { + PyValueError::new_err(format!("Unknown dialect: {name}")) + } } } -/// Whether every `(sql, placeholders)` parses, or None with the reason Python must check it. +/// Whether every `(sql, placeholders)` parses, raising the `ValueError` Python's validation raises. #[pyfunction] fn check_native_sql_syntax( py: Python<'_>, request: (String, Vec<(String, Pairs)>), -) -> (Option, Option) { +) -> PyResult { let (dialect, rows) = request; let checks: Vec = rows .into_iter() .map(|(sql, placeholders)| SyntaxCheck { sql, placeholders }) .collect(); - match py.compiler_detach(|| check_sql_syntax(&dialect, &checks)) { - Ok(valid) => (Some(valid), None), - Err(reason) => (None, Some(reason)), - } + py.compiler_detach(|| check_sql_syntax(&dialect, &checks)) + .map_err(|reason| compiler_error(native_failure(SYNTAX_CHECK_CONTEXT, &reason)))? + .map_err(syntax_value_error) } -fn project_request(request: RequestRow) -> ProjectRequest { +fn project_request(request: RequestRow) -> PyResult { let ( dialect, target, @@ -116,7 +190,7 @@ fn project_request(request: RequestRow) -> ProjectRequest { audits, ) = request; let (database, schema, seed_database, seed_schema) = defaults; - ProjectRequest { + Ok(ProjectRequest { dialect, target: target.map(|(database, schema, loader_schema)| TargetNamespace { database, @@ -129,7 +203,10 @@ fn project_request(request: RequestRow) -> ProjectRequest { seed_database, seed_schema, }, - variables: variables.into_iter().map(variable).collect(), + variables: variables + .into_iter() + .map(variable) + .collect::>()?, environment, models: models.into_iter().map(model).collect(), sources: sources @@ -143,13 +220,22 @@ fn project_request(request: RequestRow) -> ProjectRequest { .collect(), seeds: seeds .into_iter() - .map(|(name, database, schema)| SeedFacts { + .map(|(name, tags, database, schema)| SeedFacts { name, + tags, database, schema, }) .collect(), - functions: functions.into_iter().map(references).collect(), + functions: functions + .into_iter() + .map(|(kind, name, tags, rows)| FunctionFacts { + kind, + name, + tags, + references: references(rows), + }) + .collect(), audits: audits .into_iter() .map(|(rows, attached)| AuditFacts { @@ -157,23 +243,52 @@ fn project_request(request: RequestRow) -> ProjectRequest { attached, }) .collect(), - } + }) } -fn variable(row: VariableRow) -> (String, Variable) { - let (name, kind, text) = row; - let value: Variable = match kind.as_str() { - TEXT_VARIABLE => Variable::Scalar(Scalar::Text(text)), - BOOLEAN_VARIABLE => Variable::Scalar(Scalar::Bool(text == TRUE_TEXT)), - NONE_VARIABLE => Variable::Scalar(Scalar::Null), - _ => Variable::Unsupported, +fn variable(row: VariableRow) -> PyResult<(String, Variable)> { + let (name, kind, text, render) = row; + let value: Variable = match (kind.as_str(), render) { + (TEXT_VARIABLE, _) => Variable::Scalar(Scalar::Text(text)), + (BOOLEAN_VARIABLE, _) => Variable::Scalar(Scalar::Bool(text == TRUE_TEXT)), + (NONE_VARIABLE, _) => Variable::Scalar(Scalar::Null), + (OPAQUE_VARIABLE, Some((render_kind, payload))) => Variable::Opaque(OpaqueVariable { + text, + render: opaque_render(&render_kind, payload)?, + }), + _ => { + return Err(compiler_error(native_failure( + PROJECT_ASSEMBLY_CONTEXT, + &format!("an unknown variable kind '{kind}'"), + ))); + } }; - (name, value) + Ok((name, value)) +} + +fn opaque_render(kind: &str, payload: String) -> PyResult { + match kind { + RENDERED_TEXT => Ok(OpaqueRender::Text(payload)), + RENDER_REJECTED => Ok(OpaqueRender::Rejected(payload)), + RENDER_RAISES => payload.parse().map(OpaqueRender::Raises).map_err(|_| { + compiler_error(native_failure( + PROJECT_ASSEMBLY_CONTEXT, + "an opaque variable's held exception index is not a number", + )) + }), + _ => Err(compiler_error(native_failure( + PROJECT_ASSEMBLY_CONTEXT, + &format!("an unknown variable rendering '{kind}'"), + ))), + } } fn model(row: ModelRow) -> ModelFacts { - let (rows, checks) = row; + let (name, directory, tags, rows, checks) = row; ModelFacts { + name, + directory, + tags, references: references(rows), syntax_checks: checks .into_iter() @@ -192,15 +307,52 @@ fn references(rows: Vec) -> Vec { .collect() } -fn resources_row(resources: ProjectResources) -> ResourcesRow { - ( +fn resources_row(resources: ProjectResources) -> PyResult { + let failure: Option = resources.failure.map(failure_row).transpose()?; + Ok(( resources.model_deps, resources.sources, resources.seeds.into_iter().map(namespace_row).collect(), resources.function_deps, resources.audit_deps, resources.reads.into_iter().map(read_row).collect(), - ) + resources.model_syntax_valid, + failure, + )) +} + +/// `(resource list, index, error class, message, help, held exception index)`. +fn failure_row(failure: ResourceFailure) -> PyResult { + let slot: &'static str = match failure.slot { + ResourceSlot::Source => SOURCE_SLOT, + ResourceSlot::Seed => SEED_SLOT, + ResourceSlot::Audit => AUDIT_SLOT, + }; + Ok(match failure.error { + AssemblyError::CompileInput { message, help } => ( + slot, + failure.index, + COMPILE_INPUT_ERROR, + message, + help, + None, + ), + AssemblyError::Value(message) => (slot, failure.index, VALUE_ERROR, message, None, None), + AssemblyError::Raise(held) => ( + slot, + failure.index, + HELD_ERROR, + String::new(), + None, + Some(held), + ), + AssemblyError::Internal(reason) => { + return Err(compiler_error(native_failure( + PROJECT_ASSEMBLY_CONTEXT, + &reason, + ))); + } + }) } fn read_row(read: InputRead) -> (&'static str, String) { @@ -222,5 +374,6 @@ fn namespace_row(namespace: Namespace) -> NamespaceRow { pub(crate) fn register(module: &Bound<'_, PyModule>) -> PyResult<()> { module.add_function(wrap_pyfunction!(assemble_project_resource_facts, module)?)?; module.add_function(wrap_pyfunction!(check_native_sql_syntax, module)?)?; + module.add_function(wrap_pyfunction!(sql_syntax_error, module)?)?; Ok(()) } diff --git a/crates/sqlbuild-python/src/bindings/_helpers/render/macro_call_rows.rs b/crates/sqlbuild-python/src/bindings/_helpers/render/macro_call_rows.rs index 78ccae8219..bff5a278ed 100644 --- a/crates/sqlbuild-python/src/bindings/_helpers/render/macro_call_rows.rs +++ b/crates/sqlbuild-python/src/bindings/_helpers/render/macro_call_rows.rs @@ -10,8 +10,8 @@ const DECLARATION_READ: u8 = 1; const GENERATED_SQL: u8 = 2; const ARGUMENT_REFERENCE: u8 = 3; -/// One call site: start, end, name, tree names and whether typed reference text appears. -pub(crate) type SiteRow = (usize, usize, String, Vec, bool); +/// One call site: start, arguments start, end, name, tree names if scanned and whether typed reference text appears. +pub(crate) type SiteRow = (usize, usize, usize, String, Option>, bool); /// One substitution span: source start and end, output start and end. pub(crate) type SpanRow = (usize, usize, usize, usize); /// One recorded event: its tag and two text fields. @@ -22,6 +22,7 @@ pub(crate) type EntryRow = (String, Vec<(String, String)>, Vec); pub(crate) fn site_row(site: MacroCallSite) -> SiteRow { ( site.start, + site.args_start, site.end, site.name, site.tree_names, diff --git a/crates/sqlbuild-python/src/bindings/_helpers/render/macro_calls.rs b/crates/sqlbuild-python/src/bindings/_helpers/render/macro_calls.rs index 1d4677fa4a..fe4bc7b33d 100644 --- a/crates/sqlbuild-python/src/bindings/_helpers/render/macro_calls.rs +++ b/crates/sqlbuild-python/src/bindings/_helpers/render/macro_calls.rs @@ -3,34 +3,68 @@ use pyo3::exceptions::PyValueError; use pyo3::prelude::{Bound, PyModule, PyModuleMethods, PyResult, Python}; use pyo3::{pyfunction, wrap_pyfunction}; +use sqlbuild_core::panics::main::native_failure::native_failure; +use sqlbuild_core::text::main::active_python_text::active_python_text; use sqlbuild_core::text::main::python_text::python_text; +use sqlbuild_render::macro_calls::main::macro_call_names::macro_call_names as scan_names; use sqlbuild_render::macro_calls::main::scan_macro_call_sites::scan_macro_call_sites as scan_sites; use sqlbuild_render::macro_calls::main::splice_macro_calls::splice_macro_calls as splice_calls; -use sqlbuild_render::macro_calls::models::ScanDeferral; +use sqlbuild_render::macro_calls::models::{MacroCallScan, MacroScanFailure}; use crate::bindings::_helpers::boundary::panics::compiler_error; use crate::bindings::_helpers::render::macro_call_memo::MacroCallMemo; use crate::bindings::_helpers::render::macro_call_rows::{SiteRow, SpanRow, site_row, span_row}; use crate::bindings::types::CompilerDetach; -/// Every top-level macro call site of `sql`, or `None` when Python must expand the string. +const MACRO_SCAN_CONTEXT: &str = "native macro call scan"; + +/// `(call start or None, call name or None, message)` of the error Python's scan raises. +type FailureRow = (Option, Option, &'static str); + +/// Every complete top-level macro call site of `sql`, and where Python's scan raises, if it does. #[pyfunction] pub(crate) fn scan_macro_call_sites( py: Python<'_>, sql: &str, python_version: (u8, u8), unicode_version: &str, -) -> PyResult>> { - let Some(python) = python_text(python_version, unicode_version) else { - return Ok(None); - }; - let scanned = py +) -> PyResult<(Vec, Option)> { + let python = python_text(python_version, unicode_version).ok_or_else(|| { + compiler_error(native_failure( + MACRO_SCAN_CONTEXT, + "the macro bridge runs on a Python whose text tables are not compiled in", + )) + })?; + let MacroCallScan { sites, failure } = py .compiler_detach(|| Ok(scan_sites(python, sql))) .map_err(compiler_error)?; - match scanned { - Ok(sites) => Ok(Some(sites.into_iter().map(site_row).collect())), - Err(ScanDeferral) => Ok(None), - } + Ok(( + sites.into_iter().map(site_row).collect(), + failure.map( + |MacroScanFailure { + call_start, + call_name, + error, + }| (call_start, call_name, error.message()), + ), + )) +} + +/// Python's `find_macro_call_names` names, or the `CompileInputError` message of its scan. +#[pyfunction] +pub(crate) fn macro_call_names( + py: Python<'_>, + sql: &str, + nested: bool, +) -> PyResult<(Option>, Option<&'static str>)> { + let python = active_python_text(); + let names = py + .compiler_detach(|| Ok(scan_names(python, sql, nested))) + .map_err(compiler_error)?; + Ok(match names { + Ok(names) => (Some(names), None), + Err(error) => (None, Some(error.message())), + }) } /// Splice rendered macro outputs over their call sites, returning the SQL and substitution spans. @@ -51,6 +85,7 @@ pub(crate) fn splice_macro_calls( pub(crate) fn register(module: &Bound<'_, PyModule>) -> PyResult<()> { module.add_function(wrap_pyfunction!(scan_macro_call_sites, module)?)?; + module.add_function(wrap_pyfunction!(macro_call_names, module)?)?; module.add_function(wrap_pyfunction!(splice_macro_calls, module)?)?; module.add_class::()?; Ok(()) diff --git a/crates/sqlbuild-python/src/bindings/_helpers/semantic_checks/completion.rs b/crates/sqlbuild-python/src/bindings/_helpers/semantic_checks/completion.rs index c01e4e67d9..8829c70ce4 100644 --- a/crates/sqlbuild-python/src/bindings/_helpers/semantic_checks/completion.rs +++ b/crates/sqlbuild-python/src/bindings/_helpers/semantic_checks/completion.rs @@ -10,7 +10,10 @@ use sqlbuild_analysis::semantic_checks::models::{ use crate::bindings::_helpers::analysis_session::session::NativeModelAnalysisSession; use crate::bindings::_helpers::boundary::panics::compiler_error; -use crate::bindings::_helpers::semantic_checks::session_facts::session_model_facts; +use crate::bindings::_helpers::semantic_checks::failures::semantic_error; +use crate::bindings::_helpers::semantic_checks::session_facts::{ + column_names, session_model_facts, +}; use crate::bindings::_helpers::semantic_checks::type_recovery::{LineageInput, lineage_outputs}; use crate::bindings::models::ProjectCatalog; use crate::bindings::types::CompilerDetach; @@ -60,13 +63,8 @@ type CompletedRow = ( ); /// `(completed position, (model, message, note, help))`: exactly one side is set. type OrderRow = (Option, Option<(usize, String, String, String)>); -/// `(deferral, completed, model binding positions, order)`. -type OutcomeRow = ( - Option<&'static str>, - Vec, - Option>>, - Vec, -); +/// `(completed, model binding positions, order)`. +type OutcomeRow = (Vec, Option>>, Vec); /// Recover, explain and reject opt-outs, reading facts the payload omits from `session`. #[pyfunction] @@ -79,13 +77,12 @@ fn complete_semantic_checks( ) -> PyResult { let request = completion_request(request, session.as_deref()).map_err(compiler_error)?; let catalog = &catalog.inner; - let outcome = py - .compiler_detach(|| complete_semantic_diagnostics(&request, catalog)) - .map_err(compiler_error)?; - let (deferral, parts) = outcome.into_parts(); - let (diagnostics, model_bindings, order) = parts.unwrap_or_default(); + let (diagnostics, model_bindings, order) = py + .compiler_detach(|| Ok(complete_semantic_diagnostics(&request, catalog))) + .map_err(compiler_error)? + .map_err(|failure| semantic_error(py, &failure))? + .into_parts(); Ok(( - deferral, diagnostics.into_iter().map(completed_row).collect(), model_bindings, order.into_iter().map(order_row).collect(), @@ -148,10 +145,7 @@ fn completion_model( ) -> Result { let inferred_columns: Vec = match inferred_columns { Some(names) => names, - None => session_model_facts(session, &name)? - .columns - .clone() - .unwrap_or_default(), + None => column_names(session_model_facts(session, &name)?).unwrap_or_default(), }; let lineage: Vec = match lineage { Some(lineage) => lineage, diff --git a/crates/sqlbuild-python/src/bindings/_helpers/semantic_checks/failures.rs b/crates/sqlbuild-python/src/bindings/_helpers/semantic_checks/failures.rs new file mode 100644 index 0000000000..8535b64c6c --- /dev/null +++ b/crates/sqlbuild-python/src/bindings/_helpers/semantic_checks/failures.rs @@ -0,0 +1,35 @@ +//! The exception a failed native semantic completion step raises. + +use pyo3::exceptions::{PyTypeError, PyValueError}; +use pyo3::{PyErr, Python}; +use sqlbuild_analysis::semantic_checks::models::SemanticFailure; +use sqlbuild_core::constants::PANIC_MESSAGE; +use sqlbuild_core::panics::main::is_compiler_panic::is_compiler_panic; +use sqlbuild_core::panics::main::native_failure::native_failure; + +use crate::bindings::_helpers::boundary::panics::compiler_error; +use crate::bindings::_helpers::type_system::normalization::normalization_error; + +const SEMANTIC_CONTEXT: &str = "native semantic completion"; +/// The wheel's `TypeError` for `tokenize(sql, dialect=None)`. +const NO_DIALECT_MESSAGE: &str = "argument 'dialect': 'None' is not an instance of 'str'"; + +/// The error Python's semantic completion raised for the same input, or `NativeCompilerError`. +pub(crate) fn semantic_error(python: Python<'_>, failure: &SemanticFailure) -> PyErr { + match failure { + SemanticFailure::NoDialect => PyTypeError::new_err(NO_DIALECT_MESSAGE), + SemanticFailure::UnknownDialect(name) => { + PyValueError::new_err(format!("Unknown dialect: {name}")) + } + SemanticFailure::TypeNormalization(error) => normalization_error(python, error), + SemanticFailure::Internal(reason) => internal_error(reason), + } +} + +/// An internal native failure as `NativeCompilerError`, keeping an already placed context. +pub(crate) fn internal_error(reason: &str) -> PyErr { + if is_compiler_panic(reason) && reason != PANIC_MESSAGE { + return compiler_error(reason); + } + compiler_error(native_failure(SEMANTIC_CONTEXT, reason)) +} diff --git a/crates/sqlbuild-python/src/bindings/_helpers/semantic_checks/metadata.rs b/crates/sqlbuild-python/src/bindings/_helpers/semantic_checks/metadata.rs index b53ae01f31..26edf624ae 100644 --- a/crates/sqlbuild-python/src/bindings/_helpers/semantic_checks/metadata.rs +++ b/crates/sqlbuild-python/src/bindings/_helpers/semantic_checks/metadata.rs @@ -11,6 +11,7 @@ use sqlbuild_analysis::semantic_checks::models::{ use std::sync::Arc; use crate::bindings::_helpers::boundary::panics::compiler_error; +use crate::bindings::_helpers::semantic_checks::failures::semantic_error; use crate::bindings::models::ProjectCatalog; use crate::bindings::types::CompilerDetach; @@ -41,9 +42,8 @@ type RequestInput = ( ); /// `(code, message, line, column)`. type ErrorRow = (&'static str, String, i64, i64); -/// `(deferral, [(function, reference findings)], source, SQL test findings, fallback types)`. +/// `([(function, reference findings)], source, SQL test findings, fallback types)`. type OutcomeRow = ( - Option<&'static str>, Vec<(Vec, Vec)>, Vec<(usize, ErrorRow)>, Vec<(usize, ErrorRow, i64)>, @@ -59,33 +59,24 @@ fn check_semantic_metadata_rows( ) -> PyResult { let request = metadata_request(request)?; let catalog = &catalog.inner; - let checked = py - .compiler_detach(|| check_semantic_metadata(&request, catalog)) - .map_err(compiler_error)?; - Ok(match checked { - Err(deferral) => ( - Some(deferral.as_str()), - Vec::new(), - Vec::new(), - Vec::new(), - Vec::new(), - ), - Ok(outcome) => ( - None, - outcome.models.into_iter().map(model_rows).collect(), - outcome - .sources - .into_iter() - .map(|(index, error)| (index, error_row(error))) - .collect(), - outcome - .sql_tests - .into_iter() - .map(|(index, error, end)| (index, error_row(error), end)) - .collect(), - outcome.fallback_types, - ), - }) + let outcome = py + .compiler_detach(|| Ok(check_semantic_metadata(&request, catalog))) + .map_err(compiler_error)? + .map_err(|failure| semantic_error(py, &failure))?; + Ok(( + outcome.models.into_iter().map(model_rows).collect(), + outcome + .sources + .into_iter() + .map(|(index, error)| (index, error_row(error))) + .collect(), + outcome + .sql_tests + .into_iter() + .map(|(index, error, end)| (index, error_row(error), end)) + .collect(), + outcome.fallback_types, + )) } fn error_row(error: MetadataFinding) -> ErrorRow { diff --git a/crates/sqlbuild-python/src/bindings/_helpers/semantic_checks/mod.rs b/crates/sqlbuild-python/src/bindings/_helpers/semantic_checks/mod.rs index 1565c82749..b02c83a208 100644 --- a/crates/sqlbuild-python/src/bindings/_helpers/semantic_checks/mod.rs +++ b/crates/sqlbuild-python/src/bindings/_helpers/semantic_checks/mod.rs @@ -1,4 +1,5 @@ pub(crate) mod completion; +pub(crate) mod failures; pub(crate) mod metadata; pub(crate) mod registration; pub(crate) mod session_facts; diff --git a/crates/sqlbuild-python/src/bindings/_helpers/semantic_checks/session_facts.rs b/crates/sqlbuild-python/src/bindings/_helpers/semantic_checks/session_facts.rs index eaf244fa10..467c2e4eb5 100644 --- a/crates/sqlbuild-python/src/bindings/_helpers/semantic_checks/session_facts.rs +++ b/crates/sqlbuild-python/src/bindings/_helpers/semantic_checks/session_facts.rs @@ -1,7 +1,7 @@ //! Model output names and lineage the semantic stages read from a finished analysis session. use sqlbuild_analysis::assembly::analysis_session::main::finished_model_facts::finished_model_facts; -use sqlbuild_analysis::assembly::analysis_session::models::SessionModelFacts; +use sqlbuild_analysis::assembly::analysis_session::models::{ColumnFact, SessionModelFacts}; use crate::bindings::_helpers::analysis_session::session::NativeModelAnalysisSession; @@ -16,3 +16,9 @@ pub(crate) fn session_model_facts<'a>( finished_model_facts(finished, name) .ok_or_else(|| format!("the finished session kept no facts for model {name}")) } + +/// The output column names of a model's session facts. +pub(crate) fn column_names(facts: &SessionModelFacts) -> Option> { + let columns: &[ColumnFact] = facts.columns.as_deref()?; + Some(columns.iter().map(|column| column.name.clone()).collect()) +} diff --git a/crates/sqlbuild-python/src/bindings/_helpers/semantic_checks/type_recovery.rs b/crates/sqlbuild-python/src/bindings/_helpers/semantic_checks/type_recovery.rs index 801971e2a4..c95f6030ed 100644 --- a/crates/sqlbuild-python/src/bindings/_helpers/semantic_checks/type_recovery.rs +++ b/crates/sqlbuild-python/src/bindings/_helpers/semantic_checks/type_recovery.rs @@ -12,7 +12,10 @@ use sqlbuild_analysis::semantic_checks::types::RevisedBinding; use crate::bindings::_helpers::analysis_session::session::NativeModelAnalysisSession; use crate::bindings::_helpers::boundary::panics::compiler_error; -use crate::bindings::_helpers::semantic_checks::session_facts::session_model_facts; +use crate::bindings::_helpers::semantic_checks::failures::{internal_error, semantic_error}; +use crate::bindings::_helpers::semantic_checks::session_facts::{ + column_names, session_model_facts, +}; use crate::bindings::models::ProjectCatalog; use crate::bindings::types::CompilerDetach; @@ -46,18 +49,12 @@ pub(crate) struct SemanticTypeRecovery { #[pymethods] impl SemanticTypeRecovery { - /// `unchanged`, `planned` or `deferred`. + /// `unchanged` or `planned`. #[getter] fn status(&self) -> &'static str { self.step.status() } - /// The deferral kind, when the stage is handed back to Python. - #[getter] - fn deferral(&self) -> Option<&'static str> { - self.step.deferral() - } - /// Poisoned `(model, column)` outputs in Python's dict order. #[getter] fn poisoned(&self) -> Vec<(String, String)> { @@ -76,13 +73,15 @@ impl SemanticTypeRecovery { .unwrap_or_default() } - /// Retained diagnostics and model binding positions, or None to defer to Python. - fn finish(&self, revised: Vec>) -> Option { - let plan = self.step.plan()?; - match finish_type_recovery(&self.request, plan, &revised) { - Ok(outcome) => Some((outcome.kept, outcome.model_bindings)), - Err(_) => None, - } + /// Retained diagnostics and model binding positions; an internal failure raises. + fn finish(&self, revised: Vec>) -> PyResult { + let plan = self + .step + .plan() + .ok_or_else(|| internal_error("finishing a type recovery that has no plan"))?; + finish_type_recovery(&self.request, plan, &revised) + .map(|outcome| (outcome.kept, outcome.model_bindings)) + .map_err(|reason| internal_error(&reason)) } } @@ -98,8 +97,9 @@ fn plan_semantic_type_recovery( let request = recovery_request(request, session.as_deref()).map_err(compiler_error)?; let catalog = &catalog.inner; let step = py - .compiler_detach(|| plan_type_recovery(&request, catalog)) - .map_err(compiler_error)?; + .compiler_detach(|| Ok(plan_type_recovery(&request, catalog))) + .map_err(compiler_error)? + .map_err(|failure| semantic_error(py, &failure))?; Ok(SemanticTypeRecovery { request, step }) } @@ -143,7 +143,7 @@ fn recovery_model( Some(lineage) => (inferred_columns, lineage), None => { let facts = session_model_facts(session, &name)?; - (facts.columns.clone(), facts.lineage.clone()) + (column_names(facts), facts.lineage.clone()) } }; Ok(RecoveryModel { diff --git a/crates/sqlbuild-python/src/bindings/_helpers/sql_test_glue/assembly.rs b/crates/sqlbuild-python/src/bindings/_helpers/sql_test_glue/assembly.rs index 8769cb3b70..5b1c988c04 100644 --- a/crates/sqlbuild-python/src/bindings/_helpers/sql_test_glue/assembly.rs +++ b/crates/sqlbuild-python/src/bindings/_helpers/sql_test_glue/assembly.rs @@ -5,16 +5,22 @@ use pyo3::prelude::{Bound, PyAny, PyAnyMethods, PyModule, PyModuleMethods, PyRes use pyo3::{FromPyObject, PyErr, pyfunction, wrap_pyfunction}; use sqlbuild_analysis::compiler::main::sql_test_assembly::assemble_sql_test_batch; use sqlbuild_analysis::compiler::models::{ - AssembledSqlTestFacts, SqlTestAssemblyBatch, SqlTestAssemblyModel, SqlTestAssemblyModelPayload, - SqlTestAssemblyOutcome, SqlTestAssemblyPayload, SqlTestAssemblyReference, SqlTestAssemblyTest, - SqlTestCte, SqlTestParameterValue, + AssembledSqlTestFacts, SqlTestAssemblyBatch, SqlTestAssemblyFailure, SqlTestAssemblyModel, + SqlTestAssemblyModelPayload, SqlTestAssemblyOutcome, SqlTestAssemblyPayload, + SqlTestAssemblyReference, SqlTestAssemblyTest, SqlTestCte, SqlTestParameterValue, }; +use sqlbuild_core::panics::main::native_failure::native_failure; + use crate::bindings::_helpers::boundary::panics::value_error; use crate::bindings::_helpers::sqltext::lexical_syntax::LexicalSyntaxInput; use crate::bindings::types::CompilerDetach; const MACRO_TOKEN: char = '@'; +const INPUT_FAILURE: &str = "input"; +const INTERNAL_FAILURE: &str = "internal"; +const DECIMAL_OVERFLOW: &str = "decimal_overflow"; +const SQL_TEST_ASSEMBLY_CONTEXT: &str = "native SQL test assembly"; /// `(line, column, end line, end column, message, help)` of one P013 diagnostic. type DiagnosticRow = (usize, usize, usize, usize, String, String); @@ -27,8 +33,8 @@ type FactsRow = ( String, Vec, ); -/// The test's facts, or the deferral kind of a test Python assembles. -type AssemblyRow = (Option, Option<&'static str>); +/// The test's facts, and the `(kind, message)` of the error its assembly raises, if any. +type AssemblyRow = (Option, Option<(&'static str, String)>); /// The Python assembly request: the project's model inputs and the SQL test inputs. #[derive(FromPyObject)] @@ -41,7 +47,7 @@ struct AssemblyRequest<'py> { lexical_syntax: LexicalSyntaxInput, } -/// Each test input's assembled facts, or the deferral of a test Python must assemble. +/// Each test input's assembled facts, or the error its assembly raises. #[pyfunction] fn assemble_compiled_sql_tests( py: Python<'_>, @@ -120,7 +126,6 @@ fn assembly_test(test: &Bound<'_, PyAny>) -> PyResult { .getattr("reference_target_model_names")? .extract()?, mock_model_names: payload.getattr("mock_model_names")?.extract()?, - has_macro_mocks: payload.getattr("macro_mocks")?.is_truthy()?, }) }; Ok(SqlTestAssemblyTest { @@ -219,7 +224,20 @@ fn parameter_values(items: &Bound<'_, PyAny>) -> PyResult AssemblyRow { match outcome { SqlTestAssemblyOutcome::Assembled(facts) => (Some(facts_row(facts)), None), - SqlTestAssemblyOutcome::Deferred(deferral) => (None, Some(deferral.as_str())), + SqlTestAssemblyOutcome::FingerprintOverflow(facts) => ( + Some(facts_row(facts)), + Some((DECIMAL_OVERFLOW, String::new())), + ), + SqlTestAssemblyOutcome::Failed(SqlTestAssemblyFailure::Input(message)) => { + (None, Some((INPUT_FAILURE, message))) + } + SqlTestAssemblyOutcome::Failed(SqlTestAssemblyFailure::Internal(reason)) => ( + None, + Some(( + INTERNAL_FAILURE, + native_failure(SQL_TEST_ASSEMBLY_CONTEXT, &reason), + )), + ), } } diff --git a/crates/sqlbuild-python/src/bindings/_helpers/sqltext/declaration_references.rs b/crates/sqlbuild-python/src/bindings/_helpers/sqltext/declaration_references.rs index 384070befe..b01a3a7760 100644 --- a/crates/sqlbuild-python/src/bindings/_helpers/sqltext/declaration_references.rs +++ b/crates/sqlbuild-python/src/bindings/_helpers/sqltext/declaration_references.rs @@ -25,12 +25,32 @@ fn scan_sql_declaration_references( sqls: Vec, python_version: (u8, u8), unicode_version: &str, +) -> PyResult> { + scanned_rows(py, sqls, (python_version, unicode_version), false) +} + +/// The same scan walking past malformed references, as Python's declaration usage walk did. +#[pyfunction] +fn scan_sql_declaration_usages( + py: Python<'_>, + sqls: Vec, + python_version: (u8, u8), + unicode_version: &str, +) -> PyResult> { + scanned_rows(py, sqls, (python_version, unicode_version), true) +} + +fn scanned_rows( + py: Python<'_>, + sqls: Vec, + (python_version, unicode_version): ((u8, u8), &str), + skip_malformed: bool, ) -> PyResult> { let python = python_text(python_version, unicode_version).ok_or_else(|| { PyRuntimeError::new_err("declaration scanning needs a supported Python (see D017)") })?; let scanned: Vec = py - .compiler_detach(|| Ok(scan_declaration_references(python, &sqls))) + .compiler_detach(|| Ok(scan_declaration_references(python, &sqls, skip_malformed))) .map_err(compiler_error)?; Ok(scanned.into_iter().map(scan_row).collect()) } @@ -63,5 +83,6 @@ fn reference_row(reference: DeclarationReference) -> ReferenceRow { pub(crate) fn register(module: &Bound<'_, PyModule>) -> PyResult<()> { module.add_function(wrap_pyfunction!(scan_sql_declaration_references, module)?)?; + module.add_function(wrap_pyfunction!(scan_sql_declaration_usages, module)?)?; Ok(()) } diff --git a/crates/sqlbuild-python/src/bindings/_helpers/sqltext/mod.rs b/crates/sqlbuild-python/src/bindings/_helpers/sqltext/mod.rs index 13533443f7..4cd903b971 100644 --- a/crates/sqlbuild-python/src/bindings/_helpers/sqltext/mod.rs +++ b/crates/sqlbuild-python/src/bindings/_helpers/sqltext/mod.rs @@ -2,6 +2,7 @@ pub(crate) mod authored_values; pub(crate) mod declaration_references; pub(crate) mod lexical_syntax; pub(crate) mod model_headers; +pub(crate) mod placeholders; pub(crate) mod registration; pub(crate) mod sql_references; pub(crate) mod static_sql; diff --git a/crates/sqlbuild-python/src/bindings/_helpers/sqltext/placeholders.rs b/crates/sqlbuild-python/src/bindings/_helpers/sqltext/placeholders.rs new file mode 100644 index 0000000000..c65bb50926 --- /dev/null +++ b/crates/sqlbuild-python/src/bindings/_helpers/sqltext/placeholders.rs @@ -0,0 +1,24 @@ +//! Substitute `@@@name` placeholder defaults for SQL analysis. + +use pyo3::prelude::{Bound, PyModule, PyModuleMethods, PyResult, Python}; +use pyo3::{pyfunction, wrap_pyfunction}; +use sqlbuild_sqltext::compiler::main::placeholder_defaults::placeholder_defaults; + +use crate::bindings::_helpers::boundary::panics::compiler_error; +use crate::bindings::types::CompilerDetach; + +/// Python's `substitute_placeholder_defaults`: each `@@@name` becomes its default. +#[pyfunction] +fn substitute_placeholder_defaults( + py: Python<'_>, + sql: &str, + placeholders: Vec<(String, String)>, +) -> PyResult { + py.compiler_detach(|| Ok(placeholder_defaults(sql, &placeholders))) + .map_err(compiler_error) +} + +pub(crate) fn register(module: &Bound<'_, PyModule>) -> PyResult<()> { + module.add_function(wrap_pyfunction!(substitute_placeholder_defaults, module)?)?; + Ok(()) +} diff --git a/crates/sqlbuild-python/src/bindings/_helpers/sqltext/registration.rs b/crates/sqlbuild-python/src/bindings/_helpers/sqltext/registration.rs index 0e0a165845..4fe4b866e4 100644 --- a/crates/sqlbuild-python/src/bindings/_helpers/sqltext/registration.rs +++ b/crates/sqlbuild-python/src/bindings/_helpers/sqltext/registration.rs @@ -3,7 +3,7 @@ use pyo3::prelude::{Bound, PyModule, PyResult}; use crate::bindings::_helpers::sqltext::{ - declaration_references, model_headers, sql_references, static_sql, + declaration_references, model_headers, placeholders, sql_references, static_sql, }; pub(crate) fn register(module: &Bound<'_, PyModule>) -> PyResult<()> { @@ -11,5 +11,6 @@ pub(crate) fn register(module: &Bound<'_, PyModule>) -> PyResult<()> { static_sql::register(module)?; sql_references::register(module)?; declaration_references::register(module)?; + placeholders::register(module)?; Ok(()) } diff --git a/crates/sqlbuild-python/src/bindings/_helpers/type_system/normalization.rs b/crates/sqlbuild-python/src/bindings/_helpers/type_system/normalization.rs index c4c2d802e5..3f37bbd680 100644 --- a/crates/sqlbuild-python/src/bindings/_helpers/type_system/normalization.rs +++ b/crates/sqlbuild-python/src/bindings/_helpers/type_system/normalization.rs @@ -1,39 +1,61 @@ -//! Native type normalization for the preview type system. +//! Native type normalization. -use pyo3::prelude::{Bound, PyModule, PyModuleMethods, PyResult}; +use pyo3::exceptions::PyValueError; +use pyo3::prelude::{Bound, PyAnyMethods, PyErr, PyModule, PyModuleMethods, PyResult, Python}; use pyo3::{pyfunction, wrap_pyfunction}; +use sqlbuild_analysis::type_system::errors::TypeNormalizationError; use sqlbuild_analysis::type_system::main::normalize_type::normalize_type; use sqlbuild_analysis::type_system::models::{NormalizedType, TypeNormalization}; use crate::bindings::_helpers::boundary::panics::compiler_guard; /// `(name, family, precision, scale, length)` of one normalized type. -type NormalizedRow = (String, &'static str, Option, Option, Option); +type NormalizedRow = ( + String, + &'static str, + Option, + Option, + Option, +); -/// Normalize one type: `(normalized row, Polyglot parse error)`, or None to defer to Python. +/// Normalize one type: `(normalized row, Polyglot parse error)`, or Python's exception. #[pyfunction] #[pyo3(name = "normalize_type")] fn normalize_type_binding( + python: Python<'_>, type_sql: &str, dialect: &str, -) -> PyResult)>> { - compiler_guard(|| { - Ok(normalize_type(type_sql, dialect).map( - |TypeNormalization { - normalized, - parse_error, - }| (normalized_row(normalized), parse_error), - )) - }) +) -> PyResult<(NormalizedRow, Option)> { + let normalization: Result = + compiler_guard(|| Ok(normalize_type(type_sql, dialect)))?; + match normalization { + Ok(TypeNormalization { + normalized, + parse_error, + }) => Ok((normalized_row(normalized), parse_error)), + Err(error) => Err(normalization_error(python, &error)), + } +} + +/// The exception the Polyglot wheel raises for the same failure. +pub(crate) fn normalization_error(python: Python<'_>, error: &TypeNormalizationError) -> PyErr { + match error { + TypeNormalizationError::UnknownDialect(_) => PyValueError::new_err(error.message()), + TypeNormalizationError::Generation(_) => python + .import("polyglot_sql") + .and_then(|module| module.getattr("PolyglotError")) + .and_then(|class| class.call1((error.message(),))) + .map_or_else(|import_error| import_error, PyErr::from_value), + } } fn normalized_row(normalized: NormalizedType) -> NormalizedRow { ( normalized.normalized_name, normalized.family.as_str(), - normalized.precision, - normalized.scale, - normalized.length, + normalized.precision.map(|value| value.as_str().to_owned()), + normalized.scale.map(|value| value.as_str().to_owned()), + normalized.length.map(|value| value.as_str().to_owned()), ) } diff --git a/crates/sqlbuild-python/src/bindings/main/register.rs b/crates/sqlbuild-python/src/bindings/main/register.rs index 0e0d1ed5c9..5e1929b275 100644 --- a/crates/sqlbuild-python/src/bindings/main/register.rs +++ b/crates/sqlbuild-python/src/bindings/main/register.rs @@ -41,6 +41,7 @@ pub fn _native(module: &Bound<'_, PyModule>) -> PyResult<()> { } fn register_analysis_stages(module: &Bound<'_, PyModule>) -> PyResult<()> { + boundary::python_runtime::record_python_text(module.py())?; type_system::registration::register(module)?; analysis_session::registration::register(module)?; semantic_checks::registration::register(module)?; diff --git a/crates/sqlbuild-render/src/macro_calls/_helpers/scanner.rs b/crates/sqlbuild-render/src/macro_calls/_helpers/scanner.rs index 71cef2c882..249c35e149 100644 --- a/crates/sqlbuild-render/src/macro_calls/_helpers/scanner.rs +++ b/crates/sqlbuild-render/src/macro_calls/_helpers/scanner.rs @@ -1,10 +1,11 @@ -//! Byte offset port of the Python macro call scanner; unsure or rejected text defers to Python. +//! Byte offset port of the Python macro call scanner, with the errors Python's scan raises. use sqlbuild_core::text::main::is_python_alnum::is_python_alnum; +use sqlbuild_core::text::main::is_python_alpha::is_python_alpha; use sqlbuild_core::text::main::is_python_space::is_python_space; use sqlbuild_core::text::models::PythonText; -use crate::macro_calls::models::ScanDeferral; +use crate::macro_calls::errors::ScanError; const TYPED_REFERENCE_NAMES: [&str; 3] = ["__ref", "__source", "__seed"]; @@ -16,26 +17,71 @@ pub(crate) struct ScannedCall { pub(crate) name: String, } -/// Return every top-level call of `text` in order. +/// Where Python's scan of the text raises: in the call starting at a byte offset, or between calls. +pub(crate) struct ScannedFailure { + pub(crate) call_start: Option, + pub(crate) error: ScanError, +} + +/// Every top-level call of `text` in order, up to the first error Python's scan raises. pub(crate) fn top_level_calls( python: PythonText, text: &str, -) -> Result, ScanDeferral> { +) -> (Vec, Option) { let mut calls: Vec = Vec::new(); let mut cursor = 0; + while cursor < text.len() { + let start = match next_macro_start(python, text, cursor) { + Ok(Some(start)) => start, + Ok(None) => break, + Err(error) => { + let failure = ScannedFailure { + call_start: None, + error, + }; + return (calls, Some(failure)); + } + }; + match call_at(python, text, start) { + Ok(call) => { + cursor = call.close + 1; + calls.push(call); + } + Err(error) => { + let failure = ScannedFailure { + call_start: Some(start), + error, + }; + return (calls, Some(failure)); + } + } + } + (calls, None) +} + +/// Python's `_parse_macro_name`: the identifier after the `@` at byte `start`. +pub(crate) fn call_name(python: PythonText, text: &str, start: usize) -> String { + text[start + 1..identifier_end(python, text, start + 1)].to_owned() +} + +/// Python's `_scan_sqlbuild_call_names(include_nested=True)`: every call start's name in order. +pub(crate) fn every_call_name(python: PythonText, text: &str) -> Result, ScanError> { + let mut names: Vec = Vec::new(); + let mut cursor = 0; while cursor < text.len() { let Some(start) = next_macro_start(python, text, cursor)? else { break; }; - let call = call_at(python, text, start)?; - cursor = call.close + 1; - calls.push(call); + let name_end = identifier_end(python, text, start + 1); + names.push(text[start + 1..name_end].to_owned()); + let open = skip_whitespace(text, name_end); + cursor = open + char_at(text, open).map_or(1, char::len_utf8); } - Ok(calls) + Ok(names) } /// Names of every call nested in `args` in source order, in one pass without recursion. -pub(crate) fn nested_names(python: PythonText, args: &str) -> Result, ScanDeferral> { +pub(crate) fn nested_names(python: PythonText, args: &str) -> Result, ScanError> { let bytes: &[u8] = args.as_bytes(); let mut names: Vec = Vec::new(); let mut open_call_depths: Vec = Vec::new(); @@ -47,7 +93,7 @@ pub(crate) fn nested_names(python: PythonText, args: &str) -> Result b'$' => index = dollar_quote_end(bytes, index)?.unwrap_or(index + 1), b'-' if bytes.get(index + 1) == Some(&b'-') => index = line_comment_end(bytes, index), b'/' if bytes.get(index + 1) == Some(&b'*') => index = block_comment_end(bytes, index)?, - b'@' if macro_call_starts_at(python, args, index)? => { + b'@' if macro_call_starts_at(python, args, index) => { let (name, open) = call_header(python, args, index)?; names.push(name); depth += 1; @@ -62,7 +108,7 @@ pub(crate) fn nested_names(python: PythonText, args: &str) -> Result if open_call_depths.last() == Some(&depth) { let _ = open_call_depths.pop(); } - depth = depth.checked_sub(1).ok_or(ScanDeferral)?; + depth = depth.checked_sub(1).ok_or(ScanError::UnclosedParenthesis)?; index += 1; } _ => index += 1, @@ -71,7 +117,7 @@ pub(crate) fn nested_names(python: PythonText, args: &str) -> Result if open_call_depths.is_empty() { Ok(names) } else { - Err(ScanDeferral) + Err(ScanError::UnclosedParenthesis) } } @@ -80,7 +126,7 @@ pub(crate) fn mentions_typed_reference(args: &str) -> bool { TYPED_REFERENCE_NAMES.iter().any(|name| args.contains(name)) } -fn call_at(python: PythonText, text: &str, start: usize) -> Result { +fn call_at(python: PythonText, text: &str, start: usize) -> Result { let (name, open) = call_header(python, text, start)?; let close = matching_paren(text.as_bytes(), open)?; Ok(ScannedCall { @@ -91,15 +137,11 @@ fn call_at(python: PythonText, text: &str, start: usize) -> Result Result<(String, usize), ScanDeferral> { +fn call_header(python: PythonText, text: &str, start: usize) -> Result<(String, usize), ScanError> { let name_end = identifier_end(python, text, start + 1); let open = skip_whitespace(text, name_end); if text.as_bytes().get(open) != Some(&b'(') { - return Err(ScanDeferral); + return Err(ScanError::MissingParenthesis); } Ok((text[start + 1..name_end].to_owned(), open)) } @@ -108,7 +150,7 @@ fn next_macro_start( python: PythonText, text: &str, from: usize, -) -> Result, ScanDeferral> { +) -> Result, ScanError> { let bytes = text.as_bytes(); let mut index = from; while index < bytes.len() { @@ -118,7 +160,7 @@ fn next_macro_start( b'-' if bytes.get(index + 1) == Some(&b'-') => index = line_comment_end(bytes, index), b'/' if bytes.get(index + 1) == Some(&b'*') => index = block_comment_end(bytes, index)?, b'@' => { - if macro_call_starts_at(python, text, index)? { + if macro_call_starts_at(python, text, index) { return Ok(Some(index)); } index += 1; @@ -129,24 +171,21 @@ fn next_macro_start( Ok(None) } -fn macro_call_starts_at(python: PythonText, text: &str, at: usize) -> Result { +fn macro_call_starts_at(python: PythonText, text: &str, at: usize) -> bool { let Some(first) = char_at(text, at + 1) else { - return Ok(false); + return false; }; - if !first.is_ascii() { - return Err(ScanDeferral); - } - if !(first.is_ascii_alphabetic() || first == '_') { - return Ok(false); + if !(first == '_' || is_python_alpha(python, first)) { + return false; } - let mut cursor = at + 2; + let mut cursor = at + 1 + first.len_utf8(); while let Some(character) = char_at(text, cursor) { if !is_identifier_continue(python, character) { break; } cursor = skip_whitespace(text, cursor + character.len_utf8()); } - Ok(text.as_bytes().get(cursor) == Some(&b'(')) + text.as_bytes().get(cursor) == Some(&b'(') } fn identifier_end(python: PythonText, text: &str, from: usize) -> usize { @@ -179,7 +218,7 @@ fn char_at(text: &str, index: usize) -> Option { text.get(index..).and_then(|rest| rest.chars().next()) } -fn matching_paren(bytes: &[u8], open: usize) -> Result { +fn matching_paren(bytes: &[u8], open: usize) -> Result { let mut depth = 1usize; let mut index = open + 1; while index < bytes.len() { @@ -213,10 +252,10 @@ fn matching_paren(bytes: &[u8], open: usize) -> Result { } index += 1; } - Err(ScanDeferral) + Err(ScanError::UnclosedParenthesis) } -fn quote_end(bytes: &[u8], start: usize) -> Result { +fn quote_end(bytes: &[u8], start: usize) -> Result { let quote = bytes[start]; let doubled_escapes = quote == b'\'' || quote == b'"'; let mut index = start + 1; @@ -224,7 +263,7 @@ fn quote_end(bytes: &[u8], start: usize) -> Result { let offset = bytes[index.min(bytes.len())..] .iter() .position(|byte| *byte == quote) - .ok_or(ScanDeferral)?; + .ok_or(ScanError::UnclosedQuote)?; index += offset; if doubled_escapes && bytes.get(index + 1) == Some("e) { index += 2; @@ -234,7 +273,7 @@ fn quote_end(bytes: &[u8], start: usize) -> Result { } } -fn dollar_quote_end(bytes: &[u8], start: usize) -> Result, ScanDeferral> { +fn dollar_quote_end(bytes: &[u8], start: usize) -> Result, ScanError> { if start .checked_sub(1) .is_some_and(|previous| continues_dollar_word(bytes[previous])) @@ -254,7 +293,7 @@ fn dollar_quote_end(bytes: &[u8], start: usize) -> Result, ScanDef .windows(delimiter.len()) .position(|window| window == delimiter) .map(|offset| Some(tag_end + 1 + offset + delimiter.len())) - .ok_or(ScanDeferral) + .ok_or(ScanError::UnclosedQuote) } fn continues_dollar_word(byte: u8) -> bool { @@ -268,10 +307,10 @@ fn line_comment_end(bytes: &[u8], start: usize) -> usize { .map_or(bytes.len(), |offset| start + offset + 1) } -fn block_comment_end(bytes: &[u8], start: usize) -> Result { +fn block_comment_end(bytes: &[u8], start: usize) -> Result { bytes[start + 2..] .windows(2) .position(|pair| pair == b"*/") .map(|offset| start + 2 + offset + 2) - .ok_or(ScanDeferral) + .ok_or(ScanError::UnclosedComment) } diff --git a/crates/sqlbuild-render/src/macro_calls/errors.rs b/crates/sqlbuild-render/src/macro_calls/errors.rs new file mode 100644 index 0000000000..794df0001c --- /dev/null +++ b/crates/sqlbuild-render/src/macro_calls/errors.rs @@ -0,0 +1,23 @@ +//! The errors Python's macro call scan raises. + +/// An error Python's macro call scan raises. +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub enum ScanError { + UnclosedQuote, + UnclosedComment, + UnclosedParenthesis, + /// A call start whose name is not followed by its parenthesis. + MissingParenthesis, +} + +impl ScanError { + /// The message of the `CompileInputError` Python's scan raises. + pub fn message(self) -> &'static str { + match self { + Self::UnclosedQuote => "Macro expansion contains an unclosed quoted string", + Self::UnclosedComment => "Macro expansion contains an unclosed block comment", + Self::UnclosedParenthesis => "Macro expansion contains an unclosed parenthesis", + Self::MissingParenthesis => "expected opening parenthesis", + } + } +} diff --git a/crates/sqlbuild-render/src/macro_calls/main/macro_call_names.rs b/crates/sqlbuild-render/src/macro_calls/main/macro_call_names.rs new file mode 100644 index 0000000000..d8ee7b0b6a --- /dev/null +++ b/crates/sqlbuild-render/src/macro_calls/main/macro_call_names.rs @@ -0,0 +1,33 @@ +//! Python's `find_macro_call_names` and `find_nested_macro_call_names`. + +use sqlbuild_core::text::models::PythonText; + +use crate::macro_calls::_helpers::scanner::{every_call_name, top_level_calls}; +use crate::macro_calls::errors::ScanError; + +/// Python's `_scan_sqlbuild_call_names`: unique call names in encounter order. +pub fn macro_call_names( + python: PythonText, + sql: &str, + nested: bool, +) -> Result, ScanError> { + if !sql.contains('@') { + return Ok(Vec::new()); + } + let scanned: Vec = if nested { + every_call_name(python, sql)? + } else { + let (calls, failure) = top_level_calls(python, sql); + if let Some(failure) = failure { + return Err(failure.error); + } + calls.into_iter().map(|call| call.name).collect() + }; + let mut names: Vec = Vec::new(); + for name in scanned { + if !names.contains(&name) { + names.push(name); + } + } + Ok(names) +} diff --git a/crates/sqlbuild-render/src/macro_calls/main/mod.rs b/crates/sqlbuild-render/src/macro_calls/main/mod.rs index 2f945c96d5..46e047d83f 100644 --- a/crates/sqlbuild-render/src/macro_calls/main/mod.rs +++ b/crates/sqlbuild-render/src/macro_calls/main/mod.rs @@ -1,2 +1,3 @@ +pub mod macro_call_names; pub mod scan_macro_call_sites; pub mod splice_macro_calls; diff --git a/crates/sqlbuild-render/src/macro_calls/main/scan_macro_call_sites.rs b/crates/sqlbuild-render/src/macro_calls/main/scan_macro_call_sites.rs index 47598cc9dd..ae7000146a 100644 --- a/crates/sqlbuild-render/src/macro_calls/main/scan_macro_call_sites.rs +++ b/crates/sqlbuild-render/src/macro_calls/main/scan_macro_call_sites.rs @@ -4,39 +4,60 @@ use sqlbuild_core::text::models::PythonText; use crate::macro_calls::_helpers::offsets::char_offsets; use crate::macro_calls::_helpers::scanner::{ - mentions_typed_reference, nested_names, top_level_calls, + call_name, mentions_typed_reference, nested_names, top_level_calls, }; -use crate::macro_calls::models::{MacroCallSite, ScanDeferral}; +use crate::macro_calls::models::{MacroCallScan, MacroCallSite, MacroScanFailure}; -/// Every top-level call site in order under `python`'s character classes, or a deferral. -pub fn scan_macro_call_sites( - python: PythonText, - sql: &str, -) -> Result, ScanDeferral> { - let calls = top_level_calls(python, sql)?; - let boundaries: Vec = calls +/// Every complete top-level call site in order, and where Python's scan raises, if it does. +pub fn scan_macro_call_sites(python: PythonText, sql: &str) -> MacroCallScan { + let (calls, failure) = top_level_calls(python, sql); + let mut boundaries: Vec = calls .iter() - .flat_map(|call| [call.start, call.close + 1]) + .flat_map(|call| [call.start, call.open + 1, call.close + 1]) .collect(); + let failed_call: Option = failure.as_ref().and_then(|failure| failure.call_start); + boundaries.extend(failed_call); let offsets = char_offsets(sql, &boundaries); - calls + let sites: Vec = calls .into_iter() - .zip(offsets.as_chunks::<2>().0) + .zip(offsets.as_chunks::<3>().0) .map(|(call, offsets)| { let args = &sql[call.open + 1..call.close]; - let mut tree_names: Vec = vec![call.name.clone()]; - for name in nested_names(python, args)? { - if !tree_names.contains(&name) { - tree_names.push(name); - } - } - Ok(MacroCallSite { + let tree_names: Option> = call_tree_names(python, &call.name, args); + MacroCallSite { start: offsets[0], - end: offsets[1], + args_start: offsets[1], + end: offsets[2], name: call.name, tree_names, typed_reference_text: mentions_typed_reference(args), - }) + } }) - .collect() + .collect(); + let failure: Option = failure.map(|failure| MacroScanFailure { + call_start: failure.call_start.and(offsets.last().copied()), + call_name: failed_call_name(python, sql, failure.call_start), + error: failure.error, + }); + MacroCallScan { sites, failure } +} + +/// The name of the call at byte `start` that Python's evaluation raises in, if any. +fn failed_call_name(python: PythonText, sql: &str, start: Option) -> Option { + Some(call_name(python, sql, start?)) +} + +/// The call's name, then each nested call's once; None where a nested scan raises. +fn call_tree_names(python: PythonText, name: &str, args: &str) -> Option> { + let nested: Vec = match nested_names(python, args) { + Ok(nested) => nested, + Err(_scan_error) => return None, + }; + let mut tree_names: Vec = vec![name.to_owned()]; + for nested_name in nested { + if !tree_names.contains(&nested_name) { + tree_names.push(nested_name); + } + } + Some(tree_names) } diff --git a/crates/sqlbuild-render/src/macro_calls/mod.rs b/crates/sqlbuild-render/src/macro_calls/mod.rs index e6e5a52eb4..004a682592 100644 --- a/crates/sqlbuild-render/src/macro_calls/mod.rs +++ b/crates/sqlbuild-render/src/macro_calls/mod.rs @@ -1,4 +1,5 @@ pub(crate) mod _helpers; +pub mod errors; pub mod main; pub mod models; diff --git a/crates/sqlbuild-render/src/macro_calls/models.rs b/crates/sqlbuild-render/src/macro_calls/models.rs index d2d5ada473..37c2ba728f 100644 --- a/crates/sqlbuild-render/src/macro_calls/models.rs +++ b/crates/sqlbuild-render/src/macro_calls/models.rs @@ -7,6 +7,8 @@ use sqlbuild_cache::store::models::NativeStore; use std::collections::HashMap; use std::sync::Arc; +use crate::macro_calls::errors::ScanError; + use crate::macro_calls::_helpers::entry_codec::{decode_entry, encode_entry}; /// One top-level `@macro(...)` call in an authored SQL string; offsets count code points. @@ -14,19 +16,34 @@ use crate::macro_calls::_helpers::entry_codec::{decode_entry, encode_entry}; pub struct MacroCallSite { /// Offset of the `@` that starts the call. pub start: usize, + /// Offset just past the call's opening parenthesis, where its arguments start. + pub args_start: usize, /// Offset just past the call's closing parenthesis. pub end: usize, /// The called macro's name. pub name: String, - /// Every macro name in the call, the top-level name first, then nested calls once each. - pub tree_names: Vec, + /// Every macro name in the call: the top-level name, then nested calls once each. + pub tree_names: Option>, /// The arguments mention `__ref`, `__source` or `__seed`, so typed references may be passed. pub typed_reference_text: bool, } -/// The scan met text Python reports or classifies differently; Python must expand the string. -#[derive(Clone, Copy, Debug, PartialEq, Eq)] -pub struct ScanDeferral; +/// Where a scan stops: inside the call at a code point offset, or between calls. +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct MacroScanFailure { + /// Offset of the `@` of the call Python's evaluation raises in, if any. + pub call_start: Option, + /// The name of the call Python's evaluation raises in, if any. + pub call_name: Option, + pub error: ScanError, +} + +/// A string's complete top-level call sites in order, and where the scan stopped, if it did. +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct MacroCallScan { + pub sites: Vec, + pub failure: Option, +} /// One consumer-independent fact a macro call produced, replayed for every consumer in order. #[derive(Clone, Debug, PartialEq, Eq, Hash)] diff --git a/crates/sqlbuild-render/src/macro_calls/tests.rs b/crates/sqlbuild-render/src/macro_calls/tests.rs index 6340f8ffc3..f84924210d 100644 --- a/crates/sqlbuild-render/src/macro_calls/tests.rs +++ b/crates/sqlbuild-render/src/macro_calls/tests.rs @@ -2,6 +2,8 @@ mod helpers; #[path = "tests/test_macro_call_memo.rs"] mod macro_call_memo; +#[path = "tests/test_macro_call_names.rs"] +mod macro_call_names; #[path = "tests/test_scan_macro_call_sites.rs"] mod scan_macro_call_sites; #[path = "tests/test_splice_macro_calls.rs"] diff --git a/crates/sqlbuild-render/src/macro_calls/tests/helpers.rs b/crates/sqlbuild-render/src/macro_calls/tests/helpers.rs index 2fa89bc6ec..7766e69df8 100644 --- a/crates/sqlbuild-render/src/macro_calls/tests/helpers.rs +++ b/crates/sqlbuild-render/src/macro_calls/tests/helpers.rs @@ -3,7 +3,9 @@ use sqlbuild_core::text::main::python_text::python_text; use sqlbuild_core::text::models::PythonText; use std::path::Path; +use crate::macro_calls::errors::ScanError; use crate::macro_calls::models::{MacroCallEntry, MacroCallEvent, MacroCallMemo}; +use crate::macro_calls::tests::test_types::ExpectedNames; /// A memo holding one recorded `@cents(amount)` call in class 1, and that call's entry. pub(crate) fn recorded_memo() -> (MacroCallMemo, MacroCallEntry) { @@ -74,3 +76,8 @@ pub(crate) fn every_event_entry() -> MacroCallEntry { ], } } + +/// Expected call names as the owned names the scan returns. +pub(crate) fn owned_names(names: ExpectedNames) -> Result, ScanError> { + names.map(|names| names.iter().map(|name| (*name).to_owned()).collect()) +} diff --git a/crates/sqlbuild-render/src/macro_calls/tests/test_macro_call_names.rs b/crates/sqlbuild-render/src/macro_calls/tests/test_macro_call_names.rs new file mode 100644 index 0000000000..7f2110efd0 --- /dev/null +++ b/crates/sqlbuild-render/src/macro_calls/tests/test_macro_call_names.rs @@ -0,0 +1,66 @@ +use crate::macro_calls::errors::ScanError; +use crate::macro_calls::main::macro_call_names::macro_call_names; +use crate::macro_calls::tests::helpers::{owned_names, python_312}; +use crate::macro_calls::tests::test_types::MacroCallNamesTestCase; + +#[test] +fn given_sql_when_listing_macro_call_names_then_python_scan_agrees() { + let test_cases = [ + MacroCallNamesTestCase { + description: "declaration calls are listed", + sql: "@enum(x) @a(1)", + expected_top_level: Ok(&["enum", "a"]), + expected_nested: Ok(&["enum", "a"]), + }, + MacroCallNamesTestCase { + description: "a name without its parenthesis fails only the top-level scan", + sql: "@ab c(1)", + expected_top_level: Err(ScanError::MissingParenthesis), + expected_nested: Ok(&["ab"]), + }, + MacroCallNamesTestCase { + description: "an at sign inside a word starts no call", + sql: "x@\u{f6}re FROM o", + expected_top_level: Ok(&[]), + expected_nested: Ok(&[]), + }, + MacroCallNamesTestCase { + description: "an unclosed call fails only the top-level scan", + sql: "@\u{e9}(1) @b(", + expected_top_level: Err(ScanError::UnclosedParenthesis), + expected_nested: Ok(&["\u{e9}", "b"]), + }, + MacroCallNamesTestCase { + description: "quoted, commented and doubled at signs start no call", + sql: "'@q()' /* @c() */ @d ( 1 ) @@v", + expected_top_level: Ok(&[]), + expected_nested: Ok(&[]), + }, + MacroCallNamesTestCase { + description: "nested calls are listed only when nested", + sql: "@a(@b(@c()))", + expected_top_level: Ok(&["a"]), + expected_nested: Ok(&["a", "b", "c"]), + }, + MacroCallNamesTestCase { + description: "an unclosed quote fails both scans", + sql: "@a(\"x\") 'oops", + expected_top_level: Err(ScanError::UnclosedQuote), + expected_nested: Err(ScanError::UnclosedQuote), + }, + ]; + for test_case in test_cases { + assert_eq!( + ( + macro_call_names(python_312(), test_case.sql, false), + macro_call_names(python_312(), test_case.sql, true) + ), + ( + owned_names(test_case.expected_top_level), + owned_names(test_case.expected_nested) + ), + "{}", + test_case.description + ); + } +} diff --git a/crates/sqlbuild-render/src/macro_calls/tests/test_scan_macro_call_sites.rs b/crates/sqlbuild-render/src/macro_calls/tests/test_scan_macro_call_sites.rs index 0ee44440e9..3f83a4f069 100644 --- a/crates/sqlbuild-render/src/macro_calls/tests/test_scan_macro_call_sites.rs +++ b/crates/sqlbuild-render/src/macro_calls/tests/test_scan_macro_call_sites.rs @@ -1,9 +1,10 @@ +use crate::macro_calls::errors::ScanError; use crate::macro_calls::main::scan_macro_call_sites::scan_macro_call_sites; use crate::macro_calls::tests::helpers::python_312; use std::time::Instant; use crate::macro_calls::tests::test_types::{ - DeepNestingTestCase, ExpectedSite, ScanMacroCallSitesTestCase, + CallBoundsTestCase, DeepNestingTestCase, ExpectedSite, ScanMacroCallSitesTestCase, }; #[test] @@ -12,119 +13,161 @@ fn given_authored_sql_when_scanning_macro_calls_then_sites_match_python_expansio ScanMacroCallSitesTestCase { description: "one call", sql: "SELECT @a(1) FROM t", - expected_sites: Some(&[(7, 12, "a", &["a"], false)]), + expected_sites: &[(7, 12, "a", Some(&["a"]), false)], + expected_failure: None, }, ScanMacroCallSitesTestCase { description: "nested calls belong to the enclosing site", sql: "@outer(@inner(@leaf()), '@quoted()', @inner(2)) y", - expected_sites: Some(&[(0, 47, "outer", &["outer", "inner", "leaf"], false)]), + expected_sites: &[(0, 47, "outer", Some(&["outer", "inner", "leaf"]), false)], + expected_failure: None, }, ScanMacroCallSitesTestCase { description: "quoted text and comments hide calls", sql: "'@a(1)' -- @b(2)\n/* @c(3) */ \"@d()\" `@e()` $$@f()$$ @g()", - expected_sites: Some(&[(52, 56, "g", &["g"], false)]), + expected_sites: &[(52, 56, "g", Some(&["g"]), false)], + expected_failure: None, }, ScanMacroCallSitesTestCase { description: "a one-letter name followed by whitespace is not a call", sql: "@a (1)", - expected_sites: Some(&[]), + expected_sites: &[], + expected_failure: None, }, ScanMacroCallSitesTestCase { description: "a longer name may be separated from its parenthesis", sql: "@ab (1)", - expected_sites: Some(&[(0, 7, "ab", &["ab"], false)]), + expected_sites: &[(0, 7, "ab", Some(&["ab"]), false)], + expected_failure: None, }, ScanMacroCallSitesTestCase { - description: "whitespace inside a name defers to Python's error", + description: "whitespace inside a name fails in that call, as Python's evaluation does", sql: "@ab c(1)", - expected_sites: None, + expected_sites: &[], + expected_failure: Some((Some(0), ScanError::MissingParenthesis)), }, ScanMacroCallSitesTestCase { - description: "an unclosed quote after a call defers", + description: "an unclosed quote after a call fails after it", sql: "@a(1) 'oops", - expected_sites: None, + expected_sites: &[(0, 5, "a", Some(&["a"]), false)], + expected_failure: Some((None, ScanError::UnclosedQuote)), }, ScanMacroCallSitesTestCase { - description: "an unclosed call defers", + description: "an unclosed call fails in that call", sql: "@a(1", - expected_sites: None, + expected_sites: &[], + expected_failure: Some((Some(0), ScanError::UnclosedParenthesis)), }, ScanMacroCallSitesTestCase { description: "offsets count code points", sql: "SELECT 'é', @a(1)", - expected_sites: Some(&[(12, 17, "a", &["a"], false)]), + expected_sites: &[(12, 17, "a", Some(&["a"]), false)], + expected_failure: None, }, ScanMacroCallSitesTestCase { - description: "a non-ASCII character after @ defers", + description: "a non-ASCII letter after @ starts a call as Python's isalpha says", sql: "@é(1)", - expected_sites: None, + expected_sites: &[(0, 5, "é", Some(&["é"]), false)], + expected_failure: None, + }, + ScanMacroCallSitesTestCase { + description: "a non-letter non-ASCII character after @ is not a call", + sql: "@€(1) @m()", + expected_sites: &[(6, 10, "m", Some(&["m"]), false)], + expected_failure: None, + }, + ScanMacroCallSitesTestCase { + description: "an unclosed block comment between calls fails there", + sql: "@a() /* @b()", + expected_sites: &[(0, 4, "a", Some(&["a"]), false)], + expected_failure: Some((None, ScanError::UnclosedComment)), + }, + ScanMacroCallSitesTestCase { + description: "an unclosed dollar quote inside a call fails in that call", + sql: "x @a() é @b($tag$ )", + expected_sites: &[(2, 6, "a", Some(&["a"]), false)], + expected_failure: Some((Some(9), ScanError::UnclosedQuote)), }, ScanMacroCallSitesTestCase { description: "typed reference text is flagged", sql: "@m(__ref('x')) @n('__seed') @o(1)", - expected_sites: Some(&[ - (0, 14, "m", &["m"], true), - (15, 27, "n", &["n"], true), - (28, 33, "o", &["o"], false), - ]), + expected_sites: &[ + (0, 14, "m", Some(&["m"]), true), + (15, 27, "n", Some(&["n"]), true), + (28, 33, "o", Some(&["o"]), false), + ], + expected_failure: None, }, ScanMacroCallSitesTestCase { description: "a dollar sign continuing a word does not open a quote", sql: "a$$ @m()", - expected_sites: Some(&[(4, 8, "m", &["m"], false)]), + expected_sites: &[(4, 8, "m", Some(&["m"]), false)], + expected_failure: None, }, ScanMacroCallSitesTestCase { description: "interpolation markers are not calls", sql: "x @@var @m()", - expected_sites: Some(&[(8, 12, "m", &["m"], false)]), + expected_sites: &[(8, 12, "m", Some(&["m"]), false)], + expected_failure: None, }, ScanMacroCallSitesTestCase { description: "nested names follow source order across siblings and plain parentheses", sql: "@a((@b(@c(1)), (@d()) ), \"@x()\", @c())", - expected_sites: Some(&[(0, 38, "a", &["a", "b", "c", "d"], false)]), + expected_sites: &[(0, 38, "a", Some(&["a", "b", "c", "d"]), false)], + expected_failure: None, }, ScanMacroCallSitesTestCase { description: "a quoted parenthesis inside a nested call does not close it", sql: "@a(@b(')'))", - expected_sites: Some(&[(0, 11, "a", &["a", "b"], false)]), + expected_sites: &[(0, 11, "a", Some(&["a", "b"]), false)], + expected_failure: None, }, ScanMacroCallSitesTestCase { - description: "a nested name without its parenthesis defers", + description: "a nested name without its parenthesis leaves the tree unscanned", sql: "@a(@bb c(1))", - expected_sites: None, + expected_sites: &[(0, 12, "a", None, false)], + expected_failure: None, }, ScanMacroCallSitesTestCase { description: "parentheses inside quoted arguments do not close the call", sql: "@m(')', \"(\", `)`) z", - expected_sites: Some(&[(0, 17, "m", &["m"], false)]), + expected_sites: &[(0, 17, "m", Some(&["m"]), false)], + expected_failure: None, }, ]; for test_case in test_cases { - let actual: Option> = scan_macro_call_sites(python_312(), test_case.sql) - .ok() - .map(|sites| { - sites - .into_iter() - .map(|site| { - let names: Vec<&'static str> = site - .tree_names - .iter() - .map(|name| &*Box::leak(name.clone().into_boxed_str())) - .collect(); - ( - site.start, - site.end, - &*Box::leak(site.name.into_boxed_str()), - &*Box::leak(names.into_boxed_slice()), - site.typed_reference_text, - ) - }) - .collect() - }); + let scan = scan_macro_call_sites(python_312(), test_case.sql); + let actual: Vec = scan + .sites + .into_iter() + .map(|site| { + let names: Option<&'static [&'static str]> = site.tree_names.map(|names| { + let names: Vec<&'static str> = names + .into_iter() + .map(|name| &*Box::leak(name.into_boxed_str())) + .collect(); + &*Box::leak(names.into_boxed_slice()) + }); + ( + site.start, + site.end, + &*Box::leak(site.name.into_boxed_str()), + names, + site.typed_reference_text, + ) + }) + .collect(); assert_eq!( - actual, - test_case.expected_sites.map(<[ExpectedSite]>::to_vec), + ( + actual, + scan.failure + .map(|failure| (failure.call_start, failure.error)) + ), + ( + test_case.expected_sites.to_vec(), + test_case.expected_failure + ), "{}", test_case.description ); @@ -162,7 +205,7 @@ fn given_deeply_nested_calls_when_scanning_then_time_is_linear_and_nothing_overf ); let started = Instant::now(); - let sites = scan_macro_call_sites(python_312(), &sql).expect("scanned"); + let scan = scan_macro_call_sites(python_312(), &sql); assert!( started.elapsed().as_secs_f64() < test_case.expected_max_seconds, @@ -170,11 +213,77 @@ fn given_deeply_nested_calls_when_scanning_then_time_is_linear_and_nothing_overf test_case.description ); assert_eq!( - sites - .iter() - .map(|site| site.tree_names.clone()) - .collect::>(), - vec![test_case.expected_tree_names.to_vec()], + ( + scan.sites + .iter() + .map(|site| site.tree_names.clone()) + .collect::>(), + scan.failure, + ), + ( + vec![Some( + test_case + .expected_tree_names + .iter() + .map(|name| (*name).to_owned()) + .collect() + )], + None + ), + "{}", + test_case.description + ); + } +} + +#[test] +fn given_calls_when_scanning_then_argument_starts_and_failing_call_names_match_python() { + let test_cases = [ + CallBoundsTestCase { + description: "argument starts skip the whitespace before the parenthesis", + sql: "x @ab (1) @\u{e9}(@b())", + expected_args_starts: &[8, 14], + expected_failure: None, + }, + CallBoundsTestCase { + description: "a call without its parenthesis names the failing call", + sql: "@a() @bb c(1)", + expected_args_starts: &[3], + expected_failure: Some((Some(5), Some("bb"), ScanError::MissingParenthesis)), + }, + CallBoundsTestCase { + description: "an unclosed call after non-ASCII text names the failing call", + sql: "'\u{e9}' @c\u{e9}(1", + expected_args_starts: &[], + expected_failure: Some((Some(4), Some("c\u{e9}"), ScanError::UnclosedParenthesis)), + }, + CallBoundsTestCase { + description: "a failure between calls names none", + sql: "@a(1) 'open", + expected_args_starts: &[3], + expected_failure: Some((None, None, ScanError::UnclosedQuote)), + }, + ]; + for test_case in test_cases { + let scan = scan_macro_call_sites(python_312(), test_case.sql); + + assert_eq!( + ( + scan.sites + .iter() + .map(|site| site.args_start) + .collect::>(), + scan.failure + .map(|failure| (failure.call_start, failure.call_name, failure.error)), + ), + ( + test_case.expected_args_starts.to_vec(), + test_case.expected_failure.map(|(start, name, error)| ( + start, + name.map(str::to_owned), + error + )), + ), "{}", test_case.description ); diff --git a/crates/sqlbuild-render/src/macro_calls/tests/test_types.rs b/crates/sqlbuild-render/src/macro_calls/tests/test_types.rs index b58c34f5a4..f6196dad72 100644 --- a/crates/sqlbuild-render/src/macro_calls/tests/test_types.rs +++ b/crates/sqlbuild-render/src/macro_calls/tests/test_types.rs @@ -1,5 +1,13 @@ -/// One expected call site: start, end, name, tree names and whether typed reference text appears. -pub(crate) type ExpectedSite = (usize, usize, &'static str, &'static [&'static str], bool); +use crate::macro_calls::errors::ScanError; + +/// One expected call site: start, end, name, scanned tree names and typed reference text. +pub(crate) type ExpectedSite = ( + usize, + usize, + &'static str, + Option<&'static [&'static str]>, + bool, +); /// One expected splice: the rendered SQL and each span's source and output offsets. pub(crate) type ExpectedSplice = (&'static str, &'static [(usize, usize, usize, usize)]); @@ -7,7 +15,8 @@ pub(crate) type ExpectedSplice = (&'static str, &'static [(usize, usize, usize, pub(crate) struct ScanMacroCallSitesTestCase { pub(crate) description: &'static str, pub(crate) sql: &'static str, - pub(crate) expected_sites: Option<&'static [ExpectedSite]>, + pub(crate) expected_sites: &'static [ExpectedSite], + pub(crate) expected_failure: Option<(Option, ScanError)>, } pub(crate) struct SpliceMacroCallsTestCase { @@ -39,3 +48,20 @@ pub(crate) struct DeepNestingTestCase { pub(crate) expected_tree_names: &'static [&'static str], pub(crate) expected_max_seconds: f64, } + +/// Call names as Python's `_scan_sqlbuild_call_names` returned them, or its scan error. +pub(crate) type ExpectedNames = Result<&'static [&'static str], ScanError>; + +pub(crate) struct MacroCallNamesTestCase { + pub(crate) description: &'static str, + pub(crate) sql: &'static str, + pub(crate) expected_top_level: ExpectedNames, + pub(crate) expected_nested: ExpectedNames, +} + +pub(crate) struct CallBoundsTestCase { + pub(crate) description: &'static str, + pub(crate) sql: &'static str, + pub(crate) expected_args_starts: &'static [usize], + pub(crate) expected_failure: Option<(Option, Option<&'static str>, ScanError)>, +} diff --git a/crates/sqlbuild-scopes/src/relationship_names/_helpers/cte_scan.rs b/crates/sqlbuild-scopes/src/relationship_names/_helpers/cte_scan.rs index e633b46d43..b2c9ec8164 100644 --- a/crates/sqlbuild-scopes/src/relationship_names/_helpers/cte_scan.rs +++ b/crates/sqlbuild-scopes/src/relationship_names/_helpers/cte_scan.rs @@ -1,7 +1,11 @@ //! The top-level CTE scan of `extract_top_level_ctes_with_scanner`. +use sqlbuild_core::text::main::active_python_text::active_python_text; +use sqlbuild_core::text::main::is_python_alnum::is_python_alnum; +use sqlbuild_core::text::main::is_python_alpha::is_python_alpha; use sqlbuild_core::text::main::is_python_space::is_python_space; use sqlbuild_core::text::main::python_strip::python_strip; +use sqlbuild_core::text::main::python_upper::python_upper; use sqlbuild_sqltext::sql_scan::main::dialect_matching_paren::dialect_matching_paren; use sqlbuild_sqltext::sql_scan::main::dialect_non_code_end::dialect_non_code_end; use sqlbuild_sqltext::sql_scan::models::{LexicalSyntax, Unclosed}; @@ -232,7 +236,7 @@ fn try_consume_keyword(sql: &str, start: usize, keyword: &str) -> Option .char_indices() .nth(keyword.len()) .map_or(sql.len(), |(offset, _)| start + offset); - if sql[start..window_end].to_uppercase() != keyword { + if python_upper(active_python_text(), &sql[start..window_end]) != keyword { return None; } let continues = |character: Option| character.is_some_and(is_identifier_character); @@ -245,7 +249,7 @@ fn try_consume_keyword(sql: &str, start: usize, keyword: &str) -> Option fn read_identifier<'sql>(text: &ScanText<'sql>, start: usize) -> Scan<(&'sql str, usize)> { let mut characters = text.sql[start..].char_indices(); match characters.next() { - Some((_, first)) if first.is_alphabetic() || first == '_' => {} + Some((_, first)) if is_python_alpha(active_python_text(), first) || first == '_' => {} _ => return Err(failed(text, "expected a CTE name".to_owned())), } let end: usize = characters @@ -260,5 +264,5 @@ fn matching_paren(text: &ScanText<'_>, open: usize, syntax: &LexicalSyntax) -> S /// Python's `isalnum() or _`. fn is_identifier_character(character: char) -> bool { - character.is_alphanumeric() || character == '_' + is_python_alnum(active_python_text(), character) || character == '_' } diff --git a/crates/sqlbuild-scopes/src/relationship_names/tests/test_expected_model_names.rs b/crates/sqlbuild-scopes/src/relationship_names/tests/test_expected_model_names.rs index bb640b410b..60d150c7a0 100644 --- a/crates/sqlbuild-scopes/src/relationship_names/tests/test_expected_model_names.rs +++ b/crates/sqlbuild-scopes/src/relationship_names/tests/test_expected_model_names.rs @@ -26,6 +26,16 @@ fn given_sql_test_when_scanning_expected_models_then_names_and_errors_match_pyth sql: "WITH __expected__a AS (SELECT 1) select 1 ; -- done\n", expected_outcome: scanned(&["a"]), }, + ExpectedNamesTestCase { + description: "an alphabetic mark Python's isalpha rejects does not start a CTE name", + sql: "WITH \u{345}x AS (SELECT 1)", + expected_outcome: failed("SQL test 'tests/unit/test_orders.sql' expected a CTE name"), + }, + ExpectedNamesTestCase { + description: "an alphabetic mark Python's isalnum rejects ends a CTE name", + sql: "WITH __expected__a\u{345} AS (SELECT 1)", + expected_outcome: failed("SQL test 'tests/unit/test_orders.sql' expected keyword AS"), + }, ExpectedNamesTestCase { description: "no top-level WITH has no expected models", sql: "SELECT 1", diff --git a/crates/sqlbuild-scopes/src/scope_index/_helpers/identities.rs b/crates/sqlbuild-scopes/src/scope_index/_helpers/identities.rs index 12d4640057..953352e6d7 100644 --- a/crates/sqlbuild-scopes/src/scope_index/_helpers/identities.rs +++ b/crates/sqlbuild-scopes/src/scope_index/_helpers/identities.rs @@ -3,6 +3,7 @@ use crate::scope_index::models::{ DeclarationIdentity, GrantRecord, GrantThrough, ResourceIdentity, ScopeIndex, }; +use sqlbuild_core::text::main::python_str_repr::python_str_repr; /// Python's `format_identity` for a resource. pub(crate) fn resource_text(identity: &ResourceIdentity) -> String { @@ -33,38 +34,6 @@ pub(crate) fn grant_through_text(index: &ScopeIndex, grant: &GrantRecord) -> Str } } -/// Python's `repr` of a string, or `None` when it holds text whose escaping needs Unicode tables. -pub(crate) fn python_str_repr(value: &str) -> Option { - if !value.is_ascii() { - return None; - } - let quote: char = if value.contains('\'') && !value.contains('"') { - '"' - } else { - '\'' - }; - let mut text: String = String::with_capacity(value.len() + 2); - text.push(quote); - for character in value.chars() { - match character { - '\\' => text.push_str("\\\\"), - '\t' => text.push_str("\\t"), - '\n' => text.push_str("\\n"), - '\r' => text.push_str("\\r"), - _ if character == quote => { - text.push('\\'); - text.push(character); - } - _ if character < ' ' || character == '\x7f' => { - text.push_str(&format!("\\x{:02x}", u32::from(character))); - } - _ => text.push(character), - } - } - text.push(quote); - Some(text) -} - /// Python's dataclass `repr` of a `ResourceIdentity`. pub(crate) fn resource_repr(identity: &ResourceIdentity) -> Option { Some(format!( diff --git a/crates/sqlbuild-scopes/src/scope_index/main/scope_lookup.rs b/crates/sqlbuild-scopes/src/scope_index/main/scope_lookup.rs index 9c96d417e2..616304228a 100644 --- a/crates/sqlbuild-scopes/src/scope_index/main/scope_lookup.rs +++ b/crates/sqlbuild-scopes/src/scope_index/main/scope_lookup.rs @@ -1,8 +1,7 @@ //! The groupings Python's `build_lookup` derives from an index and its relationship grants. use crate::scope_index::_helpers::identities::{ - declaration_repr, declaration_text, grant_through_text, python_str_repr, resource_repr, - resource_text, + declaration_repr, declaration_text, grant_through_text, resource_repr, resource_text, }; use crate::scope_index::_helpers::ordering::{keyed_groups, sorted_by_key}; use crate::scope_index::_helpers::paths::normalize_path; @@ -10,6 +9,7 @@ use crate::scope_index::_helpers::visibility::VisibilityIndex; use crate::scope_index::models::{ DeclarationIdentity, GrantRecord, ScopeDeferral, ScopeIndex, ScopeLookupGroups, }; +use sqlbuild_core::text::main::python_str_repr::python_str_repr; /// Every lookup grouping of `index` once `grants` are attached to it. pub fn scope_lookup_groups( diff --git a/crates/sqlbuild-scopes/src/scope_index/tests/test_scope_lookup.rs b/crates/sqlbuild-scopes/src/scope_index/tests/test_scope_lookup.rs index 3265fb915e..b89ccd9df8 100644 --- a/crates/sqlbuild-scopes/src/scope_index/tests/test_scope_lookup.rs +++ b/crates/sqlbuild-scopes/src/scope_index/tests/test_scope_lookup.rs @@ -1,6 +1,6 @@ -use crate::scope_index::_helpers::identities::python_str_repr; use crate::scope_index::tests::helpers::{resource_groups, visibility_texts}; use crate::scope_index::tests::test_types::{LookupTestCase, ReprTestCase}; +use sqlbuild_core::text::main::python_str_repr::python_str_repr; #[test] fn given_identity_keys_when_grouping_then_groups_follow_python_repr_order() { diff --git a/crates/sqlbuild-sqltext/src/compiler/_helpers/declaration_references/scanner.rs b/crates/sqlbuild-sqltext/src/compiler/_helpers/declaration_references/scanner.rs index 60c0747554..0e9ddbbbe3 100644 --- a/crates/sqlbuild-sqltext/src/compiler/_helpers/declaration_references/scanner.rs +++ b/crates/sqlbuild-sqltext/src/compiler/_helpers/declaration_references/scanner.rs @@ -4,21 +4,30 @@ use crate::compiler::_helpers::declaration_references::reference_syntax::{ MatchedReference, ReferenceSyntax, match_reference, }; use crate::compiler::models::{ - DeclarationReference, DeclarationReferenceScan, DeclarationReferenceStop, + DeclarationReference, DeclarationReferenceKind, DeclarationReferenceScan, + DeclarationReferenceStop, }; use sqlbuild_core::text::models::PythonText; const SPECIAL_BYTES: &[u8] = b"'\"`$@/-"; +const ENUM_KEYWORD: &str = "@enum"; +const CONSTANT_KEYWORD: &str = "@const"; /// Where the walk for the next reference start ended. enum NextStart<'sql> { Reference(usize, MatchedReference<'sql>), + /// A malformed reference start and the byte offset after its `@enum`/`@const` keyword. + Malformed(DeclarationReferenceKind, usize), End, Stop(DeclarationReferenceStop), } -/// Python's references in `sql` (code points) and its stopping error. -pub(crate) fn scan_references(python: PythonText, sql: &str) -> DeclarationReferenceScan { +/// Python's references in `sql` (code points) and stop; `skip_malformed` resumes past malformed. +pub(crate) fn scan_references( + python: PythonText, + sql: &str, + skip_malformed: bool, +) -> DeclarationReferenceScan { let mut references: Vec = Vec::new(); let mut offsets: CharOffsets = CharOffsets::default(); let mut cursor: usize = 0; @@ -27,6 +36,14 @@ pub(crate) fn scan_references(python: PythonText, sql: &str) -> DeclarationRefer let (start, matched) = match next_reference_start(python, sql, cursor) { NextStart::Reference(start, matched) => (start, matched), NextStart::End => break, + NextStart::Malformed(_, keyword_end) if skip_malformed => { + cursor = keyword_end; + continue; + } + NextStart::Malformed(kind, _) => { + stop = Some(DeclarationReferenceStop::Malformed(kind)); + break; + } NextStart::Stop(found) => { stop = Some(found); break; @@ -77,7 +94,7 @@ fn next_reference_start(python: PythonText, sql: &str, start: usize) -> NextStar ReferenceSyntax::NotReference => Some(index + 1), ReferenceSyntax::Matched(matched) => return NextStart::Reference(index, matched), ReferenceSyntax::Malformed(kind) => { - return NextStart::Stop(DeclarationReferenceStop::Malformed(kind)); + return NextStart::Malformed(kind, index + keyword_length(kind)); } }, _ => Some(index + 1), @@ -90,6 +107,13 @@ fn next_reference_start(python: PythonText, sql: &str, start: usize) -> NextStar NextStart::End } +fn keyword_length(kind: DeclarationReferenceKind) -> usize { + match kind { + DeclarationReferenceKind::Enum => ENUM_KEYWORD.len(), + DeclarationReferenceKind::Constant => CONSTANT_KEYWORD.len(), + } +} + /// Python's `quoted_text_end_impl` for `'`, `"` (doubled quotes escape) and backticks. fn quoted_end(bytes: &[u8], start: usize, doubled_escapes: bool) -> Option { let quote: u8 = bytes[start]; diff --git a/crates/sqlbuild-sqltext/src/compiler/main/declaration_references.rs b/crates/sqlbuild-sqltext/src/compiler/main/declaration_references.rs index 5e5fd1ec90..0a35f3943a 100644 --- a/crates/sqlbuild-sqltext/src/compiler/main/declaration_references.rs +++ b/crates/sqlbuild-sqltext/src/compiler/main/declaration_references.rs @@ -6,13 +6,14 @@ use crate::compiler::_helpers::declaration_references::scanner::scan_references; use crate::compiler::models::DeclarationReferenceScan; use sqlbuild_core::text::models::PythonText; -/// Each SQL string's references and stopping error, with `python`'s word boundaries. +/// Each SQL string's references and stopping error; `skip_malformed` walks past malformed starts. #[must_use] pub fn scan_declaration_references( python: PythonText, sqls: &[String], + skip_malformed: bool, ) -> Vec { sqls.par_iter() - .map(|sql| scan_references(python, sql)) + .map(|sql| scan_references(python, sql, skip_malformed)) .collect() } diff --git a/crates/sqlbuild-sqltext/src/compiler/main/mod.rs b/crates/sqlbuild-sqltext/src/compiler/main/mod.rs index f488f56683..7b066a290e 100644 --- a/crates/sqlbuild-sqltext/src/compiler/main/mod.rs +++ b/crates/sqlbuild-sqltext/src/compiler/main/mod.rs @@ -5,5 +5,6 @@ pub mod model_header_matching; pub mod model_header_parsing; pub mod model_header_single_parsing; pub mod model_header_tokenizing; +pub mod placeholder_defaults; pub mod sql_interpolation; pub mod statement_header_matching; diff --git a/crates/sqlbuild-sqltext/src/compiler/main/placeholder_defaults.rs b/crates/sqlbuild-sqltext/src/compiler/main/placeholder_defaults.rs new file mode 100644 index 0000000000..cb69cf220a --- /dev/null +++ b/crates/sqlbuild-sqltext/src/compiler/main/placeholder_defaults.rs @@ -0,0 +1,43 @@ +//! Python's `substitute_placeholder_defaults`. + +use sqlbuild_core::text::main::active_python_text::active_python_text; +use sqlbuild_core::text::main::is_python_word::is_python_word; + +use crate::constants::PLACEHOLDER_PREFIX; + +/// `substitute_placeholder_defaults`: `@@@name` becomes its default; unknown names stay. +pub fn placeholder_defaults(sql: &str, placeholders: &[(String, String)]) -> String { + let mut result: String = String::with_capacity(sql.len()); + let mut rest: &str = sql; + while let Some(start) = rest.find(PLACEHOLDER_PREFIX) { + result.push_str(&rest[..start]); + let after: &str = &rest[start + PLACEHOLDER_PREFIX.len()..]; + let length: usize = after + .find(|character: char| !is_word(character)) + .unwrap_or(after.len()); + if length == 0 { + result.push_str(&rest[start..=start]); + rest = &rest[start + 1..]; + continue; + } + let name: &str = &after[..length]; + match placeholders + .iter() + .find(|(placeholder, _)| placeholder == name) + { + Some((_, default)) => result.push_str(default), + None => { + result.push_str(PLACEHOLDER_PREFIX); + result.push_str(name); + } + } + rest = &after[length..]; + } + result.push_str(rest); + result +} + +/// A character Python's `\w` matches. +fn is_word(character: char) -> bool { + is_python_word(active_python_text(), character) +} diff --git a/crates/sqlbuild-sqltext/src/compiler/tests/helpers.rs b/crates/sqlbuild-sqltext/src/compiler/tests/helpers.rs index 8822423b6e..bc850546cf 100644 --- a/crates/sqlbuild-sqltext/src/compiler/tests/helpers.rs +++ b/crates/sqlbuild-sqltext/src/compiler/tests/helpers.rs @@ -142,7 +142,7 @@ pub(crate) fn batch_sizes_bound_workers_by_contract() -> bool { pub(crate) fn scanned_references(sql: &str) -> Option { let python = python_text((3, 12), "15.0.0").expect("Python 3.12 is supported"); let scan: DeclarationReferenceScan = - scan_declaration_references(python, &[sql.to_owned()]).pop()?; + scan_declaration_references(python, &[sql.to_owned()], false).pop()?; let references: String = scan .references .iter() diff --git a/crates/sqlbuild-sqltext/src/constants.rs b/crates/sqlbuild-sqltext/src/constants.rs index f1e65ca5bb..775734cfba 100644 --- a/crates/sqlbuild-sqltext/src/constants.rs +++ b/crates/sqlbuild-sqltext/src/constants.rs @@ -7,3 +7,5 @@ pub(crate) const OUTSIDE_KEY: &str = "outside"; pub(crate) const SQL_HOOK: &str = "sql"; pub(crate) const THRESHOLDS_KEY: &str = "thresholds"; pub(crate) const TYPE_KEY: &str = "type"; +/// The prefix that opens a SQL placeholder. +pub(crate) const PLACEHOLDER_PREFIX: &str = "@@@"; diff --git a/fensu.toml b/fensu.toml index a10fe5c399..d2a0dd91ec 100644 --- a/fensu.toml +++ b/fensu.toml @@ -280,6 +280,16 @@ rule = "FPRSS201" path = "crates/sqlbuild-python/src/bindings/models.rs" reason = "CompactAnalysisJob holds a prepared analysis closure, which cannot implement Debug; other models derive it." +[[targets.rust.rule_exceptions]] +rule = "FPRSS130" +path = "crates/sqlbuild-core/src/text/_helpers/active_text.rs" +reason = "One interpreter per process: the extension module records the running Python's string semantics once at import, and every native text helper reads that single value." + +[[targets.rust.rule_exceptions]] +rule = "FPRSS201" +path = "crates/sqlbuild-analysis/src/assembly/analysis_session/models.rs" +reason = "NullabilityCallback implements Debug manually because it holds the adapter's nullability rule closure, which cannot implement Debug; other models derive it." + [[targets.rust.rule_exceptions]] rule = "FPRSL105" path = "crates/sqlbuild-analysis/src/sql_tokens/main/builtin_function_names.rs" diff --git a/scripts/compiler_differential/README.md b/scripts/compiler_differential/README.md index 2fd6b71f2b..4acdbf9eba 100644 --- a/scripts/compiler_differential/README.md +++ b/scripts/compiler_differential/README.md @@ -1,13 +1,13 @@ # Compiler differential `make compiler-differential` compiles fixtures, examples, generated seeds and the failure corpus -under two compiler engines and fails on the first differing artifact. `make -compiler-differential-shipped` does the same for the shipped `native` default. Both also enforce -the shared gates below. +under the shipped `native` engine and `native-preview` and fails on the first differing artifact. +It also enforces the shared gates below. The goldens are the oracle for output that both engines +share: the Python compiler they once compared against has been removed. For ad hoc runs (one project, other seeds, other engines), call the script directly, for example -`uv run python -m scripts.run_compiler_differential --corpus --project --engines python -native`. The make targets fix the corpus the allow-list and goldens are recorded for. +`uv run python -m scripts.run_compiler_differential --corpus --project --engines native +native-preview`. The make targets fix the corpus the allow-list and goldens are recorded for. ## Shared gates for native ports @@ -22,40 +22,38 @@ and of the work each native stage answers itself. It covers three kinds of recor path where a native stage hands work to Python, or runs Python with no native path yet; - analysis-stage deferrals: every `analysis-deferrals-*.jsonl` record (analysis session, lineage, semantic checks, contracts); -- native answers, from `report_native_answer(stage=NativeStage., kind=...)` where a - stage's native path produced the result: files, models, scans or calls. Their site is - `.native`. +- native answers, from `report_native_answer(stage=NativeStage., kind=...)` + (`frontier/main/_report_native_answer.py`) where a preview stage's native path produced the + result: files, models, scans or calls. Their site is `.native`. No stage is in preview + today, so the list holds no answer entries. Counting only fallbacks cannot tell a stage that answers natively from one that no longer runs -natively at all. The answer counts can: if a stage is switched to Python, its `.native` -entries vanish and the gate says so. +natively at all. The answer counts can: if a preview stage is switched off, its `.native` +entries vanish and the gate says so. A stage leaves `NativeStage`, and drops its answer counts, +once the Python engine it switched against is deleted. Every entry names an engine, stage, site and kind, with its exact count per corpus. Use `max_counts` instead of `counts` only for a count that is not stable, and give the reason in a comment and in the PR body. The records cost nothing unless `SQLBUILD_ANALYSIS_RECORD_DIR` is set, which only the harness -sets. `--native-fallbacks check` runs in both make targets and fails CI in both directions: +sets. `--native-fallbacks check` runs in the make target and fails CI in both directions: - an entry, engine or corpus count that is not on the list fails; - a listed entry whose count changed or that no longer occurs also fails, and the message says to update or remove it, so the fallback list only shrinks; - a vanished native answer fails as work that now runs in Python; - a listed fallback that vanished is refused outright, with "fallback disappeared but native answers did not appear; the stage may be switched off", unless the same engine, stage and - corpus report more `.native` answers than the list records. A stage with only fallback - entries (`sql_test_glue`, `project_assembly`) would otherwise look like a finished port when it - is switched off. + corpus report more `.native` answers than the list records. This applies only to stages + that are still `NativeStage` members, which the engine can switch off; a stage with only + fallback entries would otherwise look like a finished port when it is switched off. Shipped + stages that left `NativeStage` cannot be switched off, so their fallbacks may simply vanish. -The counts hold for the make targets' corpus (`--seeds 12`); other seed ranges are refused. +The counts hold for the make target's corpus (`--seeds 12`); other seed ranges are refused. -Two stages the list cannot watch: -- `type_system`: the compile corpus never reaches type normalization. Its callers are the planner - and executor and the analysis stages' Python fallbacks. `tests/integration/.../type_system/ - test_native_type_parity.py` proves instead that the public `normalize_type` asks native first - under `native` and `native-preview`. -- `discovery.native model_file_listings`: it is reported unconditionally inside the native model - file discovery, which has no fallback to Python, so this count cannot detect anything. It stays - only as a record that native discovery ran. +The compile corpus never reaches type normalization (its callers are the planner, the executor +and the analysis stages' Python fallbacks), so `tests/integration/.../type_system/ +test_native_type_parity.py` covers that its public `normalize_type` asks native first. **How a PR updates the list and the goldens** @@ -65,13 +63,13 @@ One command rewrites both from the current tree: make compiler-baselines ``` -It deletes `tests/goldens/compiler`, then runs the two CI differentials with `--native-fallbacks +It deletes `tests/goldens/compiler`, then runs the CI differential with `--native-fallbacks update --goldens update`. Commit the resulting `native_fallbacks.toml` and `tests/goldens/` diff in the same PR as the change that caused it. - A port deletes the Python code it replaces in the same PR. Its fallback entries then disappear - from the list, and that removal is the port's test that the fallbacks are gone. Its answer - counts usually rise. When the last entry for a `NativeFallbackSite` goes, delete the member + from the list, and that removal is the port's test that the fallbacks are gone. A preview + stage's answer counts usually rise. When the last entry for a `NativeFallbackSite` goes, delete the member and its `report_native_fallback` call too. - If the corpus does not reach a site yet, first add a failure case or seed feature that does. - A PR that merges after a list or golden change on main reruns `make compiler-baselines` after @@ -89,7 +87,7 @@ in the same PR as the change that caused it. same diff: the port must report the work it now answers. A fallback that vanished with no new answers is a stage switched off, not a port; the gate refuses it. - Code: every new path that hands work to Python calls `report_native_fallback`, and every new - native path calls `report_native_answer` where its result is used. + preview-stage native path calls `report_native_answer` where its result is used. - Goldens: - Every changed golden is an intended output change, named in the PR body. - An output-neutral port changes no golden. @@ -112,9 +110,9 @@ masked. Goldens hold outputs only, not stage captures: a seed's captures are about 690 KB, too large to review. Cache facts are covered by the incremental-versus-no-cache tests instead. -- `--goldens check` (in both make targets) compares every engine with the goldens, so an +- `--goldens check` (in the make target) compares every engine with the goldens, so an output-neutral port needs no new parity suite. -- `make compiler-baselines` rewrites them from the python oracle. Run it only when output +- `make compiler-baselines` rewrites them from the `native` oracle. Run it only when output changes on purpose, and review the diff like code. - `tests/goldens/compiler/seed_range.toml` records the seed range the goldens were written for. Every seed in that range, and every fixture, example and failure case, must have a golden. @@ -123,15 +121,14 @@ review. Cache facts are covered by the incremental-versus-no-cache tests instead - Dialect variants (`-postgres`, `-snowflake`) are generated for the first seed of a run only, so a golden is required only for the variants of the recorded `seed_start`. An ad hoc `--seed-start N` run checks its base seeds in the range and skips its variants. -- Once the Python stages are deleted, goldens are rewritten from `native`. ### All-engine user-facing errors `engine_error_cases()` in `_helpers/corpus/failure_cases.py` lists user-facing errors with their -exact text. Each case is part of the failure corpus, so it runs in both differentials and has a +exact text. Each case is part of the failure corpus, so it runs in the differential and has a golden. It also runs in -`tests/e2e/scripts/compiler_differential/test_engine_error_cases.py` on the `python`, `native` -and `native-preview` engines, which must all report its `expected_code` and `expected_message`. +`tests/e2e/scripts/compiler_differential/test_engine_error_cases.py` on the `native` and +`native-preview` engines, which must both report its `expected_code` and `expected_message`. A port that adds or changes a user-facing error adds one `failure_case(...)` to it: diff --git a/scripts/compiler_differential/_helpers/corpus/emitted_codes.py b/scripts/compiler_differential/_helpers/corpus/emitted_codes.py index 4bfc505a39..b51f3e970a 100644 --- a/scripts/compiler_differential/_helpers/corpus/emitted_codes.py +++ b/scripts/compiler_differential/_helpers/corpus/emitted_codes.py @@ -16,12 +16,14 @@ from scripts.compiler_differential._helpers.running.execution import run_engine from scripts.compiler_differential.constants import ( ANALYSIS_CODE_SCAN_ROOTS, + ANALYSIS_NATIVE_CODE_SCAN_ROOTS, COLD_COMPILE, CORPUS_FAILURES, DIAGNOSTIC_CODE_PATTERN, ERROR_SEVERITY, EXPECT_SUCCESS, LEFT_SIDE, + NATIVE_CODE_CONSTANT_PATTERN, RENDER_CODE_SCAN_EXCLUDED, RENDER_RAISED_CODES, WARNING_SEVERITY, @@ -113,13 +115,17 @@ def render_error_codes() -> frozenset[str]: def analysis_error_codes(compiler_root: Path) -> frozenset[str]: - """Return the help-catalogue codes plus every code literal in the analysis-stage modules.""" + """Return the help-catalogue codes plus every code in the analysis-stage modules and crates.""" found: set[str] = set(semantic_help_catalogue()) for root in ANALYSIS_CODE_SCAN_ROOTS: path: Path = compiler_root / root for module in sorted(path.rglob("*.py")) if path.is_dir() else (path,): found.update(_module_codes(module)) + repo_root: Path = compiler_root.parents[2] + for native_module in ANALYSIS_NATIVE_CODE_SCAN_ROOTS: + text: str = (repo_root / native_module).read_text(encoding="utf-8") + found.update(NATIVE_CODE_CONSTANT_PATTERN.findall(text)) return frozenset(found) diff --git a/scripts/compiler_differential/_helpers/running/native_fallbacks.py b/scripts/compiler_differential/_helpers/running/native_fallbacks.py index b9d50c366f..625c5ed66f 100644 --- a/scripts/compiler_differential/_helpers/running/native_fallbacks.py +++ b/scripts/compiler_differential/_helpers/running/native_fallbacks.py @@ -25,6 +25,7 @@ RecordedRun, ) from scripts.compiler_differential.types import FallbackKey +from sqlbuild.compiler.frontier.types import NativeStage def native_fallback_gate( @@ -118,6 +119,7 @@ def fallback_problems( allowed_answers: Counter[tuple[str, str, str]] = _answer_totals( {**allowed.counts, **allowed.max_counts} ) + switchable_stages: frozenset[str] = frozenset(stage.value for stage in NativeStage) problems: list[str] = [] for key in sorted({*allowed.counts, *allowed.max_counts, *observed}): if key[0] not in run.engines: @@ -134,6 +136,7 @@ def fallback_problems( bound=None if bound is None else bound.get(corpus, 0), answers_rose=observed_answers[(key[0], key[1], corpus)] > allowed_answers[(key[0], key[1], corpus)], + switchable=key[1] in switchable_stages, ) if problem is not None: problems.append(problem) @@ -196,6 +199,7 @@ def _corpus_problem( exact: int | None, bound: int | None, answers_rose: bool, + switchable: bool, ) -> str | None: if answer and exact is None and bound is None: return f"{label}: native answered {actual}, not on the allow-list; record it" @@ -206,7 +210,7 @@ def _corpus_problem( ) if exact is None and bound is None: return f"{label}: {actual} not on the allow-list; port it or list it with a reason" - if actual == 0 and not answers_rose: + if actual == 0 and switchable and not answers_rose: return ( f"{label}: fallback disappeared but native answers did not appear; the stage may be " "switched off. A port that removes a fallback must report native answers for the " diff --git a/scripts/compiler_differential/constants.py b/scripts/compiler_differential/constants.py index e78925f6af..80a567e030 100644 --- a/scripts/compiler_differential/constants.py +++ b/scripts/compiler_differential/constants.py @@ -26,12 +26,7 @@ NATIVE_FALLBACK_PROJECT_CORPUS: str = "project" NATIVE_FALLBACK_DEFERRAL_STAGES: dict[str, str] = { "analysis_session": "model_analysis", - "fast_columns.py": "lineage_facts", - "type_recovery.py": "semantic_checks", - "recovery.py": "semantic_checks", - "metadata_validation.py": "semantic_checks", "contracts/columns.py": "contracts", - "contracts/promotion.py": "contracts", } NATIVE_FALLBACK_DEFERRAL_UNKNOWN_STAGE: str = "analysis" NATIVE_FALLBACK_LIST_HEADER: str = ( @@ -62,8 +57,8 @@ GOLDEN_WORK_MASK: str = "" GOLDEN_VERSION_MASK: str = "" GOLDEN_MISSING_HINT: str = "no golden; record it with `make compiler-baselines`" -ENGINE_NAMES: tuple[str, ...] = ("python", "native", "native-preview") -DEFAULT_ENGINES: tuple[str, str] = ("python", "native-preview") +ENGINE_NAMES: tuple[str, ...] = ("native", "native-preview") +DEFAULT_ENGINES: tuple[str, str] = ("native", "native-preview") SQB_ENTRY: str = "import sys; from sqlbuild.cli.entry.main.entry import main; sys.exit(main())" EXCLUDED_ENVIRONMENT_KEYS: frozenset[str] = frozenset( {"VIRTUAL_ENV", ENGINE_ENV_VAR, STAGE_CAPTURE_ENV_VAR, ANALYSIS_RECORD_ENV_VAR} @@ -690,6 +685,12 @@ def short_model_names(*, model: Model, ctx: RuleContext) -> list[Finding]: "pipeline/_helpers/target_validation.py", "sql_analysis", ) +ANALYSIS_NATIVE_CODE_SCAN_ROOTS: tuple[str, ...] = ( + "crates/sqlbuild-analysis/src/contracts/constants.rs", +) +NATIVE_CODE_CONSTANT_PATTERN: re.Pattern[str] = re.compile( + r'const [A-Z0-9_]*_CODE: &str = "([A-Z][0-9]{3})";' +) _NEVER_REPORTED_BY_POLYGLOT: str = ( "polyglot defines the finding but never reports it, and no SQLBuild check maps to it" ) diff --git a/scripts/compiler_differential/main/differential.py b/scripts/compiler_differential/main/differential.py index 2ac8f10ce0..1b3fee8a07 100644 --- a/scripts/compiler_differential/main/differential.py +++ b/scripts/compiler_differential/main/differential.py @@ -153,8 +153,8 @@ def _parse_args(argv: list[str] | None) -> argparse.Namespace: default=list(DEFAULT_ENGINES), metavar="ENGINE", help=( - "oracle and candidate engines (default: python native-preview, every native stage; " - "pass python native to cover only the shipped native stages)" + "oracle and candidate engines (default: native native-preview, the shipped default " + "against every preview stage)" ), ) parser.add_argument("--jobs", type=int, default=os.cpu_count() or 1) diff --git a/scripts/compiler_differential/native_fallbacks.toml b/scripts/compiler_differential/native_fallbacks.toml index dcab198a7f..408b883a8a 100644 --- a/scripts/compiler_differential/native_fallbacks.toml +++ b/scripts/compiler_differential/native_fallbacks.toml @@ -6,139 +6,6 @@ seed_start = 0 seeds = 12 -[[entry]] -engine = "native" -stage = "analysis" -site = "project_assembly" -kind = "syntax_error" -counts = { failure = 3 } - -[[entry]] -engine = "native" -stage = "analysis" -site = "project_assembly" -kind = "unsupported_dialect" -counts = { failure = 1 } - -[[entry]] -engine = "native" -stage = "analysis" -site = "sql_test_assembly" -kind = "macro_mocks" -counts = { seed = 29 } - -[[entry]] -engine = "native" -stage = "attachments" -site = "attachments.native" -kind = "audit_renderings" -counts = { example = 120, failure = 10, fixture = 112, seed = 370 } - -[[entry]] -engine = "native" -stage = "attachments" -site = "attachments.native" -kind = "cursor_intrinsic_rejections" -counts = { example = 160, failure = 179, fixture = 156, seed = 961 } - -[[entry]] -engine = "native" -stage = "attachments" -site = "attachments.native" -kind = "function_headers" -counts = { example = 8, failure = 13, fixture = 12, seed = 102 } - -[[entry]] -engine = "native" -stage = "attachments" -site = "attachments.native" -kind = "omitted_select_scans" -counts = { example = 24, failure = 22, fixture = 32, seed = 193 } - -[[entry]] -engine = "native" -stage = "attachments" -site = "attachments.native" -kind = "scenario_ctes" -counts = { example = 8, failure = 7, fixture = 12, seed = 37 } - -[[entry]] -engine = "native" -stage = "attachments" -site = "attachments.native" -kind = "seed_pairs" -counts = { example = 8, fixture = 4, seed = 26 } - -[[entry]] -engine = "native" -stage = "contracts" -site = "contracts.native" -kind = "contract_validations" -counts = { example = 9, failure = 113, fixture = 6, seed = 25 } - -[[entry]] -engine = "native" -stage = "contracts" -site = "contracts.native" -kind = "promotion_checks" -counts = { example = 12, failure = 113, fixture = 8, seed = 33 } - -[[entry]] -engine = "native" -stage = "declaration_files" -site = "declaration_files.native" -kind = "failed_files" -counts = { failure = 10 } - -[[entry]] -engine = "native" -stage = "declaration_files" -site = "declaration_files.native" -kind = "parsed_files" -counts = { example = 32, failure = 83, fixture = 20, seed = 799 } - -[[entry]] -engine = "native" -stage = "declaration_files" -site = "declaration_files.native" -kind = "seed_files" -counts = { example = 8, failure = 3, fixture = 4, seed = 43 } - -[[entry]] -engine = "native" -stage = "declaration_scopes" -site = "declaration_scopes.native" -kind = "relationship_scans" -counts = { example = 15, failure = 6, fixture = 18, seed = 130 } - -[[entry]] -engine = "native" -stage = "declaration_scopes" -site = "declaration_scopes.native" -kind = "scope_indexes" -counts = { example = 12, failure = 258, fixture = 12, seed = 44 } - -[[entry]] -engine = "native" -stage = "discovery" -site = "discovery.native" -kind = "model_file_listings" -counts = { example = 12, failure = 326, fixture = 12, seed = 50 } - -[[entry]] -engine = "native" -stage = "lineage_facts" -site = "lineage_facts.native" -kind = "lineage_graphs" -counts = { example = 9, failure = 113, fixture = 6, seed = 22 } - -[[entry]] -engine = "native" -stage = "macro_call_store" -site = "macro_call_store.native" -kind = "served_calls" -counts = { example = 18, fixture = 15, seed = 192 } - [[entry]] engine = "native" stage = "macro_calls" @@ -146,293 +13,13 @@ site = "macro_calls.mocked_evaluation" kind = "test_mock" counts = { seed = 29 } -[[entry]] -engine = "native" -stage = "macro_calls" -site = "macro_calls.native" -kind = "bridged_calls" -counts = { example = 32, failure = 9, fixture = 28, seed = 719 } - -[[entry]] -engine = "native" -stage = "macro_calls" -site = "macro_calls.native" -kind = "parsed_arguments" -counts = { example = 6, failure = 16, fixture = 5, seed = 369 } - -[[entry]] -engine = "native" -stage = "macro_calls" -site = "macro_calls.resolution" -kind = "deferred" -counts = { failure = 4, seed = 3 } - -[[entry]] -engine = "native" -stage = "model_analysis" -site = "model_analysis.native" -kind = "dynamic_contract_proofs" -counts = { seed = 3 } - -[[entry]] -engine = "native" -stage = "model_analysis" -site = "model_analysis.native" -kind = "expression_shapes" -counts = { example = 4, failure = 119, fixture = 4, seed = 100 } - -[[entry]] -engine = "native" -stage = "model_analysis" -site = "model_analysis.native" -kind = "model_analyses" -counts = { example = 56, failure = 232, fixture = 52, seed = 698 } - -[[entry]] -engine = "native" -stage = "model_config" -site = "model_config.native" -kind = "config_builds" -counts = { example = 56, failure = 347, fixture = 64, seed = 914 } - -[[entry]] -engine = "native" -stage = "model_config" -site = "model_config.native" -kind = "effective_vars" -counts = { example = 29, failure = 273, fixture = 15, seed = 121 } - -[[entry]] -engine = "native" -stage = "model_config" -site = "model_config.native" -kind = "header_metadata_parses" -counts = { example = 56, failure = 402, fixture = 60, seed = 1116 } - -[[entry]] -engine = "native" -stage = "model_config" -site = "model_config.native" -kind = "template_expansions" -counts = { example = 214, failure = 1657, fixture = 333, seed = 1471 } - -[[entry]] -engine = "native" -stage = "model_config" -site = "model_config.native" -kind = "validations" -counts = { example = 56, failure = 441, fixture = 64, seed = 1124 } - -[[entry]] -engine = "native" -stage = "model_loop" -site = "model_loop.native" -kind = "cursor_intrinsic_validations" -counts = { example = 56, failure = 448, fixture = 64, seed = 1926 } - -[[entry]] -engine = "native" -stage = "model_loop" -site = "model_loop.native" -kind = "declaration_contexts" -counts = { example = 64, failure = 136, fixture = 60, seed = 964 } - -[[entry]] -engine = "native" -stage = "model_loop" -site = "model_loop.native" -kind = "declaration_expansions" -counts = { example = 56, failure = 468, fixture = 64, seed = 1127 } - -[[entry]] -engine = "native" -stage = "model_loop" -site = "model_loop.native" -kind = "variable_substitutions" -counts = { example = 56, failure = 522, fixture = 72, seed = 1187 } - -[[entry]] -engine = "native" -stage = "project_assembly" -site = "project_assembly.assembly" -kind = "deferred" -counts = { failure = 4 } - -[[entry]] -engine = "native" -stage = "project_assembly" -site = "project_assembly.native" -kind = "project_assemblies" -counts = { example = 12, failure = 115, fixture = 8, seed = 36 } - -[[entry]] -engine = "native" -stage = "reference_extraction" -site = "reference_extraction.native" -kind = "reference_scans" -counts = { example = 250, failure = 512, fixture = 249, seed = 1532 } - -[[entry]] -engine = "native" -stage = "semantic_checks" -site = "semantic_checks.native" -kind = "semantic_completions" -counts = { example = 12, failure = 115, fixture = 8, seed = 36 } - -[[entry]] -engine = "native" -stage = "sql_test_glue" -site = "sql_test_glue.assembly" -kind = "deferred" -counts = { seed = 29 } - -[[entry]] -engine = "native" -stage = "sql_test_glue" -site = "sql_test_glue.native" -kind = "sql_test_assemblies" -counts = { example = 16, failure = 7, fixture = 20, seed = 143 } - [[entry]] engine = "native" stage = "sql_test_glue" -site = "sql_test_glue.native" -kind = "sql_test_plans" -counts = { example = 1, failure = 5, fixture = 1, seed = 9 } - -[[entry]] -engine = "native-preview" -stage = "analysis" -site = "project_assembly" -kind = "syntax_error" -counts = { failure = 3 } - -[[entry]] -engine = "native-preview" -stage = "analysis" -site = "project_assembly" -kind = "unsupported_dialect" -counts = { failure = 1 } - -[[entry]] -engine = "native-preview" -stage = "analysis" -site = "sql_test_assembly" -kind = "macro_mocks" +site = "sql_test_glue.macro_mock_queries" +kind = "extension_callback" counts = { seed = 29 } -[[entry]] -engine = "native-preview" -stage = "attachments" -site = "attachments.native" -kind = "audit_renderings" -counts = { example = 120, failure = 10, fixture = 112, seed = 370 } - -[[entry]] -engine = "native-preview" -stage = "attachments" -site = "attachments.native" -kind = "cursor_intrinsic_rejections" -counts = { example = 160, failure = 179, fixture = 156, seed = 961 } - -[[entry]] -engine = "native-preview" -stage = "attachments" -site = "attachments.native" -kind = "function_headers" -counts = { example = 8, failure = 13, fixture = 12, seed = 102 } - -[[entry]] -engine = "native-preview" -stage = "attachments" -site = "attachments.native" -kind = "omitted_select_scans" -counts = { example = 24, failure = 22, fixture = 32, seed = 193 } - -[[entry]] -engine = "native-preview" -stage = "attachments" -site = "attachments.native" -kind = "scenario_ctes" -counts = { example = 8, failure = 7, fixture = 12, seed = 37 } - -[[entry]] -engine = "native-preview" -stage = "attachments" -site = "attachments.native" -kind = "seed_pairs" -counts = { example = 8, fixture = 4, seed = 26 } - -[[entry]] -engine = "native-preview" -stage = "contracts" -site = "contracts.native" -kind = "contract_validations" -counts = { example = 9, failure = 113, fixture = 6, seed = 25 } - -[[entry]] -engine = "native-preview" -stage = "contracts" -site = "contracts.native" -kind = "promotion_checks" -counts = { example = 12, failure = 113, fixture = 8, seed = 33 } - -[[entry]] -engine = "native-preview" -stage = "declaration_files" -site = "declaration_files.native" -kind = "failed_files" -counts = { failure = 10 } - -[[entry]] -engine = "native-preview" -stage = "declaration_files" -site = "declaration_files.native" -kind = "parsed_files" -counts = { example = 32, failure = 83, fixture = 20, seed = 799 } - -[[entry]] -engine = "native-preview" -stage = "declaration_files" -site = "declaration_files.native" -kind = "seed_files" -counts = { example = 8, failure = 3, fixture = 4, seed = 43 } - -[[entry]] -engine = "native-preview" -stage = "declaration_scopes" -site = "declaration_scopes.native" -kind = "relationship_scans" -counts = { example = 15, failure = 6, fixture = 18, seed = 130 } - -[[entry]] -engine = "native-preview" -stage = "declaration_scopes" -site = "declaration_scopes.native" -kind = "scope_indexes" -counts = { example = 12, failure = 258, fixture = 12, seed = 44 } - -[[entry]] -engine = "native-preview" -stage = "discovery" -site = "discovery.native" -kind = "model_file_listings" -counts = { example = 12, failure = 326, fixture = 12, seed = 50 } - -[[entry]] -engine = "native-preview" -stage = "lineage_facts" -site = "lineage_facts.native" -kind = "lineage_graphs" -counts = { example = 9, failure = 113, fixture = 6, seed = 22 } - -[[entry]] -engine = "native-preview" -stage = "macro_call_store" -site = "macro_call_store.native" -kind = "served_calls" -counts = { example = 18, fixture = 15, seed = 192 } - [[entry]] engine = "native-preview" stage = "macro_calls" @@ -440,160 +27,13 @@ site = "macro_calls.mocked_evaluation" kind = "test_mock" counts = { seed = 29 } -[[entry]] -engine = "native-preview" -stage = "macro_calls" -site = "macro_calls.native" -kind = "bridged_calls" -counts = { example = 32, failure = 9, fixture = 28, seed = 719 } - -[[entry]] -engine = "native-preview" -stage = "macro_calls" -site = "macro_calls.native" -kind = "parsed_arguments" -counts = { example = 6, failure = 16, fixture = 5, seed = 369 } - -[[entry]] -engine = "native-preview" -stage = "macro_calls" -site = "macro_calls.resolution" -kind = "deferred" -counts = { failure = 4, seed = 3 } - -[[entry]] -engine = "native-preview" -stage = "model_analysis" -site = "model_analysis.native" -kind = "dynamic_contract_proofs" -counts = { seed = 3 } - -[[entry]] -engine = "native-preview" -stage = "model_analysis" -site = "model_analysis.native" -kind = "expression_shapes" -counts = { example = 4, failure = 119, fixture = 4, seed = 100 } - -[[entry]] -engine = "native-preview" -stage = "model_analysis" -site = "model_analysis.native" -kind = "model_analyses" -counts = { example = 56, failure = 232, fixture = 52, seed = 698 } - -[[entry]] -engine = "native-preview" -stage = "model_config" -site = "model_config.native" -kind = "config_builds" -counts = { example = 56, failure = 347, fixture = 64, seed = 914 } - -[[entry]] -engine = "native-preview" -stage = "model_config" -site = "model_config.native" -kind = "effective_vars" -counts = { example = 29, failure = 273, fixture = 15, seed = 121 } - -[[entry]] -engine = "native-preview" -stage = "model_config" -site = "model_config.native" -kind = "header_metadata_parses" -counts = { example = 56, failure = 402, fixture = 60, seed = 1116 } - -[[entry]] -engine = "native-preview" -stage = "model_config" -site = "model_config.native" -kind = "template_expansions" -counts = { example = 214, failure = 1657, fixture = 333, seed = 1471 } - -[[entry]] -engine = "native-preview" -stage = "model_config" -site = "model_config.native" -kind = "validations" -counts = { example = 56, failure = 441, fixture = 64, seed = 1124 } - -[[entry]] -engine = "native-preview" -stage = "model_loop" -site = "model_loop.native" -kind = "cursor_intrinsic_validations" -counts = { example = 56, failure = 448, fixture = 64, seed = 1926 } - -[[entry]] -engine = "native-preview" -stage = "model_loop" -site = "model_loop.native" -kind = "declaration_contexts" -counts = { example = 64, failure = 136, fixture = 60, seed = 964 } - -[[entry]] -engine = "native-preview" -stage = "model_loop" -site = "model_loop.native" -kind = "declaration_expansions" -counts = { example = 56, failure = 468, fixture = 64, seed = 1127 } - -[[entry]] -engine = "native-preview" -stage = "model_loop" -site = "model_loop.native" -kind = "variable_substitutions" -counts = { example = 56, failure = 522, fixture = 72, seed = 1187 } - -[[entry]] -engine = "native-preview" -stage = "project_assembly" -site = "project_assembly.assembly" -kind = "deferred" -counts = { failure = 4 } - -[[entry]] -engine = "native-preview" -stage = "project_assembly" -site = "project_assembly.native" -kind = "project_assemblies" -counts = { example = 12, failure = 115, fixture = 8, seed = 36 } - -[[entry]] -engine = "native-preview" -stage = "reference_extraction" -site = "reference_extraction.native" -kind = "reference_scans" -counts = { example = 250, failure = 512, fixture = 249, seed = 1532 } - -[[entry]] -engine = "native-preview" -stage = "semantic_checks" -site = "semantic_checks.native" -kind = "semantic_completions" -counts = { example = 12, failure = 115, fixture = 8, seed = 36 } - [[entry]] engine = "native-preview" stage = "sql_test_glue" -site = "sql_test_glue.assembly" -kind = "deferred" +site = "sql_test_glue.macro_mock_queries" +kind = "extension_callback" counts = { seed = 29 } -[[entry]] -engine = "native-preview" -stage = "sql_test_glue" -site = "sql_test_glue.native" -kind = "sql_test_assemblies" -counts = { example = 16, failure = 7, fixture = 20, seed = 143 } - -[[entry]] -engine = "native-preview" -stage = "sql_test_glue" -site = "sql_test_glue.native" -kind = "sql_test_plans" -counts = { example = 1, failure = 5, fixture = 1, seed = 9 } - [[entry]] engine = "python" stage = "attachments" diff --git a/scripts/python_char_table/_helpers/table.py b/scripts/python_char_table/_helpers/table.py index 43802eda6b..e9049857f9 100644 --- a/scripts/python_char_table/_helpers/table.py +++ b/scripts/python_char_table/_helpers/table.py @@ -1,12 +1,16 @@ -"""Range computation and Rust rendering of Python's `str.isalnum()` and `str.isalpha()` tables.""" +"""Range and mapping computation, and Rust rendering, of Python's `str` character tables.""" from __future__ import annotations +import importlib import unicodedata from pathlib import Path +from typing import Any from scripts.python_char_table.constants import ( + IGNORECASE_KEY_TABLE, MAX_CODE_POINT, + SURROGATE_RANGE, TABLE_FILE_PREFIX, TABLE_FILE_SUFFIX, TABLE_ROOT, @@ -21,6 +25,80 @@ def table_path(*, method: str) -> Path: return directory / f"{TABLE_FILE_PREFIX}{version}{TABLE_FILE_SUFFIX}" +def mapping_path(*, method: str) -> Path: + """Return the Rust file holding one case mapping for the running Python's Unicode version.""" + + version: str = unicodedata.unidata_version.replace(".", "_") + return TABLE_ROOT / f"{method}_mappings" / f"{TABLE_FILE_PREFIX}{version}{TABLE_FILE_SUFFIX}" + + +def character_mappings(*, method: str) -> list[tuple[int, str]]: + """Return every character the `str` method changes, with what it becomes, in order.""" + + mappings: list[tuple[int, str]] = [] + for code_point in range(MAX_CODE_POINT + 1): + if code_point in SURROGATE_RANGE: + continue + character: str = chr(code_point) + mapped: str = getattr(character, method)() + if mapped != character: + mappings.append((code_point, mapped)) + return mappings + + +def render_mapping(*, method: str, mappings: list[tuple[int, str]]) -> str: + """Render the Rust expression of one case mapping table, which `case_tables.rs` includes.""" + + lines: list[str] = [ + "// Generated by `scripts/generate_python_char_table.py`; do not edit.", + f"// Every character `str.{method}()` changes in Unicode {unicodedata.unidata_version}, " + "in code point order.", + "&[", + ] + lines.extend( + f' (0x{code_point:04X}, "{_rust_escaped(mapped)}"),' for code_point, mapped in mappings + ) + lines.append("]") + return "\n".join(lines) + "\n" + + +def ignorecase_key_path() -> Path: + """Return the Rust file holding `re.IGNORECASE` match keys for this Unicode version.""" + + version: str = unicodedata.unidata_version.replace(".", "_") + return TABLE_ROOT / IGNORECASE_KEY_TABLE / f"{TABLE_FILE_PREFIX}{version}{TABLE_FILE_SUFFIX}" + + +def ignorecase_keys() -> list[tuple[int, int]]: + """Return each character whose `re.IGNORECASE` key (least `_sre` lower/casefix) differs.""" + + sre: Any = importlib.import_module("_sre") + extra: dict[int, tuple[int, ...]] = importlib.import_module("re._casefix")._EXTRA_CASES # noqa: SLF001 + keys: list[tuple[int, int]] = [] + for code_point in range(MAX_CODE_POINT + 1): + if code_point in SURROGATE_RANGE: + continue + lower: int = sre.unicode_tolower(code_point) + key: int = min((lower, *extra.get(lower, ()))) + if key != code_point: + keys.append((code_point, key)) + return keys + + +def render_ignorecase_keys(keys: list[tuple[int, int]]) -> str: + """Render the Rust expression of the `re.IGNORECASE` key table `case_tables.rs` includes.""" + + lines: list[str] = [ + "// Generated by `scripts/generate_python_char_table.py`; do not edit.", + "// Every character whose `re.IGNORECASE` match key is not itself in Unicode " + f"{unicodedata.unidata_version}, in code point order.", + "&[", + ] + lines.extend(f" (0x{code_point:04X}, 0x{key:04X})," for code_point, key in keys) + lines.append("]") + return "\n".join(lines) + "\n" + + def character_ranges(*, method: str) -> list[tuple[int, int]]: """Return the inclusive code point ranges where the `str` method is true.""" @@ -50,3 +128,7 @@ def render_table(*, method: str, ranges: list[tuple[int, int]]) -> str: lines.extend(f" (0x{start:04X}, 0x{end:04X})," for start, end in ranges) lines.append("]") return "\n".join(lines) + "\n" + + +def _rust_escaped(text: str) -> str: + return "".join(f"\\u{{{ord(character):x}}}" for character in text) diff --git a/scripts/python_char_table/constants.py b/scripts/python_char_table/constants.py index 84818e990a..95bc78d53a 100644 --- a/scripts/python_char_table/constants.py +++ b/scripts/python_char_table/constants.py @@ -7,3 +7,6 @@ TABLE_FILE_SUFFIX: str = ".in" MAX_CODE_POINT: int = 0x10FFFF TABLE_METHODS: tuple[str, ...] = ("isalnum", "isalpha", "isdecimal") +MAPPING_METHODS: tuple[str, ...] = ("casefold", "upper") +IGNORECASE_KEY_TABLE: str = "re_ignorecase_keys" +SURROGATE_RANGE: range = range(0xD800, 0xE000) diff --git a/scripts/python_char_table/main/generate.py b/scripts/python_char_table/main/generate.py index 41a0e34a00..6587f29c29 100644 --- a/scripts/python_char_table/main/generate.py +++ b/scripts/python_char_table/main/generate.py @@ -6,8 +6,18 @@ import unicodedata from pathlib import Path -from scripts.python_char_table._helpers.table import character_ranges, render_table, table_path -from scripts.python_char_table.constants import TABLE_METHODS +from scripts.python_char_table._helpers.table import ( + character_mappings, + character_ranges, + ignorecase_key_path, + ignorecase_keys, + mapping_path, + render_ignorecase_keys, + render_mapping, + render_table, + table_path, +) +from scripts.python_char_table.constants import MAPPING_METHODS, TABLE_METHODS def generate_python_char_table() -> int: @@ -20,4 +30,16 @@ def generate_python_char_table() -> int: render_table(method=method, ranges=character_ranges(method=method)), encoding="utf-8" ) print(f"wrote {path} (Unicode {unicodedata.unidata_version})", file=sys.stderr) + for method in MAPPING_METHODS: + path = mapping_path(method=method) + path.parent.mkdir(parents=True, exist_ok=True) + _ = path.write_text( + render_mapping(method=method, mappings=character_mappings(method=method)), + encoding="utf-8", + ) + print(f"wrote {path} (Unicode {unicodedata.unidata_version})", file=sys.stderr) + path = ignorecase_key_path() + path.parent.mkdir(parents=True, exist_ok=True) + _ = path.write_text(render_ignorecase_keys(ignorecase_keys()), encoding="utf-8") + print(f"wrote {path} (Unicode {unicodedata.unidata_version})", file=sys.stderr) return 0 diff --git a/src/sqlbuild/_native.pyi b/src/sqlbuild/_native.pyi index 5dc6994151..51920c796c 100644 --- a/src/sqlbuild/_native.pyi +++ b/src/sqlbuild/_native.pyi @@ -12,6 +12,9 @@ from sqlbuild.compiler.sql_test_glue.types import NativeSqlTestAssemblyRow, Nati BUILD_IDENTITY: str +class NativeCompilerError(RuntimeError): + """An internal native compiler failure: a panic or a broken native invariant.""" + class LintPreparationRequest(TypedDict): expanded: str before_expansion: str @@ -307,6 +310,9 @@ def parse_macro_arguments(text: str, nested: list[tuple[int, int]]) -> tuple[obj def scan_sql_declaration_references( sqls: list[str], python_version: tuple[int, int], unicode_version: str ) -> list[tuple[list[tuple[int, str, str | None, int, int]], int | None]]: ... +def scan_sql_declaration_usages( + sqls: list[str], python_version: tuple[int, int], unicode_version: str +) -> list[tuple[list[tuple[int, str, str | None, int, int]], int | None]]: ... def interpolate_sql_batch( sqls: list[tuple[str, str]], sources: tuple[ @@ -322,7 +328,19 @@ def interpolate_sql_batch( ]: ... def scan_macro_call_sites( sql: str, python_version: tuple[int, int], unicode_version: str -) -> list[tuple[int, int, str, list[str], bool]] | None: ... +) -> tuple[ + list[tuple[int, int, int, str, list[str] | None, bool]], + tuple[int | None, str | None, str] | None, +]: ... +def sql_test_helper_reads(sql: str, keys: list[str], /) -> list[str] | None: ... +def extract_sql_relation_names( + sql: str, dialect: str | None +) -> tuple[list[tuple[str, str | None, str | None]], list[str]] | None: ... +def substitute_placeholder_defaults(sql: str, placeholders: list[tuple[str, str]], /) -> str: ... +def fixture_projection_facts( + sql: str, dialect: str | None, / +) -> tuple[list[tuple[str, str]], list[str], list[str]]: ... +def macro_call_names(sql: str, nested: bool, /) -> tuple[list[str] | None, str | None]: ... def splice_macro_calls( sql: str, sites: list[tuple[int, int]], outputs: list[str] ) -> tuple[str, list[tuple[int, int, int, int]]]: ... @@ -358,7 +376,7 @@ def digest_files(paths: list[str]) -> list[str | None]: ... # Native analysis: type system. def normalize_type( type_sql: str, dialect: str -) -> tuple[tuple[str, str, int | None, int | None, int | None], str | None] | None: ... +) -> tuple[tuple[str, str, str | None, str | None, str | None], str | None]: ... # Native analysis: model analysis session. type _AnalysisDiagnosticRow = tuple[str, str, int | None, int | None, int | None, int | None, str] @@ -381,87 +399,54 @@ class NativeModelAnalysisSession: def fact_models(self) -> list[str]: ... def run( self, - ) -> ( - tuple[ - list[tuple[str, list[tuple[str, str]]]], - list[ - tuple[ - str, - int, - str | None, - list[tuple[str, list[tuple[str, str]]]], - list[_AnalysisDiagnosticRow], - list[tuple[str, int, int, list[tuple[str, str, str]]]] | None, - ] - ], - list[str], - ] - | None - ): ... - def provide( + ) -> tuple[list[tuple[str, list[tuple[str, str]]]], list[str]]: ... + def finish( self, - results: list[ + ) -> tuple[ + list[ tuple[ - int, bool, list[tuple[str, str | None, str]] | None, + str, + list[tuple[str, int, int, list[tuple[str, str, str]]]], bool, bool, list[_AnalysisDiagnosticRow], bool, + str, ] ], - /, - ) -> bool: ... - def finish( - self, - ) -> ( - tuple[ - list[ + list[tuple[str, list[tuple[str, str]]]], + list[str], + list[ + tuple[ + str, tuple[ bool, - list[tuple[str, str | None, str]] | None, - str, - list[tuple[str, int, int, list[tuple[str, str, str]]]], - bool, - bool, - list[_AnalysisDiagnosticRow], + list[tuple[str, str | None, str]], + list[tuple[str, str | None]], + list[str], + str | None, bool, - str, - ] - ], - list[tuple[str, list[tuple[str, str]]]], - list[str], - list[ - tuple[ - str, - tuple[ - bool, - list[tuple[str, str | None, str]], - list[tuple[str, str | None]], - list[str], - str | None, - bool, - ] - | None, ] - ], - ] - | None - ): ... + | None, + ] + ], + ]: ... def prove_dynamic_contracts( self, models: list[tuple[str, list[tuple[str, str, str, str, str, str | None]]]], / - ) -> list[_PivotContractRow] | None: ... - @property - def failure(self) -> str | None: ... + ) -> list[_PivotContractRow]: ... @property def sharing(self) -> tuple[int, int]: ... @property def cache_stats(self) -> tuple[int, int, int, str | None] | None: ... def start_model_analysis_session( - catalog: object, request: tuple[object, ...], cache: tuple[str, str] | None = None -) -> NativeModelAnalysisSession | None: ... + catalog: object, + request: tuple[object, ...], + cache: tuple[str, str] | None = None, + adapter_rules: tuple[Mapping[str, Callable[..., object]], type] | None = None, +) -> NativeModelAnalysisSession: ... def prove_dynamic_column_contracts( request: tuple[ str, @@ -472,10 +457,25 @@ def prove_dynamic_column_contracts( list[tuple[str, list[tuple[str, str, str, str, str, str | None]]]], ], /, -) -> list[_PivotContractRow] | None: ... +) -> list[_PivotContractRow]: ... +def infer_query_columns( + catalog: object | None, + request: tuple[ + str, + list[tuple[str, str]], + list[tuple[str, str]], + list[tuple[str, list[tuple[str, str]]]], + list[tuple[str, list[tuple[str, str]]]], + list[tuple[object, ...]], + str, + ], + adapter_rules: tuple[Mapping[str, Callable[..., object]], type] | None = None, +) -> list[tuple[bool, list[tuple[str, str | None, str]] | None, bool]]: ... def infer_expression_source_shapes( - catalog: object, request: tuple[str, bool, list[tuple[str, str]], list[str]], / -) -> tuple[list[tuple[bool, list[tuple[str, str]] | None]], str | None]: ... + catalog: object, + request: tuple[str, bool, list[tuple[str, str]], list[tuple[str, str]], list[str]], + adapter_rules: tuple[Mapping[str, Callable[..., object]], type] | None = None, +) -> list[list[tuple[str, str]] | None]: ... def _oracle_cte_fact_recovery( request: tuple[ str, @@ -494,14 +494,12 @@ class SemanticTypeRecovery: @property def status(self) -> str: ... @property - def deferral(self) -> str | None: ... - @property def poisoned(self) -> list[tuple[str, str]]: ... @property def revalidated(self) -> list[int]: ... def finish( self, revised: list[list[tuple[str, int | None, int | None]]], / - ) -> tuple[list[tuple[int, str | None]], list[list[int]]] | None: ... + ) -> tuple[list[tuple[int, str | None]], list[list[int]]]: ... def plan_semantic_type_recovery( catalog: object, @@ -549,7 +547,6 @@ def check_semantic_metadata_rows( ], /, ) -> tuple[ - str | None, list[tuple[list[tuple[str, str, int, int]], list[tuple[str, str, int, int]]]], list[tuple[int, tuple[str, str, int, int]]], list[tuple[int, tuple[str, str, int, int], int]], @@ -589,7 +586,6 @@ def complete_semantic_checks( session: NativeModelAnalysisSession | None = None, /, ) -> tuple[ - str | None, list[ tuple[ int, @@ -626,20 +622,17 @@ def evaluate_native_model_contracts( ], /, ) -> list[ - tuple[ - str | None, - list[ - tuple[ - str, - bool, - str, - str | None, - int | None, - str | None, - tuple[str, str] | None, - str, - ] - ], + list[ + tuple[ + str, + bool, + str, + str | None, + int | None, + str | None, + tuple[str, str] | None, + str, + ] ] ]: ... def native_promotion_conflicts( @@ -649,7 +642,7 @@ def native_promotion_conflicts( # Native analysis: column lineage facts. def build_fast_column_lineage( - catalog: object, + catalog: object | None, request: tuple[str | None, list[tuple[str, str, list[str]]], list[tuple[bool, str, list[str]]]], /, ) -> list[tuple[str, list[tuple[str, str, str, list[tuple[str, str, str]]]], bool, str | None]]: ... @@ -664,37 +657,48 @@ def assemble_compiled_sql_tests( ) -> list[NativeSqlTestAssemblyRow]: ... # Native analysis: compiled project assembly. +def sql_syntax_error( + sql: str, + placeholders: Mapping[str, str] | None, + dialect: str | None, + parse_one: bool = False, +) -> str | None: ... def check_native_sql_syntax( request: tuple[str, list[tuple[str, list[tuple[str, str]]]]], / -) -> tuple[bool | None, str | None]: ... +) -> bool: ... def assemble_project_resource_facts( request: tuple[ str, tuple[str | None, str | None, str | None] | None, tuple[str | None, str | None, str | None, str | None], - list[tuple[str, str, str]], + list[tuple[str, str, str, tuple[str, str] | None]], list[tuple[str, str | None]], - list[tuple[list[tuple[str, str, str | None]], list[tuple[str, list[tuple[str, str]]]]]], + list[ + tuple[ + str, + str, + list[str], + list[tuple[str, str, str | None]], + list[tuple[str, list[tuple[str, str]]]], + ] + ], list[tuple[str, bool, str | None, str | None]], - list[tuple[str, str | None, str | None]], - list[list[tuple[str, str, str | None]]], + list[tuple[str, list[str], str | None, str | None]], + list[tuple[str, str, list[str], list[tuple[str, str, str | None]]]], list[tuple[list[tuple[str, str, str | None]], tuple[str, str] | None]], ], /, ) -> tuple[ - tuple[ - list[list[tuple[str, str]]], - list[tuple[str | None, str | None] | None], - list[tuple[str | None, str | None, str | None, str | None]], - list[list[tuple[str, str]]], - list[list[tuple[str, str]]], - list[tuple[str, str]], - ] - | None, - str | None, + list[list[tuple[str, str]]], + list[tuple[str | None, str | None] | None], + list[tuple[str | None, str | None, str | None, str | None]], + list[list[tuple[str, str]]], + list[list[tuple[str, str]]], + list[tuple[str, str]], + list[bool], + tuple[str, int, str, str, str | None, int | None] | None, ]: ... - -# Internal oracle hooks for tests that compare native foundations with Python; not an API. +def check_native_explicit_references(request_json: str, /) -> str: ... def _oracle_json_dumps(dialect_json: str, value_json: str) -> str: ... def _oracle_text_positions( data: bytes, byte_offsets: list[int] diff --git a/src/sqlbuild/adapter/type_system/_helpers/type_normalization.py b/src/sqlbuild/adapter/type_system/_helpers/type_normalization.py index 98c8f6844c..c49ea238f5 100644 --- a/src/sqlbuild/adapter/type_system/_helpers/type_normalization.py +++ b/src/sqlbuild/adapter/type_system/_helpers/type_normalization.py @@ -2,75 +2,18 @@ from __future__ import annotations -import logging -import re from functools import lru_cache -from typing import Any -from sqlbuild.adapter.contract.constants import ( - BOOLEAN_TYPE_NAMES, - DATE_TYPE_NAME, - DATETIME_TYPE_NAME, - DECIMAL_TYPE_NAMES, - FLOAT_TYPE_NAMES, - INTEGER_TYPE_NAMES, - POLYGLOT_CUSTOM_TYPE_NAME, - STRING_TYPE_NAMES, - TIMESTAMP_TYPE_NAMES, - TIMESTAMP_TYPE_TOKEN, -) from sqlbuild.adapter.contract.models import NormalizedType from sqlbuild.adapter.contract.types import TypeDialect, TypeFamily -from sqlbuild.adapter.type_system.constants import ( - TYPE_NORMALIZATION_LOGGER_NAME, - TYPE_PARSE_FALLBACK_MESSAGE, -) from sqlbuild.adapter.type_system.main._native_normalize_type import normalize_native_type -from sqlbuild.adapters.bigquery.constants import ( - BIGNUMERIC_TYPE_NAME, - CUSTOM_NORMALIZATION_TYPE_NAMES, - FLOAT_WIRE_TYPE_NAME, - INTEGER_PARSE_TYPE_NAMES, -) -from sqlbuild.adapters.snowflake.constants import ( - DEFAULT_TEXT_LENGTH, - INTEGER_PRECISION, - INTEGER_SCALE, - NORMALIZED_LTZ_INPUT_TYPE_NAME, - NORMALIZED_NTZ_INPUT_TYPE_NAMES, - NORMALIZED_TZ_INPUT_TYPE_NAME, - TEXT_TYPE_NAME, - UNBOUNDED_TEXT_TYPE_NAMES, -) -from sqlbuild.compiler.frontier.main.native_stage_enabled import native_stage_enabled -from sqlbuild.compiler.frontier.main.report_native_answer import report_native_answer -from sqlbuild.compiler.frontier.main.report_native_fallback import report_native_fallback -from sqlbuild.compiler.frontier.types import NativeFallbackSite, NativeStage -from sqlbuild.compiler.sql_analysis.main.import_polyglot import import_polyglot -from sqlbuild.diagnostics.main.log_debug_event import log_debug_event - -_DEBUG_LOGGER: logging.Logger = logging.getLogger(TYPE_NORMALIZATION_LOGGER_NAME) @lru_cache(maxsize=1024) def normalize_type(*, type_sql: str, dialect: TypeDialect | str | None) -> NormalizedType: """Normalize one warehouse type string into a semantic comparison shape.""" - if native_stage_enabled(NativeStage.TYPE_SYSTEM): - native_normalized: NormalizedType | None = normalize_native_type( - type_sql=type_sql, dialect=dialect - ) - if native_normalized is not None: - report_native_answer(stage=NativeStage.TYPE_SYSTEM, kind="type_normalizations") - return native_normalized - report_native_fallback(site=NativeFallbackSite.TYPE_NORMALIZATION) - polyglot_normalized: NormalizedType | None = _normalize_with_polyglot( - type_sql=type_sql, - dialect=dialect, - ) - if polyglot_normalized is not None: - return polyglot_normalized - return _normalize_with_fallback(type_sql=type_sql, dialect=dialect) + return normalize_native_type(type_sql=type_sql, dialect=dialect) def normalize_numeric_family(*, type_sql: str, dialect: TypeDialect | str | None) -> str | None: @@ -89,313 +32,3 @@ def types_equal(*, left: str, right: str, dialect: TypeDialect | str | None) -> type_sql=right, dialect=dialect, ) - - -def _normalize_with_polyglot( - *, type_sql: str, dialect: TypeDialect | str | None -) -> NormalizedType | None: - polyglot_module: Any = import_polyglot() - try: - parsed: Any = polyglot_module.parse_data_type(type_sql, dialect=dialect or "generic") - except polyglot_module.PolyglotError as error: - log_debug_event( - logger=_DEBUG_LOGGER, - message=TYPE_PARSE_FALLBACK_MESSAGE, - type_sql=type_sql, - dialect=str(dialect), - sqlbuild_error=str(error), - ) - return None - return _normalized_from_parsed_type(parsed=parsed, dialect=dialect) - - -def _normalized_from_parsed_type( - *, parsed: Any, dialect: TypeDialect | str | None -) -> NormalizedType: - normalized_dialect: TypeDialect | None = _coerce_type_dialect(dialect) - normalized_name: str = parsed.sql(dialect=dialect or "generic").upper().replace(" ", "") - args: dict[str, Any] = dict(getattr(parsed, "args", {}) or {}) - dtype_name: str = _polyglot_type_name(args=args) - params: list[int] = _polyglot_type_params(args=args) - precision_and_scale_count: int = 2 - - if normalized_dialect == TypeDialect.BIGQUERY and dtype_name in INTEGER_PARSE_TYPE_NAMES: - normalized_name = "INT64" - return NormalizedType(normalized_name=normalized_name, family=TypeFamily.INTEGER) - if normalized_dialect == TypeDialect.BIGQUERY and dtype_name == BIGNUMERIC_TYPE_NAME: - return NormalizedType(normalized_name="BIGNUMERIC", family=TypeFamily.DECIMAL) - if normalized_dialect == TypeDialect.BIGQUERY and dtype_name == FLOAT_WIRE_TYPE_NAME: - return NormalizedType(normalized_name="FLOAT64", family=TypeFamily.FLOAT) - if dtype_name == POLYGLOT_CUSTOM_TYPE_NAME: - raw_name: str = str(args.get("name", normalized_name)).upper().replace(" ", "") - if normalized_dialect == TypeDialect.SNOWFLAKE and raw_name.startswith("NUMBER"): - decimal_name: str = raw_name.replace("NUMBER", "DECIMAL", 1) - base_type, params = _split_type_and_params(decimal_name) - precision: int | None = params[0] if len(params) >= 1 else None - scale: int | None = params[1] if len(params) >= precision_and_scale_count else None - if precision is None: - precision = INTEGER_PRECISION - scale = INTEGER_SCALE - decimal_name = f"DECIMAL({precision},{scale})" - return NormalizedType( - normalized_name=decimal_name, - family=TypeFamily.DECIMAL, - precision=precision, - scale=scale, - ) - return _normalize_with_fallback(type_sql=raw_name, dialect=dialect) - if dtype_name in INTEGER_TYPE_NAMES: - if normalized_dialect == TypeDialect.SNOWFLAKE: - return NormalizedType( - normalized_name=f"DECIMAL({INTEGER_PRECISION},{INTEGER_SCALE})", - family=TypeFamily.DECIMAL, - precision=INTEGER_PRECISION, - scale=INTEGER_SCALE, - ) - return NormalizedType(normalized_name=normalized_name, family=TypeFamily.INTEGER) - if dtype_name in DECIMAL_TYPE_NAMES: - precision: int | None = params[0] if len(params) >= 1 else None - scale: int | None = params[1] if len(params) >= precision_and_scale_count else None - if normalized_dialect == TypeDialect.SNOWFLAKE and precision is None: - precision = INTEGER_PRECISION - scale = INTEGER_SCALE - normalized_name = f"DECIMAL({precision},{scale})" - return NormalizedType( - normalized_name=normalized_name, - family=TypeFamily.DECIMAL, - precision=precision, - scale=scale, - ) - if dtype_name in FLOAT_TYPE_NAMES: - return NormalizedType(normalized_name=normalized_name, family=TypeFamily.FLOAT) - if dtype_name in STRING_TYPE_NAMES: - length: int | None = params[0] if len(params) >= 1 else None - if ( - normalized_dialect == TypeDialect.SNOWFLAKE - and _base_type_name(normalized_name) in UNBOUNDED_TEXT_TYPE_NAMES - ): - length = length or DEFAULT_TEXT_LENGTH - normalized_name = f"VARCHAR({length})" - return NormalizedType( - normalized_name=normalized_name, - family=TypeFamily.STRING, - length=length, - ) - if dtype_name in BOOLEAN_TYPE_NAMES: - return NormalizedType(normalized_name=normalized_name, family=TypeFamily.BOOLEAN) - if dtype_name in TIMESTAMP_TYPE_NAMES: - normalized_name = _timestamp_normalized_name( - normalized_name=normalized_name, - dialect=normalized_dialect, - ) - return NormalizedType(normalized_name=normalized_name, family=TypeFamily.TIMESTAMP) - if dtype_name == DATE_TYPE_NAME: - return NormalizedType(normalized_name=normalized_name, family=TypeFamily.DATE) - if dtype_name == DATETIME_TYPE_NAME: - return NormalizedType(normalized_name=normalized_name, family=TypeFamily.DATETIME) - return NormalizedType(normalized_name=normalized_name, family=TypeFamily.OTHER) - - -def _normalize_with_fallback(*, type_sql: str, dialect: TypeDialect | str | None) -> NormalizedType: - normalized_dialect: TypeDialect | None = _coerce_type_dialect(dialect) - normalized: str = type_sql.upper().strip() - normalized = re.sub(r"\s+", "", normalized) - base_type, params = _split_type_and_params(normalized) - precision_and_scale_count: int = 2 - - if base_type in INTEGER_TYPE_NAMES: - if normalized_dialect == TypeDialect.SNOWFLAKE: - return NormalizedType( - normalized_name=f"DECIMAL({INTEGER_PRECISION},{INTEGER_SCALE})", - family=TypeFamily.DECIMAL, - precision=INTEGER_PRECISION, - scale=INTEGER_SCALE, - ) - normalized_name: str = _fallback_integer_normalized_name( - base_type=base_type, - dialect=normalized_dialect, - ) - return NormalizedType(normalized_name=normalized_name, family=TypeFamily.INTEGER) - if base_type in DECIMAL_TYPE_NAMES: - precision: int | None = params[0] if len(params) >= 1 else None - scale: int | None = params[1] if len(params) >= precision_and_scale_count else None - if normalized_dialect == TypeDialect.SNOWFLAKE and precision is None: - precision = INTEGER_PRECISION - scale = INTEGER_SCALE - normalized_name = _fallback_decimal_normalized_name( - base_type=base_type, - dialect=normalized_dialect, - ) - if precision is not None and scale is not None: - normalized_name = f"{normalized_name}({precision},{scale})" - elif precision is not None: - normalized_name = f"{normalized_name}({precision})" - return NormalizedType( - normalized_name=normalized_name, - family=TypeFamily.DECIMAL, - precision=precision, - scale=scale, - ) - if base_type in FLOAT_TYPE_NAMES: - normalized_name = _fallback_float_normalized_name( - base_type=base_type, - dialect=normalized_dialect, - ) - return NormalizedType(normalized_name=normalized_name, family=TypeFamily.FLOAT) - if base_type in STRING_TYPE_NAMES: - length: int | None = params[0] if len(params) >= 1 else None - normalized_name = _fallback_string_normalized_name( - base_type=base_type, - dialect=normalized_dialect, - ) - normalized_name = normalized_name if length is None else f"{normalized_name}({length})" - if normalized_dialect == TypeDialect.SNOWFLAKE and base_type in UNBOUNDED_TEXT_TYPE_NAMES: - length = length or DEFAULT_TEXT_LENGTH - normalized_name = f"VARCHAR({length})" - return NormalizedType( - normalized_name=normalized_name, - family=TypeFamily.STRING, - length=length, - ) - if base_type in BOOLEAN_TYPE_NAMES: - normalized_name = _fallback_boolean_normalized_name( - base_type=base_type, - dialect=normalized_dialect, - ) - return NormalizedType(normalized_name=normalized_name, family=TypeFamily.BOOLEAN) - if TIMESTAMP_TYPE_TOKEN in base_type: - normalized_timestamp_name: str = _timestamp_normalized_name( - normalized_name=base_type, - dialect=normalized_dialect, - ) - return NormalizedType( - normalized_name=normalized_timestamp_name, - family=TypeFamily.TIMESTAMP, - ) - if base_type == DATE_TYPE_NAME: - return NormalizedType(normalized_name=base_type, family=TypeFamily.DATE) - if base_type == DATETIME_TYPE_NAME: - return NormalizedType(normalized_name=base_type, family=TypeFamily.DATETIME) - return NormalizedType(normalized_name=normalized, family=TypeFamily.OTHER) - - -def _split_type_and_params(type_sql: str) -> tuple[str, list[int]]: - match: re.Match[str] | None = re.match(r"^([A-Z0-9_]+)(?:\(([^)]*)\))?$", type_sql) - if match is None: - return type_sql, [] - raw_params: str | None = match.group(2) - if raw_params is None or not raw_params: - return match.group(1), [] - params: list[int] = [] - raw_part: str - for raw_part in raw_params.split(","): - try: - params.append(int(raw_part.strip())) - except ValueError: - continue - return match.group(1), params - - -def _base_type_name(type_sql: str) -> str: - return type_sql.split("(", maxsplit=1)[0] - - -def _fallback_integer_normalized_name(*, base_type: str, dialect: TypeDialect | None) -> str: - if dialect == TypeDialect.BIGQUERY: - return "INT64" - return base_type - - -def _fallback_decimal_normalized_name(*, base_type: str, dialect: TypeDialect | None) -> str: - if dialect == TypeDialect.BIGQUERY: - if base_type == BIGNUMERIC_TYPE_NAME: - return "BIGNUMERIC" - return "NUMERIC" - if dialect == TypeDialect.SNOWFLAKE: - return "DECIMAL" - return base_type - - -def _fallback_float_normalized_name(*, base_type: str, dialect: TypeDialect | None) -> str: - if dialect == TypeDialect.BIGQUERY: - return "FLOAT64" - return base_type - - -def _fallback_string_normalized_name(*, base_type: str, dialect: TypeDialect | None) -> str: - if dialect == TypeDialect.BIGQUERY: - return "STRING" - if dialect == TypeDialect.SNOWFLAKE and base_type == TEXT_TYPE_NAME: - return "VARCHAR" - return base_type - - -def _fallback_boolean_normalized_name(*, base_type: str, dialect: TypeDialect | None) -> str: - if dialect == TypeDialect.BIGQUERY: - return "BOOL" - return base_type - - -def _timestamp_normalized_name(*, normalized_name: str, dialect: TypeDialect | None) -> str: - if dialect != TypeDialect.SNOWFLAKE: - return normalized_name - compact: str = normalized_name.replace("_", "") - if compact in NORMALIZED_NTZ_INPUT_TYPE_NAMES: - return "TIMESTAMP_NTZ" - if compact == NORMALIZED_LTZ_INPUT_TYPE_NAME: - return "TIMESTAMP_LTZ" - if compact == NORMALIZED_TZ_INPUT_TYPE_NAME: - return "TIMESTAMP_TZ" - return normalized_name - - -def _polyglot_type_name(*, args: dict[str, Any]) -> str: - data_type: str = str(args.get("data_type", "")).upper() - polyglot_name_map: dict[str, str] = { - "BIG_INT": "BIGINT", - "SMALL_INT": "SMALLINT", - "TINY_INT": "TINYINT", - "VAR_CHAR": "VARCHAR", - "TEXT": "TEXT", - "INT": "INT", - "BOOLEAN": "BOOLEAN", - "DECIMAL": "DECIMAL", - "DOUBLE": "DOUBLE", - "FLOAT": "FLOAT", - "TIMESTAMP": "TIMESTAMP", - "DATE": "DATE", - "DATETIME": "DATETIME", - } - mapped_name: str | None = polyglot_name_map.get(data_type) - if mapped_name is not None: - return mapped_name - if data_type == POLYGLOT_CUSTOM_TYPE_NAME: - name: str = str(args.get("name", "")).upper().replace(" ", "") - if name in CUSTOM_NORMALIZATION_TYPE_NAMES: - return name - return data_type - - -def _polyglot_type_params(*, args: dict[str, Any]) -> list[int]: - params: list[int] = [] - key: str - for key in ("precision", "scale", "length"): - value: Any = args.get(key) - if value is None: - continue - try: - params.append(int(value)) - except (TypeError, ValueError): - continue - return params - - -def _coerce_type_dialect(dialect: TypeDialect | str | None) -> TypeDialect | None: - if isinstance(dialect, TypeDialect): - return dialect - if dialect is None: - return None - try: - return TypeDialect(dialect) - except ValueError: - return None diff --git a/src/sqlbuild/adapter/type_system/main/_native_normalize_type.py b/src/sqlbuild/adapter/type_system/main/_native_normalize_type.py index 6d9a9ceb50..77f1c5d714 100644 --- a/src/sqlbuild/adapter/type_system/main/_native_normalize_type.py +++ b/src/sqlbuild/adapter/type_system/main/_native_normalize_type.py @@ -1,4 +1,4 @@ -"""Native type normalization for the preview compiler engine.""" +"""Native type normalization.""" from __future__ import annotations @@ -14,19 +14,12 @@ from sqlbuild.diagnostics.main.log_debug_event import log_debug_event -def normalize_native_type( - *, type_sql: str, dialect: TypeDialect | str | None -) -> NormalizedType | None: - """Return the native normalization, or None where Python must normalize the type.""" +def normalize_native_type(*, type_sql: str, dialect: TypeDialect | str | None) -> NormalizedType: + """Return the native normalization of one type, raising as Polyglot does.""" - if not isinstance(type_sql, str) or not isinstance(dialect, str | None): - return None - native: tuple[tuple[str, str, int | None, int | None, int | None], str | None] | None = ( - _native.normalize_type(type_sql, str(dialect or "generic")) + (normalized_name, family, precision, scale, length), parse_error = _native.normalize_type( + type_sql, str(dialect or "generic") ) - if native is None: - return None - (normalized_name, family, precision, scale, length), parse_error = native if parse_error is not None: log_debug_event( logger=logging.getLogger(TYPE_NORMALIZATION_LOGGER_NAME), @@ -38,7 +31,11 @@ def normalize_native_type( return NormalizedType( normalized_name=normalized_name, family=TypeFamily(family), - precision=precision, - scale=scale, - length=length, + precision=_python_int(precision), + scale=_python_int(scale), + length=_python_int(length), ) + + +def _python_int(value: str | None) -> int | None: + return None if value is None else int(value) diff --git a/src/sqlbuild/adapter/type_system/main/_safe_cast_nullability.py b/src/sqlbuild/adapter/type_system/main/safe_cast_nullability.py similarity index 100% rename from src/sqlbuild/adapter/type_system/main/_safe_cast_nullability.py rename to src/sqlbuild/adapter/type_system/main/safe_cast_nullability.py diff --git a/src/sqlbuild/cli/commands/_helpers/compile/target_writer.py b/src/sqlbuild/cli/commands/_helpers/compile/target_writer.py index c3aba5c289..f8996b2463 100644 --- a/src/sqlbuild/cli/commands/_helpers/compile/target_writer.py +++ b/src/sqlbuild/cli/commands/_helpers/compile/target_writer.py @@ -47,13 +47,7 @@ DiagnosticSeverity, FunctionLanguage, ) -from sqlbuild.compiler.frontier.main.native_stage_enabled import native_stage_enabled -from sqlbuild.compiler.frontier.main.report_native_answer import report_native_answer -from sqlbuild.compiler.frontier.types import NativeStage from sqlbuild.compiler.planner.exceptions import PlannerInputError -from sqlbuild.compiler.planner.main.execution.sql_test_artifacts import ( - plan_and_render_sql_test_artifacts, -) from sqlbuild.compiler.planner.main.execution.sql_test_model_chain import ( sql_test_model_chain_names_by_key, ) @@ -576,20 +570,12 @@ def _plan_static_test_artifacts( with OperationLifecycle( operation_kind="project", operation_name="sql_test_planning" ) as lifecycle: - native_planning: bool = native_stage_enabled(NativeStage.SQL_TEST_GLUE) - plan_artifacts: Callable[..., tuple[NativeSqlTestArtifact, ...]] = ( - plan_native_sql_test_artifacts - if native_planning - else plan_and_render_sql_test_artifacts - ) - native_artifacts: tuple[NativeSqlTestArtifact, ...] = plan_artifacts( + native_artifacts: tuple[NativeSqlTestArtifact, ...] = plan_native_sql_test_artifacts( project=project, tests=tests, adapter=adapter, sql_analysis_enabled=project.settings.sql_analysis, ) - if native_planning: - report_native_answer(stage=NativeStage.SQL_TEST_GLUE, kind="sql_test_plans") lifecycle.completed(metadata={"item_count": len(native_artifacts)}) return native_artifacts diff --git a/src/sqlbuild/cli/commands/_helpers/entry/parser.py b/src/sqlbuild/cli/commands/_helpers/entry/parser.py index 17e9c79555..d931bfe089 100644 --- a/src/sqlbuild/cli/commands/_helpers/entry/parser.py +++ b/src/sqlbuild/cli/commands/_helpers/entry/parser.py @@ -29,7 +29,7 @@ ) from sqlbuild.cli.commands.types import CliCommand, CompileLineageMode from sqlbuild.compiler.contract_adoption.types import ContractAction -from sqlbuild.compiler.frontier.constants import COMPILER_ENGINE_OPTION, COMPILER_ENGINE_VALUES +from sqlbuild.compiler.frontier.constants import COMPILER_ENGINE_OPTION from sqlbuild.compiler.lineage.types import ColumnLineageMode from sqlbuild.compiler.scopes.types import DeclarationKind @@ -102,7 +102,6 @@ def _add_global_args(*, parser: argparse.ArgumentParser, suppress_defaults: bool parser.add_argument( COMPILER_ENGINE_OPTION, dest="compiler_engine", - choices=COMPILER_ENGINE_VALUES, default=argparse.SUPPRESS if suppress_defaults else None, help=argparse.SUPPRESS, ) diff --git a/src/sqlbuild/cli/commands/_helpers/entry/parsing.py b/src/sqlbuild/cli/commands/_helpers/entry/parsing.py index 70575c1dce..4351baf7d8 100644 --- a/src/sqlbuild/cli/commands/_helpers/entry/parsing.py +++ b/src/sqlbuild/cli/commands/_helpers/entry/parsing.py @@ -25,7 +25,9 @@ SelectorFileSummary, SelectorInputs, ) +from sqlbuild.compiler.frontier.constants import COMPILER_ENGINE_OPTION from sqlbuild.compiler.frontier.exceptions import CompilerEngineError +from sqlbuild.compiler.frontier.main.parse_compiler_engine import parse_compiler_engine from sqlbuild.compiler.frontier.main.resolve_compiler_engine import resolve_compiler_engine from sqlbuild.compiler.scopes.types import DeclarationKind from sqlbuild.integrations.dbt.types import DbtInteropCommand @@ -117,11 +119,16 @@ def parse_cli_invocation( if unknown_args: parser.error(f"unrecognized arguments: {' '.join(unknown_args)}") args.verbose = args.verbose or args.debug - if args.compiler_engine is None: - try: - _ = resolve_compiler_engine() - except CompilerEngineError as error: - parser.error(str(error)) + try: + _ = ( + resolve_compiler_engine() + if args.compiler_engine is None + else parse_compiler_engine( + raw_value=args.compiler_engine, source=COMPILER_ENGINE_OPTION + ) + ) + except CompilerEngineError as error: + parser.error(str(error)) if ( args.debug and args.command == CliCommand.DBT diff --git a/src/sqlbuild/compiler/analysis_session/_helpers/dynamic_contracts.py b/src/sqlbuild/compiler/analysis_session/_helpers/dynamic_contracts.py index 560870c25c..4a93e94489 100644 --- a/src/sqlbuild/compiler/analysis_session/_helpers/dynamic_contracts.py +++ b/src/sqlbuild/compiler/analysis_session/_helpers/dynamic_contracts.py @@ -5,15 +5,10 @@ from typing import Any import sqlbuild._native as _native -from sqlbuild.compiler.analysis_session._helpers.deferral_records import record_analysis_deferral -from sqlbuild.compiler.analysis_session._helpers.session_rows import ( - contract_proof, - family_rows, - shape_rows, -) -from sqlbuild.compiler.analysis_session.constants import CONTRACT_DEFERRED, DEFERRAL_DYNAMIC_PIVOT +from sqlbuild.compiler.analysis_session._helpers.profile_rows import shape_rows +from sqlbuild.compiler.analysis_session._helpers.session_rows import contract_proof, family_rows from sqlbuild.compiler.analysis_session.models import NativePivotTables -from sqlbuild.compiler.analysis_session.types import ContractRow, ShapeRows +from sqlbuild.compiler.analysis_session.types import ContractRow from sqlbuild.compiler.compile.classes.python_model_analysis import PythonModelAnalysis from sqlbuild.compiler.compile.models import DynamicColumnContractProof from sqlbuild.spec.contracts.models import SchemaDynamicColumnFamily @@ -27,47 +22,27 @@ def native_dynamic_contracts( tables: NativePivotTables, models: tuple[tuple[str, tuple[SchemaDynamicColumnFamily, ...]], ...], ) -> tuple[DynamicColumnContractProof | None, ...]: - """Each model's proof in order, None (recorded) where Python must prove it.""" + """Each model's proof in order; a native internal failure raises.""" if not models: return () rows: list[_ModelRow] = [_model_row(sql=sql, families=families) for sql, families in models] - contracts: list[ContractRow] | None = ( + contracts: list[ContractRow] = ( session.prove_dynamic_contracts(rows) if session is not None - else _standalone_contracts(tables=tables, rows=rows) - ) - if contracts is None: - record_analysis_deferral(kind=DEFERRAL_DYNAMIC_PIVOT, count=len(models)) - return (None,) * len(models) - record_analysis_deferral( - kind=DEFERRAL_DYNAMIC_PIVOT, - count=sum(kind == CONTRACT_DEFERRED for kind, _ in contracts), + else _native.prove_dynamic_column_contracts( + ( + tables.dialect or "generic", + shape_rows(tables.column_types_by_table), + shape_rows(tables.authoritative_column_types_by_table), + shape_rows(tables.column_nullability_by_table), + family_rows(tables.dynamic_families_by_table), + rows, + ) + ) ) return tuple(contract_proof(proof) for _, proof in contracts) def _model_row(*, sql: str, families: tuple[SchemaDynamicColumnFamily, ...]) -> _ModelRow: return (sql, list(map(PythonModelAnalysis.family_row, families))) - - -def _standalone_contracts( - *, tables: NativePivotTables, rows: list[_ModelRow] -) -> list[ContractRow] | None: - shapes: tuple[ShapeRows | None, ...] = ( - shape_rows(tables.column_types_by_table), - shape_rows(tables.authoritative_column_types_by_table), - shape_rows(tables.column_nullability_by_table), - ) - if any(shape is None for shape in shapes): - return None - return _native.prove_dynamic_column_contracts( - ( - tables.dialect or "generic", - shapes[0] or [], - shapes[1] or [], - shapes[2] or [], - family_rows(tables.dynamic_families_by_table), - rows, - ) - ) diff --git a/src/sqlbuild/compiler/analysis_session/_helpers/expression_shapes.py b/src/sqlbuild/compiler/analysis_session/_helpers/expression_shapes.py index 6a70d30bc3..1d2bb0c2aa 100644 --- a/src/sqlbuild/compiler/analysis_session/_helpers/expression_shapes.py +++ b/src/sqlbuild/compiler/analysis_session/_helpers/expression_shapes.py @@ -2,71 +2,61 @@ from __future__ import annotations -import logging from typing import Any import sqlbuild._native as _native from sqlbuild.adapter.contract.models import ExpressionInferenceProfile +from sqlbuild.adapter.contract.types import FunctionNullabilityRule from sqlbuild.compiler.analysis_session._helpers.deferral_records import record_analysis_deferral -from sqlbuild.compiler.analysis_session._helpers.session_rows import case_sensitive_shapes -from sqlbuild.compiler.analysis_session.constants import ( - DEFERRAL_EXPRESSION_SHAPES, - DEFERRAL_NO_CATALOG, - NATIVE_SHAPES_FAILURE_MESSAGE, +from sqlbuild.compiler.analysis_session._helpers.profile_rows import ( + adapter_nullability_rules, + case_sensitive_shapes, + nullability_rule_rows, ) +from sqlbuild.compiler.analysis_session.constants import ADAPTER_NULLABILITY_CALLBACK +from sqlbuild.compiler.lineage.types import InferredNullability from sqlbuild.compiler.sql_analysis.constants import NATIVE_DIALECT_ALIASES -from sqlbuild.diagnostics.main.log_debug_event import log_debug_event - -_DEBUG_LOGGER: logging.Logger = logging.getLogger("sqlbuild.compile") +from sqlbuild.compiler.sql_analysis.main._binding_catalog import create_binding_catalog def native_expression_source_shapes( *, expressions: tuple[str, ...], profile: ExpressionInferenceProfile -) -> tuple[dict[str, str] | None, ...] | None: - """One shape per expression, or None (recorded) where Python must infer the shapes.""" +) -> tuple[dict[str, str] | None, ...]: + """One shape per expression; a native internal failure raises `NativeCompilerError`.""" - catalog: Any = profile.binding_catalog - if catalog is None: - record_analysis_deferral(kind=DEFERRAL_NO_CATALOG) - return None + dialect: str = profile.sql_analysis_dialect or "generic" + dialect = NATIVE_DIALECT_ALIASES.get(dialect, dialect) + catalog: Any = profile.binding_catalog or create_binding_catalog( + dialect=dialect, + quoted_ignore_case=profile.quoted_identifiers_ignore_case, + known_functions=(), + known_types=(), + relations={}, + ) cache: dict[str, dict[str, str] | None] = catalog.expression_shapes pending: tuple[str, ...] = tuple( dict.fromkeys(expression for expression in expressions if expression not in cache) ) - inferred: dict[str, dict[str, str] | None] | None = ( - _inferred_shapes(catalog=catalog, pending=pending, profile=profile) if pending else {} - ) - if inferred is None: - return None - cache.update(inferred) + if pending: + adapter_rules: dict[str, FunctionNullabilityRule] = adapter_nullability_rules(profile) + if adapter_rules: + record_analysis_deferral(kind=ADAPTER_NULLABILITY_CALLBACK) + shapes: list[list[tuple[str, str]] | None] = _native.infer_expression_source_shapes( + catalog.native, + ( + dialect, + case_sensitive_shapes(profile=profile, dialect=dialect), + list(profile.function_return_types.items()), + nullability_rule_rows(profile), + list(pending), + ), + (adapter_rules, InferredNullability) if adapter_rules else None, + ) + cache.update( + (expression, dict(shape) if shape is not None else None) + for expression, shape in zip(pending, shapes, strict=True) + ) return tuple( None if cache[expression] is None else dict(cache[expression] or {}) for expression in expressions ) - - -def _inferred_shapes( - *, catalog: Any, pending: tuple[str, ...], profile: ExpressionInferenceProfile -) -> dict[str, dict[str, str] | None] | None: - dialect: str = profile.sql_analysis_dialect or "generic" - dialect = NATIVE_DIALECT_ALIASES.get(dialect, dialect) - shapes, failure = _native.infer_expression_source_shapes( - catalog.native, - ( - dialect, - case_sensitive_shapes(profile=profile, dialect=dialect), - list(profile.function_return_types.items()), - list(pending), - ), - ) - deferred: int = len(pending) if failure is not None else sum(not done for done, _ in shapes) - if deferred: - record_analysis_deferral(kind=DEFERRAL_EXPRESSION_SHAPES, count=deferred) - log_debug_event( - logger=_DEBUG_LOGGER, message=NATIVE_SHAPES_FAILURE_MESSAGE, sqlbuild_error=failure - ) - return None - return { - expression: dict(shape) if shape is not None else None - for expression, (_, shape) in zip(pending, shapes, strict=True) - } diff --git a/src/sqlbuild/compiler/analysis_session/_helpers/model_analysis.py b/src/sqlbuild/compiler/analysis_session/_helpers/model_analysis.py index 2e15575448..61782def29 100644 --- a/src/sqlbuild/compiler/analysis_session/_helpers/model_analysis.py +++ b/src/sqlbuild/compiler/analysis_session/_helpers/model_analysis.py @@ -1,17 +1,17 @@ -"""Start the native model analysis session, or hand the whole analysis to Python.""" +"""Run the native model analysis session.""" from __future__ import annotations -from typing import Any +from typing import Any, cast import sqlbuild._native as _native +from sqlbuild.adapter.contract.types import FunctionNullabilityRule from sqlbuild.compiler.analysis_session._helpers.deferral_records import record_analysis_deferral +from sqlbuild.compiler.analysis_session._helpers.profile_rows import adapter_nullability_rules from sqlbuild.compiler.analysis_session._helpers.session_rows import session_request from sqlbuild.compiler.analysis_session.classes.native_model_analysis import NativeModelAnalysis from sqlbuild.compiler.analysis_session.constants import ( - DEFERRAL_NO_CATALOG, - DEFERRAL_NO_COMPACT_ANALYSIS, - DEFERRAL_SESSION, + ADAPTER_NULLABILITY_CALLBACK, NATIVE_ANALYSIS_STORE_FILE_NAME, NATIVE_ANALYSIS_STORE_VERSION, ) @@ -20,42 +20,39 @@ NativeModelAnalysisRequest, ) from sqlbuild.compiler.compile.classes.python_model_analysis import PythonModelAnalysis -from sqlbuild.compiler.compile.models import AnalysisCacheContext, ModelSqlAnalysis +from sqlbuild.compiler.compile.models import AnalysisCacheContext from sqlbuild.compiler.frontier.main.compiled_code_identity import compiled_code_identity +from sqlbuild.compiler.lineage.types import InferredNullability -def native_model_analyses(*, request: NativeModelAnalysisRequest) -> NativeModelAnalyses | None: - """Each model's analysis by name and the finished session, or None (recorded) for Python.""" +def native_model_analyses(*, request: NativeModelAnalysisRequest) -> NativeModelAnalyses: + """Each model's analysis by name and the finished session; a native internal failure raises.""" - catalog: Any = request.inference_profile.binding_catalog - if not request.allow_compact_analysis: - record_analysis_deferral(kind=DEFERRAL_NO_COMPACT_ANALYSIS) - return None - if catalog is None: - record_analysis_deferral(kind=DEFERRAL_NO_CATALOG) - return None if not request.model_inputs: return NativeModelAnalyses(analyses={}, session=None) + catalog: Any = cast(Any, request.inference_profile.binding_catalog) python: PythonModelAnalysis = PythonModelAnalysis( model_inputs=request.model_inputs, inference_profile=request.inference_profile, complete_binding_schemas=request.complete_binding_schemas, ) - row: tuple[object, ...] | None = session_request( - request=request, python=python, schemas=catalog.schemas + adapter_rules: dict[str, FunctionNullabilityRule] = adapter_nullability_rules( + request.inference_profile ) - session: _native.NativeModelAnalysisSession | None = ( - _native.start_model_analysis_session(catalog.native, row, _analysis_store(request)) - if row is not None - else None + if adapter_rules: + record_analysis_deferral(kind=ADAPTER_NULLABILITY_CALLBACK) + session: _native.NativeModelAnalysisSession = _native.start_model_analysis_session( + catalog.native, + session_request(request=request, python=python, schemas=catalog.schemas), + None if adapter_rules else _analysis_store(request), + (adapter_rules, InferredNullability) if adapter_rules else None, + ) + return NativeModelAnalyses( + analyses=NativeModelAnalysis(request=request, python=python, catalog=catalog).analyses( + session + ), + session=session, ) - if session is None: - record_analysis_deferral(kind=DEFERRAL_SESSION) - return None - analyses: dict[str, ModelSqlAnalysis] | None = NativeModelAnalysis( - request=request, python=python, catalog=catalog - ).analyses(session) - return None if analyses is None else NativeModelAnalyses(analyses=analyses, session=session) def _analysis_store(request: NativeModelAnalysisRequest) -> tuple[str, str] | None: diff --git a/src/sqlbuild/compiler/analysis_session/_helpers/profile_rows.py b/src/sqlbuild/compiler/analysis_session/_helpers/profile_rows.py new file mode 100644 index 0000000000..e4cb8eb2a5 --- /dev/null +++ b/src/sqlbuild/compiler/analysis_session/_helpers/profile_rows.py @@ -0,0 +1,64 @@ +"""Inference-profile settings crossing into native analysis: rule ids and shape case.""" + +from __future__ import annotations + +from collections.abc import Mapping + +from sqlbuild.adapter.contract.models import ExpressionInferenceProfile +from sqlbuild.adapter.contract.types import FunctionNullabilityRule +from sqlbuild.adapter.type_system.main.conditional_result_nullability import ( + conditional_result_nullability, +) +from sqlbuild.adapter.type_system.main.first_arg_nullability import first_arg_nullability +from sqlbuild.adapter.type_system.main.safe_cast_nullability import safe_cast_nullability +from sqlbuild.compiler.analysis_session.constants import ( + NULLABILITY_RULE_ADAPTER, + NULLABILITY_RULE_CONDITIONAL_RESULT, + NULLABILITY_RULE_FIRST_ARG, + NULLABILITY_RULE_SAFE_CAST, +) +from sqlbuild.compiler.analysis_session.types import ShapeRows +from sqlbuild.compiler.sql_analysis.constants import CASE_SENSITIVE_BINDING_DIALECTS + +_NULLABILITY_RULE_IDS: dict[FunctionNullabilityRule, str] = { + first_arg_nullability: NULLABILITY_RULE_FIRST_ARG, + conditional_result_nullability: NULLABILITY_RULE_CONDITIONAL_RESULT, + safe_cast_nullability: NULLABILITY_RULE_SAFE_CAST, +} + + +def nullability_rule_rows(profile: ExpressionInferenceProfile) -> list[tuple[str, str]]: + """Adapter nullability rules as `(name, rule id)`; an adapter's own rule is `python`.""" + + return [ + (name, _NULLABILITY_RULE_IDS.get(rule, NULLABILITY_RULE_ADAPTER)) + for name, rule in profile.function_nullability_rules.items() + ] + + +def adapter_nullability_rules( + profile: ExpressionInferenceProfile, +) -> dict[str, FunctionNullabilityRule]: + """The adapter's own nullability rules, which the native session calls back into.""" + + return { + name: rule + for name, rule in profile.function_nullability_rules.items() + if rule not in _NULLABILITY_RULE_IDS + } + + +def case_sensitive_shapes(*, profile: ExpressionInferenceProfile, dialect: str | None) -> bool: + """Python's `inferred_binding_shape` test for keeping authored identifier quoting.""" + + return not profile.quoted_identifiers_ignore_case and dialect in CASE_SENSITIVE_BINDING_DIALECTS + + +def shape_rows(shapes: Mapping[str, Mapping[str, str]]) -> ShapeRows: + """`{relation: {column: value}}` as ordered rows; discovery rejects non-text names and types.""" + + return [(name, _shape_pairs(shape)) for name, shape in shapes.items()] + + +def _shape_pairs(shape: Mapping[str, str]) -> list[tuple[str, str]]: + return [(column, str(value)) for column, value in shape.items()] diff --git a/src/sqlbuild/compiler/analysis_session/_helpers/query_columns.py b/src/sqlbuild/compiler/analysis_session/_helpers/query_columns.py new file mode 100644 index 0000000000..9da526a761 --- /dev/null +++ b/src/sqlbuild/compiler/analysis_session/_helpers/query_columns.py @@ -0,0 +1,135 @@ +"""Python's per-query column analysis outside the session, run natively.""" + +from __future__ import annotations + +from collections.abc import Mapping, Sequence +from typing import Any + +import sqlbuild._native as _native +from sqlbuild.adapter.contract.models import ExpressionInferenceProfile +from sqlbuild.adapter.contract.types import FunctionNullabilityRule +from sqlbuild.compiler.analysis_session._helpers.deferral_records import record_analysis_deferral +from sqlbuild.compiler.analysis_session._helpers.profile_rows import ( + adapter_nullability_rules, + nullability_rule_rows, + shape_rows, +) +from sqlbuild.compiler.analysis_session.constants import ADAPTER_NULLABILITY_CALLBACK +from sqlbuild.compiler.analysis_session.models import NativeColumnQuery, NativeQueryColumns +from sqlbuild.compiler.compile.models import CompileSqlReference, InferredColumn +from sqlbuild.compiler.compile.types import CompiledResourceType +from sqlbuild.compiler.lineage.types import InferredNullability +from sqlbuild.compiler.references.types import SqlReferenceKind +from sqlbuild.compiler.sql_analysis.constants import ( + NATIVE_DIALECT_ALIASES, + TABLE_FUNCTION_ANALYSIS_PREFIX, +) +from sqlbuild.compiler.sql_analysis.main._binding_catalog import create_binding_catalog + +_BATCH_MODE: str = "batch" +_LINEAGE_RESOURCE_TYPES: dict[str, CompiledResourceType] = { + SqlReferenceKind.REF: CompiledResourceType.MODEL, + SqlReferenceKind.SOURCE: CompiledResourceType.SOURCE, + SqlReferenceKind.SEED: CompiledResourceType.SEED, + SqlReferenceKind.TABLE_FUNCTION: CompiledResourceType.TABLE_FN, +} + + +def native_query_columns( + *, + queries: Sequence[NativeColumnQuery], + profile: ExpressionInferenceProfile, + column_types_by_table: Mapping[str, Mapping[str, str]], + column_nullability_by_table: Mapping[str, Mapping[str, InferredNullability]], +) -> tuple[NativeQueryColumns, ...]: + """Each query's columns; a native internal failure raises `NativeCompilerError`.""" + + if not queries: + return () + dialect: str = profile.sql_analysis_dialect or "generic" + dialect = NATIVE_DIALECT_ALIASES.get(dialect, dialect) + catalog: Any | None = ( + ( + profile.binding_catalog + or create_binding_catalog( + dialect=dialect, + quoted_ignore_case=profile.quoted_identifiers_ignore_case, + known_functions=(), + known_types=(), + relations={}, + ) + ) + if any(query.mode == _BATCH_MODE for query in queries) + else None + ) + adapter_rules: dict[str, FunctionNullabilityRule] = adapter_nullability_rules(profile) + if adapter_rules: + record_analysis_deferral(kind=ADAPTER_NULLABILITY_CALLBACK) + rows: list[tuple[bool, list[tuple[str, str | None, str]] | None, bool]] = ( + _native.infer_query_columns( + None if catalog is None else catalog.native, + ( + dialect, + list(profile.function_return_types.items()), + nullability_rule_rows(profile), + shape_rows(column_types_by_table), + shape_rows(column_nullability_by_table), + [_query_row(query) for query in queries], + profile.sql_analysis_dialect or "generic", + ), + (adapter_rules, InferredNullability) if adapter_rules else None, + ) + ) + return tuple( + NativeQueryColumns( + succeeded=succeeded, + columns=None if columns is None else _inferred_columns(columns), + has_star=has_star, + ) + for succeeded, columns, has_star in rows + ) + + +def _inferred_columns( + columns: list[tuple[str, str | None, str]], +) -> tuple[InferredColumn, ...]: + return tuple( + InferredColumn(name=name, type=data_type, nullability=InferredNullability(nullability)) + for name, data_type, nullability in columns + ) + + +def _query_row(query: NativeColumnQuery) -> tuple[object, ...]: + references: tuple[CompileSqlReference, ...] = query.references + return ( + query.sql, + list((query.placeholders or {}).items()), + [_analysis_name(reference) for reference in references], + [ + (name, resource_type, resource_name) + for name, (resource_type, resource_name) in _lineage_references(references).items() + ], + query.recover_cte_facts, + query.mode, + ) + + +def _lineage_references( + references: tuple[CompileSqlReference, ...], +) -> dict[str, tuple[str, str]]: + """Each lineage reference's analysis name, resource type and name; the last wins in place.""" + + return { + _analysis_name(reference): ( + _LINEAGE_RESOURCE_TYPES[reference.ref_kind].value, + reference.ref_name, + ) + for reference in references + if reference.ref_kind in _LINEAGE_RESOURCE_TYPES + } + + +def _analysis_name(reference: CompileSqlReference) -> str: + if reference.ref_kind == SqlReferenceKind.TABLE_FUNCTION: + return f"{TABLE_FUNCTION_ANALYSIS_PREFIX}{reference.ref_name}" + return reference.ref_name diff --git a/src/sqlbuild/compiler/analysis_session/_helpers/session_rows.py b/src/sqlbuild/compiler/analysis_session/_helpers/session_rows.py index 99cd11b33f..01ffc36212 100644 --- a/src/sqlbuild/compiler/analysis_session/_helpers/session_rows.py +++ b/src/sqlbuild/compiler/analysis_session/_helpers/session_rows.py @@ -5,19 +5,14 @@ from collections.abc import Mapping from sqlbuild.adapter.contract.models import ExpressionInferenceProfile -from sqlbuild.adapter.contract.types import FunctionNullabilityRule -from sqlbuild.adapter.type_system.main.conditional_result_nullability import ( - conditional_result_nullability, -) -from sqlbuild.adapter.type_system.main.first_arg_nullability import first_arg_nullability -from sqlbuild.compiler.analysis_session.constants import ( - NULLABILITY_RULE_CONDITIONAL_RESULT, - NULLABILITY_RULE_FIRST_ARG, +from sqlbuild.compiler.analysis_session._helpers.profile_rows import ( + case_sensitive_shapes, + nullability_rule_rows, + shape_rows, ) from sqlbuild.compiler.analysis_session.models import NativeModelAnalysisRequest from sqlbuild.compiler.analysis_session.types import ( ColumnRow, - DeferredRow, DiagnosticRow, FamilyRow, LineageItem, @@ -32,50 +27,27 @@ DynamicColumnContractProof, DynamicColumnFamilyProof, InferredColumn, - PolyglotAnalysisResult, ) from sqlbuild.compiler.lineage.types import InferredNullability -from sqlbuild.compiler.sql_analysis.constants import CASE_SENSITIVE_BINDING_DIALECTS from sqlbuild.compiler.sql_analysis.models import SqlBindingDiagnostic from sqlbuild.spec.contracts.models import SchemaDynamicColumnFamily -_NULLABILITY_RULE_IDS: dict[FunctionNullabilityRule, str] = { - first_arg_nullability: NULLABILITY_RULE_FIRST_ARG, - conditional_result_nullability: NULLABILITY_RULE_CONDITIONAL_RESULT, -} - - -def shape_rows(shapes: Mapping[str, Mapping[str, object]]) -> ShapeRows | None: - """`{relation: {column: value}}` as ordered rows, or None when a value is not text.""" - - rows: ShapeRows = [] - for name, shape in shapes.items(): - columns: list[tuple[str, str]] = [] - for column, value in shape.items(): - if not isinstance(column, str) or not isinstance(value, str): - return None - columns.append((column, str(value))) - rows.append((name, columns)) - return rows - def session_request( *, request: NativeModelAnalysisRequest, python: PythonModelAnalysis, schemas: Mapping[str, Mapping[str, str]], -) -> tuple[object, ...] | None: - """The session request, or None when a shape cannot cross as text.""" +) -> tuple[object, ...]: + """The session request.""" profile: ExpressionInferenceProfile = request.inference_profile - shapes: tuple[ShapeRows | None, ...] = ( + shapes: tuple[ShapeRows, ...] = ( shape_rows(request.column_types_by_table), shape_rows(request.column_nullability_by_table), shape_rows(request.complete_binding_schemas), shape_rows(schemas), ) - if any(rows is None for rows in shapes): - return None return ( profile.sql_analysis_dialect or "generic", case_sensitive_shapes(profile=profile, dialect=profile.sql_analysis_dialect), @@ -88,20 +60,8 @@ def session_request( ) -def nullability_rule_rows(profile: ExpressionInferenceProfile) -> list[tuple[str, str]] | None: - """Adapter nullability rules as `(name, rule id)`, or None for a rule SQLBuild lacks.""" - - rows: list[tuple[str, str]] = [] - for name, rule in profile.function_nullability_rules.items(): - rule_id: str | None = _NULLABILITY_RULE_IDS.get(rule) - if rule_id is None: - return None - rows.append((name, rule_id)) - return rows - - def contract_proof(row: ProofRow | None) -> DynamicColumnContractProof | None: - """A native dynamic pivot proof as Python's, None when absent or left to Python.""" + """A native dynamic pivot proof as Python's, None when absent.""" if row is None: return None @@ -119,12 +79,6 @@ def contract_proof(row: ProofRow | None) -> DynamicColumnContractProof | None: ) -def case_sensitive_shapes(*, profile: ExpressionInferenceProfile, dialect: str | None) -> bool: - """Python's `inferred_binding_shape` test for keeping authored identifier quoting.""" - - return not profile.quoted_identifiers_ignore_case and dialect in CASE_SENSITIVE_BINDING_DIALECTS - - def column_rows(columns: tuple[InferredColumn, ...] | None) -> list[ColumnRow] | None: if columns is None: return None @@ -146,20 +100,6 @@ def diagnostic_rows(diagnostics: tuple[SqlBindingDiagnostic, ...]) -> list[Diagn ] -def deferred_row(*, model: int, analysis: PolyglotAnalysisResult) -> DeferredRow: - """Python's answer to one deferral, without the lineage Python keeps.""" - - return ( - model, - analysis.analysis_succeeded, - column_rows(analysis.columns), - analysis.has_star, - analysis.star_resolved, - diagnostic_rows(analysis.binding_diagnostics), - analysis.binding_validated, - ) - - def inferred_columns(rows: list[ColumnRow] | None) -> tuple[InferredColumn, ...] | None: if rows is None: return None diff --git a/src/sqlbuild/compiler/analysis_session/classes/native_model_analysis.py b/src/sqlbuild/compiler/analysis_session/classes/native_model_analysis.py index e3d4950bf6..9068596130 100644 --- a/src/sqlbuild/compiler/analysis_session/classes/native_model_analysis.py +++ b/src/sqlbuild/compiler/analysis_session/classes/native_model_analysis.py @@ -1,39 +1,26 @@ -"""One compile's native model analysis, with Python answering the session's deferrals.""" +"""One compile's native model analysis, read into Python's analysis objects.""" from __future__ import annotations import logging -from collections import Counter from collections.abc import Sequence from typing import Any import sqlbuild._native as _native -from sqlbuild.compiler.analysis_session._helpers.deferral_records import record_analysis_deferral from sqlbuild.compiler.analysis_session._helpers.session_rows import ( binding_diagnostics, compact_lineage, contract_proof, - deferred_row, lineage_facts, ) from sqlbuild.compiler.analysis_session.constants import ( - CONTRACT_DEFERRED, - DEFERRAL_ANALYSIS, - DEFERRAL_DYNAMIC_PIVOT, - DEFERRAL_ENRICHMENT, - DEFERRAL_LEGACY_ANALYSIS, - DEFERRAL_SESSION, - LINEAGE_FACTS, LINEAGE_NATIVE, NATIVE_ANALYSIS_FAILURE_MESSAGE, NATIVE_ANALYSIS_STORE_FAILURE_MESSAGE, - NATIVE_SESSION_FAILURE_MESSAGE, ) from sqlbuild.compiler.analysis_session.models import NativeModelAnalysisRequest from sqlbuild.compiler.analysis_session.types import ( ColumnRow, - DeferralRow, - DeferredRow, FinishRow, OutcomeRow, ProofRow, @@ -55,7 +42,7 @@ class NativeModelAnalysis: - """Drive one native session, answering deferrals with today's Python analysis.""" + """Drive one native session and read its outcomes as Python's analyses.""" def __init__( self, @@ -70,40 +57,32 @@ def __init__( self._nullability: dict[str, dict[str, InferredNullability]] = dict( request.column_nullability_by_table ) - self._kept: dict[tuple[int, str], PolyglotAnalysisResult] = {} self._columns: dict[ColumnRow, InferredColumn] = {} - self._deferrals: Counter[str] = Counter() - def analyses( - self, session: _native.NativeModelAnalysisSession - ) -> dict[str, ModelSqlAnalysis] | None: - """Every model's analysis by name, or None when Python must analyse them all.""" + def analyses(self, session: _native.NativeModelAnalysisSession) -> dict[str, ModelSqlAnalysis]: + """Every model's analysis by name; a native internal failure raises.""" - finished: FinishRow | None = self._finished(session) - if finished is None: - record_analysis_deferral(kind=DEFERRAL_SESSION) + step: StepRow = session.run() + publications, failures = step + for failure in failures: log_debug_event( logger=_DEBUG_LOGGER, - message=NATIVE_SESSION_FAILURE_MESSAGE, - sqlbuild_error=session.failure, + message=NATIVE_ANALYSIS_FAILURE_MESSAGE, + sqlbuild_error=failure, ) - return None + self._publish(publications) + finished: FinishRow = session.finish() outcomes, schema_additions, analysis_names, contracts = finished self._record_catalog_changes( schema_additions=schema_additions, analysis_names=analysis_names ) - self._deferrals[DEFERRAL_DYNAMIC_PIVOT] += sum( - kind == CONTRACT_DEFERRED for kind, _ in contracts - ) - for kind, count in self._deferrals.items(): - record_analysis_deferral(kind=kind, count=count) self._record_cache(session) return { request.model_input.model_file.file_path.stem: self._model_analysis( - index=index, request=request, outcome=outcome, contract=contract + request=request, outcome=outcome, contract=contract ) - for index, (request, outcome, (_, contract)) in enumerate( - zip(self._python.requests, outcomes, contracts, strict=True) + for request, outcome, (_, contract) in zip( + self._python.requests, outcomes, contracts, strict=True ) } @@ -124,25 +103,6 @@ def _record_cache(self, session: _native.NativeModelAnalysisSession) -> None: return self._python.record_cached(hits=hits, misses=misses) - def _finished(self, session: _native.NativeModelAnalysisSession) -> FinishRow | None: - step: StepRow | None = session.run() - while step is not None: - publications, deferrals, failures = step - for failure in failures: - log_debug_event( - logger=_DEBUG_LOGGER, - message=NATIVE_ANALYSIS_FAILURE_MESSAGE, - sqlbuild_error=failure, - ) - self._publish(publications) - if not deferrals: - return session.finish() - answers: list[DeferredRow] = [self._answer(deferral) for deferral in deferrals] - if not session.provide(answers): - return None - step = session.run() - return None - def _publish(self, publications: ShapeRows) -> None: for name, shape in publications: published: dict[str, str] = dict(shape) @@ -151,29 +111,6 @@ def _publish(self, publications: ShapeRows) -> None: name, dict.fromkeys(published, InferredNullability.UNKNOWN) ) - def _answer(self, deferral: DeferralRow) -> DeferredRow: - kind, model, cleaned_sql, schemas, diagnostics, lineage = deferral - shapes: dict[str, dict[str, str]] = {name: dict(shape) for name, shape in schemas} - analysis: PolyglotAnalysisResult - if kind == DEFERRAL_ANALYSIS: - self._deferrals[DEFERRAL_LEGACY_ANALYSIS] += 1 - analysis = self._python.analyze_deferred( - model=model, - precomputed=PythonModelAnalysis.legacy_precomputed( - cleaned_sql=cleaned_sql or "", - binding_diagnostics=binding_diagnostics(diagnostics), - lineage=lineage, - ), - binding_schema=shapes, - column_types_by_table=self._types, - column_nullability_by_table=self._nullability, - ) - else: - self._deferrals[DEFERRAL_ENRICHMENT] += 1 - analysis = self._python.enrich(model=model, input_schemas=shapes) - self._kept[(model, kind)] = analysis - return deferred_row(model=model, analysis=analysis) - def _record_catalog_changes( self, *, schema_additions: ShapeRows, analysis_names: list[str] ) -> None: @@ -216,7 +153,6 @@ def _inferred_column(self, row: ColumnRow) -> InferredColumn: def _model_analysis( self, *, - index: int, request: ModelSqlAnalysisRequest, outcome: OutcomeRow, contract: ProofRow | None, @@ -236,8 +172,6 @@ def _model_analysis( (compact_lineage(lineage_rows) if succeeded else ()) if lineage_source == LINEAGE_NATIVE else lineage_facts(lineage_rows) - if lineage_source == LINEAGE_FACTS - else self._kept[(index, lineage_source)].lineage_columns ) return ModelSqlAnalysis( polyglot_analysis=PolyglotAnalysisResult( diff --git a/src/sqlbuild/compiler/analysis_session/constants.py b/src/sqlbuild/compiler/analysis_session/constants.py index 265104358b..769d729c97 100644 --- a/src/sqlbuild/compiler/analysis_session/constants.py +++ b/src/sqlbuild/compiler/analysis_session/constants.py @@ -1,23 +1,14 @@ """Native model analysis session constants.""" ANALYSIS_DEFERRAL_SITE: str = "analysis_session" -DEFERRAL_NO_COMPACT_ANALYSIS: str = "no_compact_analysis" -DEFERRAL_NO_CATALOG: str = "no_analysis_catalog" -DEFERRAL_SESSION: str = "session" -DEFERRAL_LEGACY_ANALYSIS: str = "legacy_analysis" -DEFERRAL_ENRICHMENT: str = "input_enrichment" -DEFERRAL_DYNAMIC_PIVOT: str = "dynamic_pivot" -DEFERRAL_EXPRESSION_SHAPES: str = "expression_shapes" -DEFERRAL_ANALYSIS: str = "analysis" -DEFERRAL_ENRICH: str = "enrichment" LINEAGE_NATIVE: str = "native" LINEAGE_FACTS: str = "facts" -CONTRACT_DEFERRED: str = "deferred" NATIVE_ANALYSIS_FAILURE_MESSAGE: str = "native compact query analysis failed" -NATIVE_SESSION_FAILURE_MESSAGE: str = "native model analysis failed; falling back" -NATIVE_SHAPES_FAILURE_MESSAGE: str = "native expression-source shape inference failed; falling back" NULLABILITY_RULE_FIRST_ARG: str = "first_arg" NULLABILITY_RULE_CONDITIONAL_RESULT: str = "conditional_result" +NULLABILITY_RULE_SAFE_CAST: str = "safe_cast" +NULLABILITY_RULE_ADAPTER: str = "python" +ADAPTER_NULLABILITY_CALLBACK: str = "adapter_nullability_callback" NATIVE_ANALYSIS_STORE_FILE_NAME: str = "model-analyses.bin" NATIVE_ANALYSIS_STORE_VERSION: str = "native-model-analysis-store-v1" NATIVE_ANALYSIS_STORE_FAILURE_MESSAGE: str = "native model analysis cache not read or saved" diff --git a/src/sqlbuild/compiler/analysis_session/main/_analyze_native_model_sql.py b/src/sqlbuild/compiler/analysis_session/main/_analyze_native_model_sql.py index 8f72279583..1e808be7bd 100644 --- a/src/sqlbuild/compiler/analysis_session/main/_analyze_native_model_sql.py +++ b/src/sqlbuild/compiler/analysis_session/main/_analyze_native_model_sql.py @@ -9,7 +9,7 @@ ) -def analyze_native_model_sql(*, request: NativeModelAnalysisRequest) -> NativeModelAnalyses | None: - """Return each model's analysis (and pivot proof) and the session, or None to defer.""" +def analyze_native_model_sql(*, request: NativeModelAnalysisRequest) -> NativeModelAnalyses: + """Return each model's analysis (and pivot proof) and the session.""" return native_model_analyses(request=request) diff --git a/src/sqlbuild/compiler/analysis_session/main/_infer_native_expression_source_shapes.py b/src/sqlbuild/compiler/analysis_session/main/_infer_native_expression_source_shapes.py index 53cb602fc9..7509f3c4f5 100644 --- a/src/sqlbuild/compiler/analysis_session/main/_infer_native_expression_source_shapes.py +++ b/src/sqlbuild/compiler/analysis_session/main/_infer_native_expression_source_shapes.py @@ -1,4 +1,4 @@ -"""Infer expression-source shapes natively for the preview compiler engine.""" +"""Infer expression-source shapes natively.""" from __future__ import annotations @@ -10,7 +10,7 @@ def infer_native_expression_source_shapes( *, expressions: tuple[str, ...], profile: ExpressionInferenceProfile -) -> tuple[dict[str, str] | None, ...] | None: - """Return one shape per expression, or None where Python must infer the shapes.""" +) -> tuple[dict[str, str] | None, ...]: + """One shape per expression; a native internal failure raises `NativeCompilerError`.""" return native_expression_source_shapes(expressions=expressions, profile=profile) diff --git a/src/sqlbuild/compiler/analysis_session/main/_infer_native_query_columns.py b/src/sqlbuild/compiler/analysis_session/main/_infer_native_query_columns.py new file mode 100644 index 0000000000..b4837e9689 --- /dev/null +++ b/src/sqlbuild/compiler/analysis_session/main/_infer_native_query_columns.py @@ -0,0 +1,27 @@ +"""Infer the output columns of queries outside the native analysis session.""" + +from __future__ import annotations + +from collections.abc import Mapping, Sequence + +from sqlbuild.adapter.contract.models import ExpressionInferenceProfile +from sqlbuild.compiler.analysis_session._helpers.query_columns import native_query_columns +from sqlbuild.compiler.analysis_session.models import NativeColumnQuery, NativeQueryColumns +from sqlbuild.compiler.lineage.types import InferredNullability + + +def infer_native_query_columns( + *, + queries: Sequence[NativeColumnQuery], + profile: ExpressionInferenceProfile, + column_types_by_table: Mapping[str, Mapping[str, str]] | None = None, + column_nullability_by_table: Mapping[str, Mapping[str, InferredNullability]] | None = None, +) -> tuple[NativeQueryColumns, ...]: + """Each query's columns; a native internal failure raises `NativeCompilerError`.""" + + return native_query_columns( + queries=queries, + profile=profile, + column_types_by_table=column_types_by_table or {}, + column_nullability_by_table=column_nullability_by_table or {}, + ) diff --git a/src/sqlbuild/compiler/analysis_session/models.py b/src/sqlbuild/compiler/analysis_session/models.py index 2db27e023e..3fd27e09bc 100644 --- a/src/sqlbuild/compiler/analysis_session/models.py +++ b/src/sqlbuild/compiler/analysis_session/models.py @@ -6,9 +6,12 @@ from typing import Any from sqlbuild.adapter.contract.models import ExpressionInferenceProfile +from sqlbuild.compiler.analysis_session.types import QueryColumnsMode from sqlbuild.compiler.compile.models import ( AnalysisCacheContext, CompileModelInput, + CompileSqlReference, + InferredColumn, ModelSqlAnalysis, ) from sqlbuild.compiler.lineage.types import InferredNullability @@ -49,3 +52,23 @@ class NativePivotTables: authoritative_column_types_by_table: dict[str, dict[str, str]] column_nullability_by_table: dict[str, dict[str, InferredNullability]] dynamic_families_by_table: dict[str, tuple[SchemaDynamicColumnFamily, ...]] + + +@dataclass(frozen=True, slots=True) +class NativeColumnQuery: + """One query outside the session whose output columns Python's analysis inferred.""" + + sql: str + mode: QueryColumnsMode + placeholders: dict[str, str] | None = None + references: tuple[CompileSqlReference, ...] = () + recover_cte_facts: bool = True + + +@dataclass(frozen=True, slots=True) +class NativeQueryColumns: + """One query's analysis: whether it succeeded, its columns and whether it projects a star.""" + + succeeded: bool + columns: tuple[InferredColumn, ...] | None + has_star: bool diff --git a/src/sqlbuild/compiler/analysis_session/types.py b/src/sqlbuild/compiler/analysis_session/types.py index 8fcf150865..bfa4f7e783 100644 --- a/src/sqlbuild/compiler/analysis_session/types.py +++ b/src/sqlbuild/compiler/analysis_session/types.py @@ -2,15 +2,13 @@ from __future__ import annotations +from typing import Literal + type ShapeRows = list[tuple[str, list[tuple[str, str]]]] type ColumnRow = tuple[str, str | None, str] type DiagnosticRow = tuple[str, str, int | None, int | None, int | None, int | None, str] type LineageItem = tuple[str, int, int, list[tuple[str, str, str]]] -type DeferredRow = tuple[int, bool, list[ColumnRow] | None, bool, bool, list[DiagnosticRow], bool] -type DeferralRow = tuple[ - str, int, str | None, ShapeRows, list[DiagnosticRow], list[LineageItem] | None -] -type StepRow = tuple[ShapeRows, list[DeferralRow], list[str]] +type StepRow = tuple[ShapeRows, list[str]] type OutcomeRow = tuple[ bool, list[ColumnRow] | None, @@ -28,3 +26,5 @@ ] type ContractRow = tuple[str, ProofRow | None] type FinishRow = tuple[list[OutcomeRow], ShapeRows, list[str], list[ContractRow]] + +type QueryColumnsMode = Literal["batch", "reanalysis", "parse", "legacy"] diff --git a/src/sqlbuild/compiler/compile/_helpers/analysis/binding_requests.py b/src/sqlbuild/compiler/compile/_helpers/analysis/binding_requests.py new file mode 100644 index 0000000000..35c2a57dbd --- /dev/null +++ b/src/sqlbuild/compiler/compile/_helpers/analysis/binding_requests.py @@ -0,0 +1,33 @@ +"""Native schema-validation requests for model SQL.""" + +from __future__ import annotations + +from sqlbuild.compiler.sql_analysis.main._normalize_analysis import normalize_analysis_sql +from sqlbuild.compiler.sql_analysis.models import ( + SqlSchemaValidationRequest, +) + + +def get_complete_schema_binding_request( + *, + query_sql: str, + placeholders: dict[str, str] | None, + dialect: str | None, + binding_schema: dict[str, dict[str, str]], + known_functions: tuple[str, ...] = (), + known_types: tuple[str, ...] = (), + cleaned_sql: str | None = None, +) -> SqlSchemaValidationRequest: + """Build one stable native schema-validation request.""" + + if cleaned_sql is None: + cleaned_sql = normalize_analysis_sql( + sql=query_sql, dialect=dialect, placeholders=placeholders + ) + return SqlSchemaValidationRequest( + sql=cleaned_sql, + dialect=dialect, + schema=binding_schema, + known_functions=known_functions, + known_types=known_types, + ) diff --git a/src/sqlbuild/compiler/compile/_helpers/analysis/cache.py b/src/sqlbuild/compiler/compile/_helpers/analysis/cache.py index 10a92d3e45..2ae479e965 100644 --- a/src/sqlbuild/compiler/compile/_helpers/analysis/cache.py +++ b/src/sqlbuild/compiler/compile/_helpers/analysis/cache.py @@ -1,109 +1,22 @@ -"""Versioned project-local cache for deterministic model SQL analysis facts.""" +"""The analysis cache context and the model analysis cache metrics.""" from __future__ import annotations import hashlib -import hmac import inspect import json import platform -import sqlite3 -import time -from collections import defaultdict, deque -from collections.abc import Sequence from importlib.metadata import PackageNotFoundError, version from pathlib import Path -from string import hexdigits -from typing import Any, cast - -import orjson from sqlbuild.adapter.contract.models import ExpressionInferenceProfile -from sqlbuild.compiler.compile._helpers.analysis.columns import table_function_analysis_name -from sqlbuild.compiler.compile.exceptions import AnalysisCacheEntryError -from sqlbuild.compiler.compile.models import ( - AnalysisCacheContext, - CompactAnalysisCacheCandidate, - CompactAnalysisCacheModel, - CompactAnalysisCachePlan, - CompactBatchPreparation, - CompactLineageFacts, - CompiledLineageColumnFact, - CompiledLineageSourceFact, - CompileSqlReference, - InferredColumn, - PolyglotAnalysisResult, -) -from sqlbuild.compiler.compile.types import CompactBatchResponseCallback, CompiledResourceType -from sqlbuild.compiler.lineage.types import ( - ColumnLineageConfidence, - ColumnTransformKind, - InferredNullability, -) +from sqlbuild.compiler.compile.models import AnalysisCacheContext from sqlbuild.compiler.profiling.main._metric import record_compile_metric -from sqlbuild.compiler.profiling.main.record import record_compile_timing -from sqlbuild.compiler.references.types import SqlReferenceKind -from sqlbuild.compiler.sql_analysis.constants import BINDING_SEVERITIES, TYPE_CHECKED_DIALECTS -from sqlbuild.compiler.sql_analysis.models import SqlBindingDiagnostic +from sqlbuild.compiler.sql_analysis.constants import TYPE_CHECKED_DIALECTS _ANALYSIS_CACHE_VERSION: int = 13 _ANALYSIS_ALGORITHM_FINGERPRINT: str = "model-sql-analysis-v21-completed-star-shapes" -_LINEAGE_COLUMN_VALUE_COUNT: int = 4 -_LINEAGE_SOURCE_VALUE_COUNT: int = 3 -_COMPACT_TRANSFORM_CODES: dict[str, int] = { - CompactLineageFacts.transform_kind(code).value: code for code in range(6) -} -_COMPACT_CONFIDENCE_CODES: dict[str, int] = { - CompactLineageFacts.confidence(code).value: code for code in range(3) -} -_COMPACT_TRANSFORM_VALUES: tuple[str, ...] = tuple(_COMPACT_TRANSFORM_CODES) -_COMPACT_CONFIDENCE_VALUES: tuple[str, ...] = tuple(_COMPACT_CONFIDENCE_CODES) -_RESOURCE_TYPE_VALUES: frozenset[str] = frozenset(item.value for item in CompiledResourceType) -_NULLABILITY_BY_VALUE: dict[str, InferredNullability] = { - item.value: item for item in InferredNullability -} -_MAX_CACHE_ENTRY_BYTES: int = 10_000_000 -_SHA256_HEX_LENGTH: int = 64 -_CACHE_ENTRY_SEPARATOR: str = "\n" _LOCAL_QUALNAME_MARKER: str = "" -_SQLITE_QUERY_CHUNK_SIZE: int = 500 -_SQLITE_TIMEOUT_SECONDS: float = 0.1 -_CACHE_DATABASE_NAME: str = "model-analysis.sqlite3" -_COMPACT_BATCH_CACHE_VERSION: int = 1 -_MAX_COMPACT_BATCH_BYTES: int = 128 * 1024 * 1024 -_MAX_COMPACT_BATCH_RECORDS: int = 2 -_CREATE_CACHE_TABLE_SQL: str = """ -CREATE TABLE IF NOT EXISTS model_analysis ( - cache_key TEXT PRIMARY KEY, - payload TEXT NOT NULL -) -""" -_CREATE_SIGNATURE_TABLE_SQL: str = """ -CREATE TABLE IF NOT EXISTS model_analysis_signature ( - shared_fingerprint TEXT NOT NULL, - signature_namespace TEXT NOT NULL, - model_name TEXT NOT NULL, - output_signature TEXT NOT NULL, - PRIMARY KEY (shared_fingerprint, signature_namespace, model_name) -) -""" -_CREATE_DEPENDENCY_TABLE_SQL: str = """ -CREATE TABLE IF NOT EXISTS model_analysis_dependency ( - signature_namespace TEXT NOT NULL, - cache_key TEXT NOT NULL, - upstream_model_name TEXT NOT NULL, - output_signature TEXT NOT NULL, - PRIMARY KEY (signature_namespace, cache_key, upstream_model_name) -) -""" -_CREATE_COMPACT_BATCH_TABLE_SQL: str = """ -CREATE TABLE IF NOT EXISTS model_analysis_compact_batch ( - batch_key TEXT PRIMARY KEY, - shared_fingerprint TEXT NOT NULL, - payload BLOB NOT NULL, - created_ns INTEGER NOT NULL -) -""" def build_analysis_cache_context( @@ -142,186 +55,6 @@ def build_analysis_cache_context( return None -def model_analysis_cache_key( - *, - context: AnalysisCacheContext, - query_sql: str, - references: tuple[CompileSqlReference, ...], - placeholders: dict[str, str] | None, - column_nullability_by_table: dict[str, dict[str, InferredNullability]], - column_types_by_table: dict[str, dict[str, str]], - binding_schema: dict[str, dict[str, str]] | None = None, - recover_cte_facts: bool = False, -) -> str: - """Return the exact analysis identity for one expanded model query.""" - - payload: dict[str, object] = { - "shared_fingerprint": context.shared_fingerprint, - "query_sql": query_sql, - "references": [ - { - "kind": str(reference.ref_kind), - "name": reference.ref_name, - "package": reference.ref_package, - "call_argument_count": reference.call_argument_count, - } - for reference in references - ], - "placeholders": dict(sorted((placeholders or {}).items())), - "referenced_column_nullability": _referenced_nullability_payload( - references=references, - column_nullability_by_table=column_nullability_by_table, - ), - "referenced_column_types": _referenced_types_payload( - references=references, - column_types_by_table=column_types_by_table, - ), - "binding_schema": binding_schema, - } - if recover_cte_facts: - payload["recover_cte_facts"] = True - return _json_value_digest(payload) - - -def compact_analysis_batch_cache_key( - *, context: AnalysisCacheContext, reuse_keys: tuple[str, ...] -) -> str: - """Return the exact identity of one ordered whole-project compact analysis batch.""" - - return _payload_digest( - { - "cache_version": _ANALYSIS_CACHE_VERSION, - "compact_batch_version": _COMPACT_BATCH_CACHE_VERSION, - "shared_fingerprint": context.shared_fingerprint, - "reuse_keys": reuse_keys, - } - ) - - -def compact_analysis_model_reuse_key( - *, cache_key: str, upstream_reuse_keys: tuple[tuple[str, str], ...] -) -> str: - """Return one model key that changes with every transitive model dependency.""" - - return _json_value_digest( - { - "cache_key": cache_key, - "upstream": upstream_reuse_keys, - } - ) - - -def build_compact_analysis_cache_plan( - *, - context: AnalysisCacheContext | None, - models: tuple[CompactAnalysisCacheModel, ...], - min_model_count: int, -) -> CompactAnalysisCachePlan | None: - """Build a dependency-aware ordered batch identity when every model is cacheable.""" - - if context is None or len(models) < min_model_count: - return None - models_by_name: dict[str, CompactAnalysisCacheModel] = {model.name: model for model in models} - dependencies_by_name: dict[str, tuple[str, ...]] = {} - for model in models: - dependencies_by_name[model.name] = tuple( - name for name in model.upstream_names if name in models_by_name - ) - dependents_by_name: dict[str, list[str]] = defaultdict(list) - remaining_dependency_count: dict[str, int] = {} - for model_name, dependencies in dependencies_by_name.items(): - remaining_dependency_count[model_name] = len(dependencies) - for dependency in dependencies: - dependents_by_name[dependency].append(model_name) - resolved: dict[str, str] = {} - ready: deque[str] = deque( - sorted(name for name, count in remaining_dependency_count.items() if count == 0) - ) - while ready: - model_name: str = ready.popleft() - model: CompactAnalysisCacheModel = models_by_name[model_name] - if model.cache_key is None: - return None - resolved[model_name] = compact_analysis_model_reuse_key( - cache_key=model.cache_key, - upstream_reuse_keys=tuple( - (upstream_name, resolved[upstream_name]) - for upstream_name in dependencies_by_name[model_name] - ), - ) - for dependent_name in sorted(dependents_by_name.get(model_name, ())): - remaining_dependency_count[dependent_name] -= 1 - if remaining_dependency_count[dependent_name] == 0: - ready.append(dependent_name) - if len(resolved) != len(models): - return None - cache_keys: tuple[str, ...] = tuple( - model.cache_key for model in models if model.cache_key is not None - ) - if len(cache_keys) != len(models): - return None - reuse_keys: tuple[str, ...] = tuple(resolved[model.name] for model in models) - return CompactAnalysisCachePlan( - context=context, - batch_key=compact_analysis_batch_cache_key(context=context, reuse_keys=reuse_keys), - cache_keys=cache_keys, - reuse_keys=reuse_keys, - ) - - -def read_compact_analysis_cache_candidate( - *, plan: CompactAnalysisCachePlan, expected_count: int, min_model_count: int -) -> CompactAnalysisCacheCandidate | None: - """Read one compatible generation and locate dependency-safe matching positions.""" - - cached: tuple[tuple[str, ...], tuple[str, ...], tuple[str, ...], object] | None = ( - read_compact_analysis_batch(context=plan.context, batch_key=plan.batch_key) - ) - if cached is None: - return None - stored_cache_keys, stored_reuse_keys, cleaned_sql, response = cached - matching_indexes: tuple[int, ...] = tuple( - index - for index, (stored_key, current_key) in enumerate( - zip(stored_reuse_keys, plan.reuse_keys, strict=False) - ) - if stored_key == current_key - ) - if len(stored_cache_keys) != expected_count or len(matching_indexes) < min_model_count: - return None - return CompactAnalysisCacheCandidate( - matching_indexes=matching_indexes, - preparation=CompactBatchPreparation( - cleaned_sql=cleaned_sql, - queries=(), - templates=(), - projections=(), - ), - response=response, - ) - - -def compact_analysis_batch_response_writer( - *, plan: CompactAnalysisCachePlan, count: int -) -> CompactBatchResponseCallback: - """Build a callback that publishes one complete compact generation.""" - - def write(*, preparation: CompactBatchPreparation, response: object) -> None: - if len(preparation.cleaned_sql) != count: - return - with record_compile_timing("cache_publication_ms"): - write_compact_analysis_batch( - context=plan.context, - batch_key=plan.batch_key, - cache_keys=plan.cache_keys, - reuse_keys=plan.reuse_keys, - cleaned_sql=preparation.cleaned_sql, - response=response, - ) - - return write - - def record_analysis_cache_metrics( *, batch_hits: int, entry_hits: int, misses: int, bypasses: int ) -> None: @@ -333,399 +66,6 @@ def record_analysis_cache_metrics( record_compile_metric(metric="analysis_cache_bypasses", value=bypasses) -def read_compact_analysis_batch( - *, context: AnalysisCacheContext, batch_key: str -) -> tuple[tuple[str, ...], tuple[str, ...], tuple[str, ...], object] | None: - """Read the newest compatible compact generation, treating every fault as a miss.""" - - database_path: Path = _cache_database_path(context=context) - if not database_path.is_file(): - return None - try: - connection_uri: str = f"file:{database_path}?mode=ro" - with sqlite3.connect( - connection_uri, - uri=True, - timeout=_SQLITE_TIMEOUT_SECONDS, - ) as connection: - metadata_row: tuple[str, int] | None = connection.execute( - "SELECT batch_key, length(payload) FROM model_analysis_compact_batch " - "WHERE batch_key = ?", - (batch_key,), - ).fetchone() - if metadata_row is None: - metadata_row = connection.execute( - "SELECT batch_key, length(payload) FROM model_analysis_compact_batch " - "WHERE shared_fingerprint = ? ORDER BY created_ns DESC LIMIT 1", - (context.shared_fingerprint,), - ).fetchone() - if metadata_row is None: - return None - stored_batch_key, payload_bytes = metadata_row - if payload_bytes < 0 or payload_bytes > _MAX_COMPACT_BATCH_BYTES: - return None - payload_row: tuple[bytes] | None = connection.execute( - "SELECT payload FROM model_analysis_compact_batch WHERE batch_key = ?", - (stored_batch_key,), - ).fetchone() - if payload_row is None: - return None - contents: bytes = payload_row[0] - if not isinstance(contents, bytes) or len(contents) != payload_bytes: - return None - envelope: object = orjson.loads(contents) - if not isinstance(envelope, dict): - return None - values: dict[str, Any] = cast(dict[str, Any], envelope) - cache_keys_value: object = values.get("cache_keys") - reuse_keys_value: object = values.get("reuse_keys") - cleaned_sql_value: object = values.get("cleaned_sql") - response: object = values.get("response") - if ( - not isinstance(cache_keys_value, list) - or not all(isinstance(value, str) for value in cache_keys_value) - or not isinstance(reuse_keys_value, list) - or not all(isinstance(value, str) for value in reuse_keys_value) - or not isinstance(cleaned_sql_value, list) - or not all(isinstance(value, str) for value in cleaned_sql_value) - ): - return None - cache_keys: tuple[str, ...] = tuple(cache_keys_value) - reuse_keys: tuple[str, ...] = tuple(reuse_keys_value) - cleaned_sql: tuple[str, ...] = tuple(cleaned_sql_value) - if ( - values.get("version") != _COMPACT_BATCH_CACHE_VERSION - or values.get("batch_key") != stored_batch_key - or values.get("shared_fingerprint") != context.shared_fingerprint - or values.get("count") != len(cache_keys) - or len(reuse_keys) != len(cache_keys) - or len(cleaned_sql) != len(cache_keys) - or not isinstance(values.get("facts_sha256"), str) - or not hmac.compare_digest( - values["facts_sha256"], - _compact_batch_facts_digest( - cache_keys=cache_keys, - reuse_keys=reuse_keys, - cleaned_sql=cleaned_sql, - response=response, - ), - ) - ): - return None - return cache_keys, reuse_keys, cleaned_sql, response - except (OSError, sqlite3.DatabaseError, TypeError, ValueError, orjson.JSONDecodeError): - return None - - -def write_compact_analysis_batch( - *, - context: AnalysisCacheContext, - batch_key: str, - cache_keys: tuple[str, ...], - reuse_keys: tuple[str, ...], - cleaned_sql: tuple[str, ...], - response: object, -) -> None: - """Persist one compact native response transactionally, with bounded logical retention.""" - - try: - if not (len(cache_keys) == len(reuse_keys) == len(cleaned_sql)): - return - contents: bytes = orjson.dumps( - { - "version": _COMPACT_BATCH_CACHE_VERSION, - "batch_key": batch_key, - "shared_fingerprint": context.shared_fingerprint, - "count": len(cleaned_sql), - "facts_sha256": _compact_batch_facts_digest( - cache_keys=cache_keys, - reuse_keys=reuse_keys, - cleaned_sql=cleaned_sql, - response=response, - ), - "cache_keys": cache_keys, - "reuse_keys": reuse_keys, - "cleaned_sql": cleaned_sql, - "response": response, - }, - option=orjson.OPT_SORT_KEYS, - ) - if len(contents) > _MAX_COMPACT_BATCH_BYTES: - return - database_path: Path = _cache_database_path(context=context) - database_path.parent.mkdir(parents=True, exist_ok=True) - with sqlite3.connect(database_path, timeout=_SQLITE_TIMEOUT_SECONDS) as connection: - _ = connection.execute(_CREATE_COMPACT_BATCH_TABLE_SQL) - _ = connection.execute( - "INSERT OR REPLACE INTO model_analysis_compact_batch " - "(batch_key, shared_fingerprint, payload, created_ns) VALUES (?, ?, ?, ?)", - (batch_key, context.shared_fingerprint, contents, time.time_ns()), - ) - _ = connection.execute( - "DELETE FROM model_analysis_compact_batch WHERE batch_key NOT IN " - "(SELECT batch_key FROM model_analysis_compact_batch " - "ORDER BY created_ns DESC LIMIT ?)", - (_MAX_COMPACT_BATCH_RECORDS,), - ) - except (OSError, sqlite3.DatabaseError, TypeError, ValueError): - return - - -def _compact_batch_facts_digest( - *, - cache_keys: tuple[str, ...], - reuse_keys: tuple[str, ...], - cleaned_sql: tuple[str, ...], - response: object, -) -> str: - digest: Any = hashlib.sha256() - for label, value in ( - (b"cache_keys\0", cache_keys), - (b"reuse_keys\0", reuse_keys), - (b"cleaned_sql\0", cleaned_sql), - (b"response\0", response), - ): - digest.update(label) - digest.update(orjson.dumps(value, option=orjson.OPT_SORT_KEYS)) - digest.update(b"\0") - return digest.hexdigest() - - -def read_model_analyses( - *, - context: AnalysisCacheContext, - cache_keys: tuple[str, ...], - model_names: tuple[str, ...], - upstream_model_names_by_key: dict[str, tuple[str, ...]], -) -> tuple[dict[str, PolyglotAnalysisResult], dict[str, str], dict[str, str]]: - """Read one consistent snapshot of analyses, dependencies, and output signatures.""" - - database_path: Path = _cache_database_path(context=context) - if not database_path.is_file() or not cache_keys: - return {}, {}, {} - analyses: dict[str, PolyglotAnalysisResult] = {} - signatures: dict[str, str] = {} - output_signatures_by_key: dict[str, str] = {} - sources: _LineageSourceInterner = _LineageSourceInterner() - try: - connection_uri: str = f"file:{database_path}?mode=ro" - with sqlite3.connect( - connection_uri, - uri=True, - timeout=_SQLITE_TIMEOUT_SECONDS, - ) as connection: - _ = connection.execute("BEGIN") - signature_model_name_set: set[str] = set(model_names) - upstream_names: tuple[str, ...] - for upstream_names in upstream_model_names_by_key.values(): - signature_model_name_set.update(upstream_names) - signature_model_names: tuple[str, ...] = tuple(sorted(signature_model_name_set)) - for start in range(0, len(signature_model_names), _SQLITE_QUERY_CHUNK_SIZE): - model_chunk: tuple[str, ...] = signature_model_names[ - start : start + _SQLITE_QUERY_CHUNK_SIZE - ] - model_placeholders: str = ",".join("?" for _ in model_chunk) - signature_rows: list[tuple[str, str]] = connection.execute( - f"SELECT model_name, output_signature FROM model_analysis_signature " - f"WHERE shared_fingerprint = ? AND signature_namespace = ? " - f"AND model_name IN ({model_placeholders})", - ( - context.shared_fingerprint, - context.signature_namespace, - *model_chunk, - ), - ).fetchall() - signatures.update(signature_rows) - for start in range(0, len(cache_keys), _SQLITE_QUERY_CHUNK_SIZE): - chunk: tuple[str, ...] = cache_keys[start : start + _SQLITE_QUERY_CHUNK_SIZE] - placeholders: str = ",".join("?" for _ in chunk) - rows: list[tuple[str, str]] = connection.execute( - f"SELECT cache_key, payload FROM model_analysis " - f"WHERE cache_key IN ({placeholders})", - chunk, - ).fetchall() - dependency_rows: list[tuple[str, str, str]] = connection.execute( - f"SELECT cache_key, upstream_model_name, output_signature " - f"FROM model_analysis_dependency WHERE signature_namespace = ? " - f"AND cache_key IN ({placeholders})", - (context.signature_namespace, *chunk), - ).fetchall() - dependencies_by_key: dict[str, dict[str, str]] = {} - for cache_key, upstream_name, output_signature in dependency_rows: - dependencies_by_key.setdefault(cache_key, {})[upstream_name] = output_signature - for cache_key, contents in rows: - expected_dependencies: dict[str, str] | None = _expected_dependencies( - upstream_model_names=upstream_model_names_by_key.get(cache_key, ()), - signatures=signatures, - ) - if ( - expected_dependencies is None - or dependencies_by_key.get(cache_key, {}) != expected_dependencies - ): - continue - cached_result: tuple[PolyglotAnalysisResult, str] | None = ( - _analysis_from_contents( - contents=contents, - expected_cache_key=cache_key, - sources=sources, - ) - ) - if cached_result is not None: - analysis, output_signature = cached_result - analyses[cache_key] = analysis - output_signatures_by_key[cache_key] = output_signature - except (OSError, sqlite3.DatabaseError): - return {}, {}, {} - return analyses, signatures, output_signatures_by_key - - -def write_model_analyses( - *, - context: AnalysisCacheContext, - analyses_by_key: dict[str, PolyglotAnalysisResult], - latest_analyses_by_model: dict[str, PolyglotAnalysisResult] | None = None, - dependency_signatures_by_key: dict[str, dict[str, str]] | None = None, -) -> None: - """Transactionally persist deterministic analyses; cache failures never fail compilation.""" - - signed_analyses: dict[int, PolyglotAnalysisResult] = { - id(analysis): analysis - for analysis in (*analyses_by_key.values(), *(latest_analyses_by_model or {}).values()) - } - output_signatures: dict[int, str] = { - key: model_analysis_output_signature(analysis) for key, analysis in signed_analyses.items() - } - rows: list[tuple[str, str]] = [] - for cache_key, analysis in analyses_by_key.items(): - try: - contents: str = _analysis_contents( - cache_key=cache_key, - analysis=analysis, - output_signature=output_signatures[id(analysis)], - ) - except orjson.JSONEncodeError: - continue - if len(contents.encode()) <= _MAX_CACHE_ENTRY_BYTES: - rows.append((cache_key, contents)) - signature_rows: list[tuple[str, str, str, str]] = [ - ( - context.shared_fingerprint, - context.signature_namespace, - model_name, - output_signatures[id(analysis)], - ) - for model_name, analysis in (latest_analyses_by_model or {}).items() - ] - dependency_rows: list[tuple[str, str, str, str]] = [] - for cache_key, dependencies in (dependency_signatures_by_key or {}).items(): - analysis: PolyglotAnalysisResult | None = analyses_by_key.get(cache_key) - if analysis is None: - continue - dependency_rows.extend( - (context.signature_namespace, cache_key, upstream_name, output_signature) - for upstream_name, output_signature in dependencies.items() - ) - if not rows and not signature_rows: - return - try: - database_path: Path = _cache_database_path(context=context) - database_path.parent.mkdir(parents=True, exist_ok=True) - with sqlite3.connect(database_path, timeout=_SQLITE_TIMEOUT_SECONDS) as connection: - _ = connection.execute(_CREATE_CACHE_TABLE_SQL) - _ = connection.execute(_CREATE_SIGNATURE_TABLE_SQL) - _ = connection.execute(_CREATE_DEPENDENCY_TABLE_SQL) - _ = connection.executemany( - "INSERT OR REPLACE INTO model_analysis (cache_key, payload) VALUES (?, ?)", - rows, - ) - written_cache_keys: tuple[str, ...] = tuple(cache_key for cache_key, _ in rows) - for start in range(0, len(written_cache_keys), _SQLITE_QUERY_CHUNK_SIZE): - chunk: tuple[str, ...] = written_cache_keys[ - start : start + _SQLITE_QUERY_CHUNK_SIZE - ] - placeholders: str = ",".join("?" for _ in chunk) - _ = connection.execute( - f"DELETE FROM model_analysis_dependency " - f"WHERE signature_namespace = ? AND cache_key IN ({placeholders})", - (context.signature_namespace, *chunk), - ) - _ = connection.executemany( - "INSERT INTO model_analysis_dependency " - "(signature_namespace, cache_key, upstream_model_name, output_signature) " - "VALUES (?, ?, ?, ?)", - dependency_rows, - ) - _ = connection.executemany( - "INSERT OR REPLACE INTO model_analysis_signature " - "(shared_fingerprint, signature_namespace, model_name, output_signature) " - "VALUES (?, ?, ?, ?)", - signature_rows, - ) - except (OSError, sqlite3.DatabaseError): - return - - -def _expected_dependencies( - *, - upstream_model_names: tuple[str, ...], - signatures: dict[str, str], -) -> dict[str, str] | None: - if any(name not in signatures for name in upstream_model_names): - return None - return {name: signatures[name] for name in upstream_model_names} - - -def model_analysis_output_signature(analysis: PolyglotAnalysisResult) -> str: - """Return the exported column signature relevant to downstream analysis.""" - - return _json_value_digest( - { - "columns": ( - None - if analysis.columns is None - else [ - { - "name": column.name, - "type": column.type, - "nullability": column.nullability.value, - } - for column in analysis.columns - ] - ), - "has_star": analysis.has_star, - "star_resolved": analysis.star_resolved, - } - ) - - -def _analysis_from_contents( - *, - contents: object, - expected_cache_key: str, - sources: _LineageSourceInterner | None = None, -) -> tuple[PolyglotAnalysisResult, str] | None: - if not isinstance(contents, str): - return None - try: - if len(contents.encode()) > _MAX_CACHE_ENTRY_BYTES: - return None - stored_digest, separator, serialized_payload = contents.partition(_CACHE_ENTRY_SEPARATOR) - if not separator or not hmac.compare_digest( - stored_digest, - _cache_entry_digest( - cache_key=expected_cache_key, - serialized_payload=serialized_payload, - ), - ): - return None - payload: object = orjson.loads(serialized_payload) - return _analysis_from_payload( - payload=payload, expected_cache_key=expected_cache_key, sources=sources - ) - except (ValueError, TypeError, KeyError, RecursionError, orjson.JSONDecodeError): - return None - - def _inference_profile_payload( profile: ExpressionInferenceProfile, ) -> dict[str, object] | None: @@ -765,372 +105,6 @@ def _inference_profile_payload( } -def _referenced_nullability_payload( - *, - references: tuple[CompileSqlReference, ...], - column_nullability_by_table: dict[str, dict[str, InferredNullability]], -) -> dict[str, dict[str, str]]: - payload: dict[str, dict[str, str]] = {} - table: str - for table in _referenced_analysis_tables(references): - columns: dict[str, InferredNullability] | None = column_nullability_by_table.get(table) - if columns is None: - continue - payload[table] = { - column: nullability.value for column, nullability in sorted(columns.items()) - } - return payload - - -def _referenced_types_payload( - *, - references: tuple[CompileSqlReference, ...], - column_types_by_table: dict[str, dict[str, str]], -) -> dict[str, dict[str, str]]: - payload: dict[str, dict[str, str]] = {} - table: str - for table in _referenced_analysis_tables(references): - columns: dict[str, str] | None = column_types_by_table.get(table) - if columns is not None: - payload[table] = dict(sorted(columns.items())) - return payload - - -def _referenced_analysis_tables( - references: tuple[CompileSqlReference, ...], -) -> tuple[str, ...]: - names: set[str] = set() - for reference in references: - names.add( - table_function_analysis_name(reference.ref_name) - if reference.ref_kind == SqlReferenceKind.TABLE_FUNCTION - else reference.ref_name - ) - return tuple(sorted(names)) - - -def _analysis_payload( - *, cache_key: str, analysis: PolyglotAnalysisResult, output_signature: str | None = None -) -> dict[str, object]: - return { - "v": _ANALYSIS_CACHE_VERSION, - "k": cache_key, - "a": analysis.analysis_succeeded, - "s": ( - model_analysis_output_signature(analysis) - if output_signature is None - else output_signature - ), - "c": ( - None - if analysis.columns is None - else [ - [column.name, column.type, column.nullability.value] for column in analysis.columns - ] - ), - "l": _lineage_payload(analysis.lineage_columns), - "h": analysis.has_star, - "sr": analysis.star_resolved, - "b": [ - [ - diagnostic.code, - diagnostic.message, - diagnostic.line, - diagnostic.column, - diagnostic.start, - diagnostic.end, - diagnostic.severity, - ] - for diagnostic in analysis.binding_diagnostics - ], - "bv": analysis.binding_validated, - } - - -def _lineage_payload(lineage_columns: Sequence[CompiledLineageColumnFact]) -> list[list[object]]: - if isinstance(lineage_columns, CompactLineageFacts): - compact: list[list[object]] | None = _compact_lineage_payload(lineage_columns) - if compact is not None: - return compact - return [_lineage_column_payload(column) for column in lineage_columns] - - -def _compact_lineage_payload(lineage: CompactLineageFacts) -> list[list[object]] | None: - """Serialise indexed rows without projecting facts; None defers to the validating projection.""" - - pool: tuple[str, ...] = lineage.string_pool - payload: list[list[object]] = [] - for name_index, transform_code, confidence_code, sources in lineage.rows: - upstream_columns: list[list[str]] = [] - for resource_type_index, resource_name_index, column_index in sources: - resource_type: str = pool[resource_type_index] - if resource_type not in _RESOURCE_TYPE_VALUES: - return None - upstream_columns.append( - [resource_type, lineage.resource_name(resource_name_index), pool[column_index]] - ) - payload.append( - [ - pool[name_index], - _COMPACT_TRANSFORM_VALUES[transform_code], - _COMPACT_CONFIDENCE_VALUES[confidence_code], - upstream_columns, - ] - ) - return payload - - -def _lineage_column_payload(column: CompiledLineageColumnFact) -> list[object]: - return [ - column.output_column, - column.transform_kind.value, - column.confidence.value, - [ - [ - str(source.resource_type), - source.resource_name, - source.column_name, - ] - for source in column.upstream_columns - ], - ] - - -def _analysis_from_payload( - *, - payload: object, - expected_cache_key: str, - sources: _LineageSourceInterner | None = None, -) -> tuple[PolyglotAnalysisResult, str]: - if not isinstance(payload, dict): - raise AnalysisCacheEntryError("analysis cache entry must be an object") - values: dict[str, Any] = cast(dict[str, Any], payload) - version_value: object = values["v"] - if type(version_value) is not int or version_value != _ANALYSIS_CACHE_VERSION: - raise AnalysisCacheEntryError("analysis cache version mismatch") - if values["k"] != expected_cache_key: - raise AnalysisCacheEntryError("analysis cache key mismatch") - analysis_succeeded: object = values["a"] - if not isinstance(analysis_succeeded, bool): - raise AnalysisCacheEntryError("analysis cache success flag must be a boolean") - output_signature: object = values["s"] - if not ( - isinstance(output_signature, str) - and len(output_signature) == _SHA256_HEX_LENGTH - and all(character in hexdigits for character in output_signature) - ): - raise AnalysisCacheEntryError("analysis cache output signature is invalid") - columns_payload: object = values["c"] - columns: tuple[InferredColumn, ...] | None = ( - None - if columns_payload is None - else tuple(_column_from_payload(column) for column in _value_lists(columns_payload)) - ) - lineage_payload: list[list[object]] = _value_lists(values["l"]) - lineage_columns: Sequence[CompiledLineageColumnFact] | None = _compact_lineage_from_payload( - payload=lineage_payload - ) - if lineage_columns is None: - interner: _LineageSourceInterner = _LineageSourceInterner() if sources is None else sources - lineage_columns = tuple( - _lineage_column_from_payload(payload=column, sources=interner) - for column in lineage_payload - ) - has_star: object = values["h"] - if not isinstance(has_star, bool): - raise AnalysisCacheEntryError("analysis cache has_star must be a boolean") - binding_diagnostics: tuple[SqlBindingDiagnostic, ...] = tuple( - _binding_diagnostic_from_payload(value) for value in _value_lists(values["b"]) - ) - binding_validated: object = values["bv"] - if not isinstance(binding_validated, bool): - raise AnalysisCacheEntryError("analysis cache binding validation flag must be a boolean") - return ( - PolyglotAnalysisResult( - analysis_succeeded=analysis_succeeded, - columns=columns, - lineage_columns=lineage_columns, - has_star=has_star, - star_resolved=values.get("sr") is True, - binding_diagnostics=binding_diagnostics, - binding_validated=binding_validated, - ), - output_signature, - ) - - -def _binding_diagnostic_from_payload(payload: list[object]) -> SqlBindingDiagnostic: - diagnostic_value_count: int = 7 - if len(payload) != diagnostic_value_count: - raise AnalysisCacheEntryError("analysis cache binding diagnostic must contain seven values") - code, message, line, column, start, end, severity = payload - if severity not in BINDING_SEVERITIES: - raise AnalysisCacheEntryError("analysis cache binding diagnostic severity is invalid") - if not isinstance(code, str) or not isinstance(message, str): - raise AnalysisCacheEntryError( - "analysis cache binding diagnostic code/message must be strings" - ) - positions: tuple[object, ...] = (line, column, start, end) - if any(value is not None and not isinstance(value, int) for value in positions): - raise AnalysisCacheEntryError("analysis cache binding diagnostic positions are invalid") - return SqlBindingDiagnostic( - code=code, - message=message, - line=cast(int | None, line), - column=cast(int | None, column), - start=cast(int | None, start), - end=cast(int | None, end), - severity=cast(str, severity), - ) - - -def _value_lists(payload: object) -> list[list[object]]: - if not isinstance(payload, list) or not all(isinstance(item, list) for item in payload): - raise AnalysisCacheEntryError("analysis cache collection must contain arrays") - return cast(list[list[object]], payload) - - -def _column_from_payload(payload: list[object]) -> InferredColumn: - column_value_count: int = 3 - if len(payload) != column_value_count: - raise AnalysisCacheEntryError("analysis cache column must contain three values") - name, column_type, nullability = payload - if not isinstance(name, str) or not isinstance(nullability, str): - raise AnalysisCacheEntryError("analysis cache column name and nullability must be strings") - if column_type is not None and not isinstance(column_type, str): - raise AnalysisCacheEntryError("analysis cache column type must be a string or null") - return InferredColumn( - name=name, - type=column_type, - nullability=_NULLABILITY_BY_VALUE.get(nullability) or InferredNullability(nullability), - ) - - -def _compact_lineage_from_payload(*, payload: list[list[object]]) -> CompactLineageFacts | None: - """Validate cached lineage into lazy indexed rows; None means use the eager decoder.""" - - pool: dict[str, int] = {} - rows: list[tuple[int, int, int, tuple[tuple[int, int, int], ...]]] = [] - column: list[object] - for column in payload: - if len(column) != _LINEAGE_COLUMN_VALUE_COUNT: - raise AnalysisCacheEntryError("analysis cache lineage column must contain four values") - output_column, transform_kind, confidence, upstream_columns = column - if not ( - type(output_column) is str and type(transform_kind) is str and type(confidence) is str - ): - raise AnalysisCacheEntryError("analysis cache lineage attributes must be strings") - transform_code: int | None = _COMPACT_TRANSFORM_CODES.get(transform_kind) - confidence_code: int | None = _COMPACT_CONFIDENCE_CODES.get(confidence) - if transform_code is None or confidence_code is None: - return None - if type(upstream_columns) is not list: - raise AnalysisCacheEntryError("analysis cache collection must contain arrays") - source_rows: list[tuple[int, int, int]] = [] - source: object - for source in upstream_columns: - if not ( - type(source) is list - and len(source) == _LINEAGE_SOURCE_VALUE_COUNT - and type(source[0]) is str - and type(source[1]) is str - and type(source[2]) is str - ): - raise AnalysisCacheEntryError( - "analysis cache lineage source must contain three strings" - ) - if source[0] not in _RESOURCE_TYPE_VALUES: - raise AnalysisCacheEntryError("analysis cache lineage resource type is invalid") - source_rows.append( - ( - pool.setdefault(source[0], len(pool)), - pool.setdefault(source[1], len(pool)), - pool.setdefault(source[2], len(pool)), - ) - ) - rows.append( - ( - pool.setdefault(output_column, len(pool)), - transform_code, - confidence_code, - tuple(source_rows), - ) - ) - return CompactLineageFacts(string_pool=tuple(pool), rows=tuple(rows)) - - -class _LineageSourceInterner: - """Share identical immutable lineage source facts across one cache read.""" - - def __init__(self) -> None: - self._facts: dict[tuple[str, str, str], CompiledLineageSourceFact] = {} - - def decode(self, *, payload: list[object]) -> CompiledLineageSourceFact: - source_value_count: int = 3 - if len(payload) != source_value_count or not all( - isinstance(value, str) for value in payload - ): - raise AnalysisCacheEntryError( - "analysis cache lineage source must contain three strings" - ) - resource_type, resource_name, column_name = cast(list[str], payload) - key: tuple[str, str, str] = (resource_type, resource_name, column_name) - fact: CompiledLineageSourceFact | None = self._facts.get(key) - if fact is None: - fact = CompiledLineageSourceFact( - resource_type=resource_type, - resource_name=resource_name, - column_name=column_name, - ) - self._facts[key] = fact - return fact - - -def _lineage_column_from_payload( - *, payload: list[object], sources: _LineageSourceInterner -) -> CompiledLineageColumnFact: - lineage_value_count: int = 4 - if len(payload) != lineage_value_count: - raise AnalysisCacheEntryError("analysis cache lineage column must contain four values") - output_column, transform_kind, confidence, upstream_columns = payload - if not all(isinstance(value, str) for value in (output_column, transform_kind, confidence)): - raise AnalysisCacheEntryError("analysis cache lineage attributes must be strings") - return CompiledLineageColumnFact( - output_column=cast(str, output_column), - transform_kind=ColumnTransformKind(cast(str, transform_kind)), - confidence=ColumnLineageConfidence(cast(str, confidence)), - upstream_columns=tuple( - sources.decode(payload=source) for source in _value_lists(upstream_columns) - ), - ) - - -def _cache_database_path(*, context: AnalysisCacheContext) -> Path: - return context.root / f"v{_ANALYSIS_CACHE_VERSION}" / _CACHE_DATABASE_NAME - - -def _analysis_contents( - *, cache_key: str, analysis: PolyglotAnalysisResult, output_signature: str | None = None -) -> str: - serialized_payload: str = orjson.dumps( - _analysis_payload( - cache_key=cache_key, analysis=analysis, output_signature=output_signature - ), - option=orjson.OPT_SORT_KEYS, - ).decode() - return _CACHE_ENTRY_SEPARATOR.join( - ( - _cache_entry_digest(cache_key=cache_key, serialized_payload=serialized_payload), - serialized_payload, - ) - ) - - -def _cache_entry_digest(*, cache_key: str, serialized_payload: str) -> str: - encoded: bytes = f"{cache_key}\0{serialized_payload}".encode() - return hashlib.sha256(encoded).hexdigest() - - def _payload_digest(payload: object) -> str: encoded: bytes = json.dumps( payload, @@ -1141,12 +115,6 @@ def _payload_digest(payload: object) -> str: return hashlib.sha256(encoded).hexdigest() -def _json_value_digest(payload: dict[str, object]) -> str: - """Digest string-keyed JSON scalars exactly as _payload_digest does, via orjson.""" - - return hashlib.sha256(orjson.dumps(payload, option=orjson.OPT_SORT_KEYS)).hexdigest() - - def _package_version(package: str) -> str: try: return version(package) diff --git a/src/sqlbuild/compiler/compile/_helpers/analysis/columns.py b/src/sqlbuild/compiler/compile/_helpers/analysis/columns.py deleted file mode 100644 index 7a7613b533..0000000000 --- a/src/sqlbuild/compiler/compile/_helpers/analysis/columns.py +++ /dev/null @@ -1,1155 +0,0 @@ -"""Required SQL analysis-backed output inference, binding, and lineage facts.""" - -from __future__ import annotations - -import logging -import re -from collections.abc import Iterable -from typing import Any, cast - -from sqlbuild.adapter.contract.constants import POLYGLOT_CUSTOM_TYPE_NAME -from sqlbuild.adapter.contract.models import ExpressionInferenceProfile -from sqlbuild.adapter.contract.types import FunctionNullabilityRule -from sqlbuild.compiler.compile._helpers.analysis.cte_facts import ( - _polyglot_cte_passthrough_nullability_from_parsed, - _polyglot_cte_passthrough_types_from_parsed, - _polyglot_expression_is_non_null_after_filter, - _polyglot_non_null_filter_context, - _polyglot_top_level_ctes, - _unwrap_polyglot_annotations, -) -from sqlbuild.compiler.compile.constants import ( - DECIMAL_SQL_TYPE_NAME, - SQL_QUALIFIER_SEPARATOR_TOKEN, - SQL_WILDCARD_TOKEN, -) -from sqlbuild.compiler.compile.models import ( - CompiledLineageColumnFact, - CompiledLineageSourceFact, - CompileSqlReference, - InferredColumn, - NonNullFilterContext, -) -from sqlbuild.compiler.compile.types import CompiledResourceType -from sqlbuild.compiler.lineage.types import ( - ColumnLineageConfidence, - ColumnTransformKind, - InferredNullability, -) -from sqlbuild.compiler.references.types import SqlReferenceKind -from sqlbuild.compiler.sql_analysis.constants import ( - POLYGLOT_AGGREGATE_KINDS as _POLYGLOT_AGGREGATE_KINDS, -) -from sqlbuild.compiler.sql_analysis.constants import ( - POLYGLOT_BOOLEAN_RESULT_KINDS as _POLYGLOT_BOOLEAN_RESULT_KINDS, -) -from sqlbuild.compiler.sql_analysis.constants import ( - POLYGLOT_CAST_KINDS as _POLYGLOT_CAST_KINDS, -) -from sqlbuild.compiler.sql_analysis.constants import ( - POLYGLOT_JOIN_FULL as _POLYGLOT_JOIN_FULL, -) -from sqlbuild.compiler.sql_analysis.constants import ( - POLYGLOT_JOIN_LEFT as _POLYGLOT_JOIN_LEFT, -) -from sqlbuild.compiler.sql_analysis.constants import ( - POLYGLOT_JOIN_RIGHT as _POLYGLOT_JOIN_RIGHT, -) -from sqlbuild.compiler.sql_analysis.constants import ( - POLYGLOT_KIND_ALIAS as _POLYGLOT_KIND_ALIAS, -) -from sqlbuild.compiler.sql_analysis.constants import ( - POLYGLOT_KIND_CAST as _POLYGLOT_KIND_CAST, -) -from sqlbuild.compiler.sql_analysis.constants import ( - POLYGLOT_KIND_COALESCE as _POLYGLOT_KIND_COALESCE, -) -from sqlbuild.compiler.sql_analysis.constants import ( - POLYGLOT_KIND_COLUMN as _POLYGLOT_KIND_COLUMN, -) -from sqlbuild.compiler.sql_analysis.constants import ( - POLYGLOT_KIND_COUNT as _POLYGLOT_KIND_COUNT, -) -from sqlbuild.compiler.sql_analysis.constants import ( - POLYGLOT_KIND_IS_NULL as _POLYGLOT_KIND_IS_NULL, -) -from sqlbuild.compiler.sql_analysis.constants import ( - POLYGLOT_KIND_LITERAL as _POLYGLOT_KIND_LITERAL, -) -from sqlbuild.compiler.sql_analysis.constants import ( - POLYGLOT_KIND_NULL as _POLYGLOT_KIND_NULL, -) -from sqlbuild.compiler.sql_analysis.constants import ( - POLYGLOT_KIND_SELECT as _POLYGLOT_KIND_SELECT, -) -from sqlbuild.compiler.sql_analysis.constants import ( - POLYGLOT_KIND_TABLE as _POLYGLOT_KIND_TABLE, -) -from sqlbuild.compiler.sql_analysis.constants import ( - POLYGLOT_KIND_TIMESTAMP as _POLYGLOT_KIND_TIMESTAMP, -) -from sqlbuild.compiler.sql_analysis.constants import ( - POLYGLOT_KIND_TRY_CAST as _POLYGLOT_KIND_TRY_CAST, -) -from sqlbuild.compiler.sql_analysis.constants import ( - POLYGLOT_PAYLOAD_ALIAS as _POLYGLOT_PAYLOAD_ALIAS, -) -from sqlbuild.compiler.sql_analysis.constants import ( - POLYGLOT_PAYLOAD_COLUMN as _POLYGLOT_PAYLOAD_COLUMN, -) -from sqlbuild.compiler.sql_analysis.constants import ( - POLYGLOT_PAYLOAD_DATA_TYPE as _POLYGLOT_PAYLOAD_DATA_TYPE, -) -from sqlbuild.compiler.sql_analysis.constants import ( - POLYGLOT_PAYLOAD_EXPRESSIONS as _POLYGLOT_PAYLOAD_EXPRESSIONS, -) -from sqlbuild.compiler.sql_analysis.constants import ( - POLYGLOT_PAYLOAD_FROM as _POLYGLOT_PAYLOAD_FROM, -) -from sqlbuild.compiler.sql_analysis.constants import ( - POLYGLOT_PAYLOAD_JOINS as _POLYGLOT_PAYLOAD_JOINS, -) -from sqlbuild.compiler.sql_analysis.constants import ( - POLYGLOT_PAYLOAD_KIND as _POLYGLOT_PAYLOAD_KIND, -) -from sqlbuild.compiler.sql_analysis.constants import ( - POLYGLOT_PAYLOAD_NAME as _POLYGLOT_PAYLOAD_NAME, -) -from sqlbuild.compiler.sql_analysis.constants import ( - POLYGLOT_PAYLOAD_PRECISION as _POLYGLOT_PAYLOAD_PRECISION, -) -from sqlbuild.compiler.sql_analysis.constants import ( - POLYGLOT_PAYLOAD_SCALE as _POLYGLOT_PAYLOAD_SCALE, -) -from sqlbuild.compiler.sql_analysis.constants import ( - POLYGLOT_PAYLOAD_SELECT as _POLYGLOT_PAYLOAD_SELECT, -) -from sqlbuild.compiler.sql_analysis.constants import ( - POLYGLOT_PAYLOAD_TABLE as _POLYGLOT_PAYLOAD_TABLE, -) -from sqlbuild.compiler.sql_analysis.constants import ( - POLYGLOT_PAYLOAD_THIS as _POLYGLOT_PAYLOAD_THIS, -) -from sqlbuild.compiler.sql_analysis.constants import ( - POLYGLOT_PAYLOAD_TIMEZONE as _POLYGLOT_PAYLOAD_TIMEZONE, -) -from sqlbuild.compiler.sql_analysis.constants import ( - POLYGLOT_PAYLOAD_TO as _POLYGLOT_PAYLOAD_TO, -) -from sqlbuild.compiler.sql_analysis.constants import ( - POLYGLOT_SET_OPERATION_KINDS as _POLYGLOT_SET_OPERATION_KINDS, -) -from sqlbuild.compiler.sql_analysis.constants import ( - POLYGLOT_VARCHAR_DATA_TYPES as _POLYGLOT_VARCHAR_DATA_TYPES, -) -from sqlbuild.compiler.sql_analysis.constants import ( - TIMESTAMP_WITH_TIME_ZONE_SQL_TYPE_NAME as _TIMESTAMP_WITH_TIME_ZONE_SQL_TYPE_NAME, -) -from sqlbuild.compiler.sql_analysis.main._normalize_analysis import normalize_analysis_sql -from sqlbuild.compiler.sql_analysis.main.import_polyglot_sql import import_polyglot_sql -from sqlbuild.diagnostics.main.log_debug_event import log_debug_event - -_DEBUG_LOGGER: logging.Logger = logging.getLogger("sqlbuild.compile") -_PLACEHOLDER_PATTERN: re.Pattern[str] = re.compile(r"@@@(\w+)") -_QUALIFIED_IDENTIFIER_PATTERN: re.Pattern[str] = re.compile( - r'(?[^"]+)"|`(?P[^`]+)`|' - r"\[(?P[^\]]+)\]|(?P[A-Za-z_$][A-Za-z0-9_$]*))" - r"(?:\s|--[^\r\n]*(?:\r?\n|$)|/\*.*?\*/)*\.", - re.DOTALL, -) -_QUALIFIED_SCAN_CONSUMING_TOKENS: tuple[str, ...] = ('"', "`", "[", "--", "/*") -_PLAIN_IDENTIFIER_PATTERN: re.Pattern[str] = re.compile(r"[a-z_$][a-z0-9_$]*") -_IDENTIFIER_CHARACTERS: frozenset[str] = frozenset( - "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_$" -) - - -def _infer_columns_with_polyglot( - *, - cleaned_sql: str, - dialect: str | None, - column_nullability_by_table: dict[str, dict[str, InferredNullability]], - inference_profile: ExpressionInferenceProfile, -) -> tuple[InferredColumn, ...] | None | bool: - polyglot_module: Any = import_polyglot_sql() - try: - parsed: Any = polyglot_module.parse_one(cleaned_sql, dialect=dialect or "generic") - except polyglot_module.PolyglotError as error: - log_debug_event( - logger=_DEBUG_LOGGER, - message="column inference parse failed; falling back", - sqlbuild_error=str(error), - ) - return False - return _infer_columns_from_polyglot_ast( - parsed=parsed, - column_nullability_by_table=column_nullability_by_table, - inference_profile=inference_profile, - ) - - -def _infer_columns_from_polyglot_ast( - *, - parsed: Any, - column_nullability_by_table: dict[str, dict[str, InferredNullability]], - inference_profile: ExpressionInferenceProfile, -) -> tuple[InferredColumn, ...] | None | bool: - infer_nullability: bool = str(getattr(parsed, "kind", "")) not in _POLYGLOT_SET_OPERATION_KINDS - select: Any | None = parsed - if str(getattr(select, "kind", "")) != _POLYGLOT_KIND_SELECT: - select = parsed.find(_POLYGLOT_KIND_SELECT) - if select is None or str(getattr(select, "kind", "")) != _POLYGLOT_KIND_SELECT: - return None - - column_nullability_by_table = dict(column_nullability_by_table) - alias_nullability: dict[str, InferredNullability] = {} - if _has_known_nullability(column_nullability_by_table): - alias_nullability = _polyglot_alias_nullability_from_select( - select=select, - column_nullability_by_table=column_nullability_by_table, - ) - top_level_ctes: tuple[tuple[str, Any, bool], ...] = _polyglot_top_level_ctes(parsed) - referenced_table_names: tuple[str, ...] = ( - tuple( - str(getattr(table, "name", "") or "") for table in parsed.find_all(_POLYGLOT_KIND_TABLE) - ) - if top_level_ctes - else () - ) - cte_passthrough_types: dict[str, str] = _polyglot_cte_passthrough_types_from_parsed( - parsed=parsed, - column_types_by_table={}, - inference_profile=inference_profile, - expression_type_resolver=_polyglot_expression_type, - top_level_ctes=top_level_ctes, - referenced_table_names=referenced_table_names, - ) - cte_passthrough_nullability: dict[str, InferredNullability] = ( - _polyglot_cte_passthrough_nullability_from_parsed( - parsed=parsed, - column_nullability_by_table=column_nullability_by_table, - inference_profile=inference_profile, - nullability_resolver=_infer_polyglot_nullability, - shallow_nullability_resolver=_infer_polyglot_shallow_nullability, - alias_nullability_resolver=_polyglot_alias_nullability_from_select, - top_level_ctes=top_level_ctes, - referenced_table_names=referenced_table_names, - ) - ) - non_null_filter_context: NonNullFilterContext | None = _polyglot_non_null_filter_context( - select=select, - column_nullability_by_table=column_nullability_by_table, - ) - columns: list[InferredColumn] = [] - projection: Any - for projection in getattr(select, "expressions", ()): - projection = _unwrap_polyglot_annotations(projection) - if bool(getattr(projection, "is_star", False)): - continue - name: str = str(getattr(projection, "output_name", "") or "") - if not name or name == SQL_WILDCARD_TOKEN: - continue - inner: Any = ( - projection.this - if str(getattr(projection, "kind", "")) == _POLYGLOT_KIND_ALIAS - else projection - ) - col_type: str | None = cte_passthrough_types.get(name) or _polyglot_expression_type( - expression=inner, - inference_profile=inference_profile, - ) - nullability: InferredNullability = InferredNullability.UNKNOWN - if infer_nullability: - nullability = ( - InferredNullability.NON_NULL - if _polyglot_expression_is_non_null_after_filter( - expression=inner, - context=non_null_filter_context, - ) - else cte_passthrough_nullability.get( - name, - _infer_polyglot_nullability( - expression=inner, - alias_nullability=alias_nullability, - column_nullability_by_table=column_nullability_by_table, - inference_profile=inference_profile, - ), - ) - ) - columns.append(InferredColumn(name=name, type=col_type, nullability=nullability)) - return tuple(columns) - - -def _analyze_columns_and_lineage_from_polyglot_ast( - *, - parsed: Any, - references: tuple[CompileSqlReference, ...], - column_nullability_by_table: dict[str, dict[str, InferredNullability]], - column_types_by_table: dict[str, dict[str, str]], - inference_profile: ExpressionInferenceProfile, - recover_cte_facts: bool, -) -> tuple[tuple[InferredColumn, ...] | None, tuple[CompiledLineageColumnFact, ...], bool]: - infer_nullability: bool = str(getattr(parsed, "kind", "")) not in _POLYGLOT_SET_OPERATION_KINDS - select: Any | None = parsed - if str(getattr(select, "kind", "")) != _POLYGLOT_KIND_SELECT: - select = parsed.find(_POLYGLOT_KIND_SELECT) - if select is None or str(getattr(select, "kind", "")) != _POLYGLOT_KIND_SELECT: - return None, (), False - - column_nullability_by_table = dict(column_nullability_by_table) - has_known_nullability: bool = _has_known_nullability(column_nullability_by_table) - alias_nullability: dict[str, InferredNullability] = {} - if has_known_nullability: - alias_nullability = _polyglot_alias_nullability_from_select( - select=select, - column_nullability_by_table=column_nullability_by_table, - ) - alias_map: dict[str, tuple[CompiledResourceType, str]] = _polyglot_reference_alias_map( - parsed=select, - references=references, - ) - unqualified_resource: tuple[CompiledResourceType, str] | None = _single_alias_resource( - alias_map - ) - - top_level_ctes: tuple[tuple[str, Any, bool], ...] = ( - _polyglot_top_level_ctes(parsed) if recover_cte_facts else () - ) - referenced_table_names: tuple[str, ...] = ( - tuple( - str(getattr(table, "name", "") or "") for table in parsed.find_all(_POLYGLOT_KIND_TABLE) - ) - if top_level_ctes - else () - ) - cte_passthrough_types: dict[str, str] = ( - _polyglot_cte_passthrough_types_from_parsed( - parsed=parsed, - column_types_by_table=column_types_by_table, - inference_profile=inference_profile, - expression_type_resolver=_polyglot_expression_type, - top_level_ctes=top_level_ctes, - referenced_table_names=referenced_table_names, - ) - if recover_cte_facts - else {} - ) - cte_passthrough_nullability: dict[str, InferredNullability] = ( - _polyglot_cte_passthrough_nullability_from_parsed( - parsed=parsed, - column_nullability_by_table=column_nullability_by_table, - inference_profile=inference_profile, - nullability_resolver=_infer_polyglot_nullability, - shallow_nullability_resolver=_infer_polyglot_shallow_nullability, - alias_nullability_resolver=_polyglot_alias_nullability_from_select, - top_level_ctes=top_level_ctes, - referenced_table_names=referenced_table_names, - ) - if recover_cte_facts - else {} - ) - non_null_filter_context: NonNullFilterContext | None = _polyglot_non_null_filter_context( - select=select, - column_nullability_by_table=column_nullability_by_table, - ) - columns: list[InferredColumn] = [] - lineage_columns: list[CompiledLineageColumnFact] = [] - has_star: bool = False - projection: Any - for projection in getattr(select, "expressions", ()): - projection = _unwrap_polyglot_annotations(projection) - if bool(getattr(projection, "is_star", False)): - has_star = True - continue - inner: Any = ( - projection.this - if str(getattr(projection, "kind", "")) == _POLYGLOT_KIND_ALIAS - else projection - ) - if bool(getattr(inner, "is_star", False)): - has_star = True - continue - output_column: str = str(getattr(projection, "output_name", "") or "") - if not output_column or output_column == SQL_WILDCARD_TOKEN: - continue - col_type: str | None = cte_passthrough_types.get( - output_column - ) or _polyglot_expression_type( - expression=inner, - inference_profile=inference_profile, - ) - nullability: InferredNullability = InferredNullability.UNKNOWN - if infer_nullability: - nullability = ( - InferredNullability.NON_NULL - if _polyglot_expression_is_non_null_after_filter( - expression=inner, - context=non_null_filter_context, - ) - else ( - cte_passthrough_nullability[output_column] - if output_column in cte_passthrough_nullability - else ( - _infer_polyglot_nullability( - expression=inner, - alias_nullability=alias_nullability, - column_nullability_by_table=column_nullability_by_table, - inference_profile=inference_profile, - ) - if has_known_nullability - else _infer_polyglot_shallow_nullability( - expression=inner, - inference_profile=inference_profile, - ) - ) - ) - ) - columns.append(InferredColumn(name=output_column, type=col_type, nullability=nullability)) - - upstream_columns, confidence = _polyglot_lineage_upstream_columns( - projection=projection, - alias_map=alias_map, - unqualified_resource=unqualified_resource, - ) - transform_kind: ColumnTransformKind = _polyglot_lineage_transform_kind( - expression=inner, - has_upstream=bool(upstream_columns), - ) - lineage_columns.append( - CompiledLineageColumnFact( - output_column=output_column, - upstream_columns=upstream_columns, - transform_kind=transform_kind, - confidence=confidence - if upstream_columns or transform_kind == ColumnTransformKind.CONSTANT - else ColumnLineageConfidence.UNKNOWN, - ) - ) - return tuple(columns), tuple(lineage_columns), has_star - - -def _polyglot_reference_alias_map( - *, parsed: Any, references: tuple[CompileSqlReference, ...] -) -> dict[str, tuple[CompiledResourceType, str]]: - resource_by_name: dict[str, tuple[CompiledResourceType, str]] = {} - reference: CompileSqlReference - for reference in references: - resource_type: CompiledResourceType | None = _lineage_resource_type(reference) - if resource_type is None: - continue - resource_by_name[_analysis_reference_name(reference)] = ( - resource_type, - reference.ref_name, - ) - alias_map: dict[str, tuple[CompiledResourceType, str]] = {} - tables: tuple[Any, ...] = tuple(parsed.find_all(_POLYGLOT_KIND_TABLE)) - table: Any - for table in tables: - table_name: str = str(getattr(table, "name", "") or "") - resource: tuple[CompiledResourceType, str] | None = resource_by_name.get(table_name) - if resource is None: - continue - alias_map[table_name] = resource - alias_or_name: str = str(getattr(table, "alias_or_name", "") or "") - if alias_or_name: - alias_map[alias_or_name] = resource - return alias_map - - -def _lineage_resource_type(reference: CompileSqlReference) -> CompiledResourceType | None: - if reference.ref_kind == SqlReferenceKind.REF: - return CompiledResourceType.MODEL - if reference.ref_kind == SqlReferenceKind.SOURCE: - return CompiledResourceType.SOURCE - if reference.ref_kind == SqlReferenceKind.SEED: - return CompiledResourceType.SEED - if reference.ref_kind == SqlReferenceKind.TABLE_FUNCTION: - return CompiledResourceType.TABLE_FN - return None - - -def _analysis_reference_name(reference: CompileSqlReference) -> str: - if reference.ref_kind == SqlReferenceKind.TABLE_FUNCTION: - return table_function_analysis_name(reference.ref_name) - return reference.ref_name - - -def table_function_analysis_name(function_name: str) -> str: - """Return the stable relation stub used to analyze a table-function call.""" - - return f"__sqlbuild_table_function_{function_name}" - - -def _polyglot_lineage_upstream_columns( - *, - projection: Any, - alias_map: dict[str, tuple[CompiledResourceType, str]], - unqualified_resource: tuple[CompiledResourceType, str] | None, -) -> tuple[tuple[CompiledLineageSourceFact, ...], ColumnLineageConfidence]: - columns: list[CompiledLineageSourceFact] = [] - seen: set[tuple[CompiledResourceType, str, str]] = set() - confidence: ColumnLineageConfidence = ColumnLineageConfidence.HIGH - column_refs: tuple[tuple[str, str], ...] = _polyglot_column_refs_in_expression(projection) - for column_name, table_name in column_refs: - if not column_name: - continue - resource: tuple[CompiledResourceType, str] | None = None - if table_name: - resource = alias_map.get(table_name) - elif unqualified_resource is not None: - resource = unqualified_resource - confidence = ColumnLineageConfidence.MEDIUM - else: - confidence = ColumnLineageConfidence.UNKNOWN - if resource is None: - continue - resource_type, resource_name = resource - key: tuple[CompiledResourceType, str, str] = (resource_type, resource_name, column_name) - if key in seen: - continue - seen.add(key) - columns.append( - CompiledLineageSourceFact( - resource_type=resource_type, - resource_name=resource_name, - column_name=column_name, - ) - ) - return tuple(columns), confidence - - -def _single_alias_resource( - alias_map: dict[str, tuple[CompiledResourceType, str]], -) -> tuple[CompiledResourceType, str] | None: - resource: tuple[CompiledResourceType, str] | None = None - for candidate in alias_map.values(): - if resource is None: - resource = candidate - continue - if candidate[1] != resource[1]: - return None - return resource - - -def _polyglot_column_refs_in_expression(expression: Any) -> tuple[tuple[str, str], ...]: - if str(getattr(expression, "kind", "")) == _POLYGLOT_KIND_COLUMN: - return ( - (str(getattr(expression, "name", "") or ""), _polyglot_column_table_name(expression)), - ) - payload: object = expression.to_dict() - refs: list[tuple[str, str]] = [] - - def visit(*, node: object, collected_refs: list[tuple[str, str]]) -> list[tuple[str, str]]: - if isinstance(node, dict): - node_dict: dict[str, object] = cast(dict[str, object], node) - column_payload: object = node_dict.get(_POLYGLOT_PAYLOAD_COLUMN) - if isinstance(column_payload, dict): - column_dict: dict[str, object] = cast(dict[str, object], column_payload) - column_name: str = _polyglot_name_payload_value( - column_dict.get(_POLYGLOT_PAYLOAD_NAME) - ) - table_payload: object = column_dict.get(_POLYGLOT_PAYLOAD_TABLE) - table_name: str = "" - if isinstance(table_payload, dict): - table_dict: dict[str, object] = cast(dict[str, object], table_payload) - table_name = _polyglot_name_payload_value( - table_dict.get(_POLYGLOT_PAYLOAD_NAME) - ) - return [*collected_refs, (column_name, table_name)] - for value in node_dict.values(): - collected_refs = visit(node=value, collected_refs=collected_refs) - elif isinstance(node, list): - for value in node: - collected_refs = visit(node=value, collected_refs=collected_refs) - return collected_refs - - refs = visit(node=payload, collected_refs=refs) - return tuple(refs) - - -def _has_known_nullability( - column_nullability_by_table: dict[str, dict[str, InferredNullability]], -) -> bool: - for column_facts in column_nullability_by_table.values(): - for value in column_facts.values(): - if value != InferredNullability.UNKNOWN: - return True - return False - - -def _polyglot_lineage_transform_kind(*, expression: Any, has_upstream: bool) -> ColumnTransformKind: - kind: str = str(getattr(expression, "kind", "")) - if bool(getattr(expression, "is_star", False)): - return ColumnTransformKind.STAR - if kind in _POLYGLOT_CAST_KINDS: - return ColumnTransformKind.CAST - if _polyglot_has_aggregation(expression): - return ColumnTransformKind.AGGREGATION - if not has_upstream: - return ColumnTransformKind.CONSTANT - if kind == _POLYGLOT_KIND_COLUMN: - return ColumnTransformKind.DIRECT - return ColumnTransformKind.EXPRESSION - - -def _polyglot_has_aggregation(expression: Any) -> bool: - nodes: tuple[Any, ...] = tuple(expression.walk()) - return any(str(getattr(node, "kind", "")) in _POLYGLOT_AGGREGATE_KINDS for node in nodes) - - -def _polyglot_expression_type( - *, expression: Any, inference_profile: ExpressionInferenceProfile -) -> str | None: - kind: str = str(getattr(expression, "kind", "")) - function_name: str = str(getattr(expression, "name", "")) or kind - function_type: str | None = ( - inference_profile.function_return_type(function_name) - if kind != _POLYGLOT_KIND_COLUMN - else None - ) - if function_type is not None: - return function_type - if kind in _POLYGLOT_BOOLEAN_RESULT_KINDS: - return "BOOLEAN" - if kind not in _POLYGLOT_CAST_KINDS: - return None - payload: object = expression.to_dict().get(kind, {}) - if not isinstance(payload, dict): - return None - target: object = payload.get(_POLYGLOT_PAYLOAD_TO) - if not isinstance(target, dict): - return None - raw_type: object = target.get(_POLYGLOT_PAYLOAD_DATA_TYPE) - if not isinstance(raw_type, str) or not raw_type: - return None - if raw_type.upper() == POLYGLOT_CUSTOM_TYPE_NAME: - custom_name: object = target.get(_POLYGLOT_PAYLOAD_NAME) - if isinstance(custom_name, str) and custom_name: - return custom_name.upper() - if ( - raw_type.lower() == _POLYGLOT_KIND_TIMESTAMP - and target.get(_POLYGLOT_PAYLOAD_TIMEZONE) is True - ): - return _TIMESTAMP_WITH_TIME_ZONE_SQL_TYPE_NAME - type_name: str = _polyglot_type_name(raw_type) - length: object = target.get("length") - if raw_type.lower() in _POLYGLOT_VARCHAR_DATA_TYPES and isinstance(length, int): - return f"VARCHAR({length})" - precision: object = target.get(_POLYGLOT_PAYLOAD_PRECISION) - scale: object = target.get(_POLYGLOT_PAYLOAD_SCALE) - if type_name == DECIMAL_SQL_TYPE_NAME and isinstance(precision, int): - if isinstance(scale, int): - return f"DECIMAL({precision}, {scale})" - return f"DECIMAL({precision})" - return type_name - - -def _polyglot_type_name(raw_type: str) -> str: - known_types: dict[str, str] = { - "big_int": "BIGINT", - "bool": "BOOLEAN", - "boolean": "BOOLEAN", - "date": "DATE", - "decimal": "DECIMAL", - "double": "DOUBLE", - "float": "FLOAT", - "int": "INT", - "integer": "INT", - "text": "TEXT", - "timestamp": "TIMESTAMP", - "var_char": "TEXT", - "varchar": "TEXT", - } - return known_types.get(raw_type, raw_type.replace("_", " ").upper()) - - -def _infer_polyglot_nullability( - *, - expression: Any, - alias_nullability: dict[str, InferredNullability], - column_nullability_by_table: dict[str, dict[str, InferredNullability]], - inference_profile: ExpressionInferenceProfile, -) -> InferredNullability: - kind: str = str(getattr(expression, "kind", "")) - if kind == _POLYGLOT_KIND_NULL: - return InferredNullability.NULLABLE - if kind == _POLYGLOT_KIND_LITERAL: - return InferredNullability.NON_NULL - if kind == _POLYGLOT_KIND_COLUMN: - return _infer_polyglot_column_nullability( - expression=expression, - alias_nullability=alias_nullability, - column_nullability_by_table=column_nullability_by_table, - ) - if kind == _POLYGLOT_KIND_CAST: - inner: Any | None = getattr(expression, "this", None) - if inner is None: - return InferredNullability.UNKNOWN - return _infer_polyglot_nullability( - expression=inner, - alias_nullability=alias_nullability, - column_nullability_by_table=column_nullability_by_table, - inference_profile=inference_profile, - ) - if kind == _POLYGLOT_KIND_TRY_CAST: - return InferredNullability.UNKNOWN - if kind == _POLYGLOT_KIND_COUNT: - return InferredNullability.NON_NULL - if kind == _POLYGLOT_KIND_IS_NULL: - return InferredNullability.NON_NULL - if kind == _POLYGLOT_KIND_COALESCE: - child_nullabilities: list[InferredNullability] = [ - _infer_polyglot_nullability( - expression=child, - alias_nullability=alias_nullability, - column_nullability_by_table=column_nullability_by_table, - inference_profile=inference_profile, - ) - for child in _polyglot_expression_args(expression) - ] - if any(value == InferredNullability.NON_NULL for value in child_nullabilities): - return InferredNullability.NON_NULL - if child_nullabilities and all( - value == InferredNullability.NULLABLE for value in child_nullabilities - ): - return InferredNullability.NULLABLE - return InferredNullability.UNKNOWN - rule: FunctionNullabilityRule | None = inference_profile.function_nullability_rule(kind) - if rule is None: - return InferredNullability.UNKNOWN - child_nullabilities: tuple[InferredNullability, ...] = tuple( - _infer_polyglot_nullability( - expression=child, - alias_nullability=alias_nullability, - column_nullability_by_table=column_nullability_by_table, - inference_profile=inference_profile, - ) - for child in _polyglot_expression_args(expression) - ) - return rule(child_nullabilities) - - -def _infer_polyglot_shallow_nullability( - *, - expression: Any, - inference_profile: ExpressionInferenceProfile, -) -> InferredNullability: - kind: str = str(getattr(expression, "kind", "")) - if kind == _POLYGLOT_KIND_NULL: - return InferredNullability.NULLABLE - if kind == _POLYGLOT_KIND_LITERAL: - return InferredNullability.NON_NULL - if kind == _POLYGLOT_KIND_COUNT: - return InferredNullability.NON_NULL - if kind == _POLYGLOT_KIND_IS_NULL: - return InferredNullability.NON_NULL - if kind == _POLYGLOT_KIND_COLUMN: - return InferredNullability.UNKNOWN - if kind == _POLYGLOT_KIND_CAST: - inner: Any | None = getattr(expression, "this", None) - if inner is None: - return InferredNullability.UNKNOWN - return _infer_polyglot_shallow_nullability( - expression=inner, - inference_profile=inference_profile, - ) - if kind == _POLYGLOT_KIND_TRY_CAST: - return InferredNullability.UNKNOWN - if kind == _POLYGLOT_KIND_COALESCE: - child_nullabilities: tuple[InferredNullability, ...] = tuple( - _infer_polyglot_shallow_nullability( - expression=child, - inference_profile=inference_profile, - ) - for child in _polyglot_expression_args(expression) - ) - if any(value == InferredNullability.NON_NULL for value in child_nullabilities): - return InferredNullability.NON_NULL - if child_nullabilities and all( - value == InferredNullability.NULLABLE for value in child_nullabilities - ): - return InferredNullability.NULLABLE - return InferredNullability.UNKNOWN - rule: FunctionNullabilityRule | None = inference_profile.function_nullability_rule(kind) - if rule is None: - return InferredNullability.UNKNOWN - child_nullabilities: tuple[InferredNullability, ...] = tuple( - _infer_polyglot_shallow_nullability( - expression=child, - inference_profile=inference_profile, - ) - for child in _polyglot_expression_args(expression) - ) - return rule(child_nullabilities) - - -def _infer_polyglot_column_nullability( - *, - expression: Any, - alias_nullability: dict[str, InferredNullability], - column_nullability_by_table: dict[str, dict[str, InferredNullability]], -) -> InferredNullability: - column_name: str = str(getattr(expression, "name", "") or "") - if not column_name: - return InferredNullability.UNKNOWN - payload: object = expression.to_dict().get(_POLYGLOT_PAYLOAD_COLUMN, {}) - table_name: str = "" - if isinstance(payload, dict): - table_payload: object = payload.get(_POLYGLOT_PAYLOAD_TABLE) - if isinstance(table_payload, dict): - raw_name: object = table_payload.get(_POLYGLOT_PAYLOAD_NAME) - if isinstance(raw_name, str): - table_name = raw_name - if table_name: - table_fact: InferredNullability = alias_nullability.get( - table_name, InferredNullability.UNKNOWN - ) - if table_fact == InferredNullability.NULLABLE: - return InferredNullability.NULLABLE - return column_nullability_by_table.get(table_name, {}).get( - column_name, InferredNullability.UNKNOWN - ) - matches: list[InferredNullability] = [ - columns[column_name] - for columns in column_nullability_by_table.values() - if column_name in columns - ] - if len(matches) == 1: - return matches[0] - return InferredNullability.UNKNOWN - - -def _polyglot_column_table_name(column: Any) -> str: - payload: object = column.to_dict().get(_POLYGLOT_PAYLOAD_COLUMN, {}) - if not isinstance(payload, dict): - return "" - table_payload: object = payload.get(_POLYGLOT_PAYLOAD_TABLE) - if not isinstance(table_payload, dict): - return "" - raw_name: object = table_payload.get(_POLYGLOT_PAYLOAD_NAME) - return raw_name if isinstance(raw_name, str) else "" - - -def _polyglot_expression_args(expression: Any) -> tuple[Any, ...]: - args: list[Any] = [] - primary_arg: Any | None = getattr(expression, "this", None) - if primary_arg is not None: - args.append(primary_arg) - args.extend(getattr(expression, "expressions", ()) or ()) - return tuple(args) - - -def _polyglot_alias_nullability_from_select( - *, - select: Any, - column_nullability_by_table: dict[str, dict[str, InferredNullability]], -) -> dict[str, InferredNullability]: - alias_nullability: dict[str, InferredNullability] = {} - current_aliases: set[str] = set() - - select_payload: object = select.to_dict().get(_POLYGLOT_PAYLOAD_SELECT, {}) - if not isinstance(select_payload, dict): - return alias_nullability - - from_payload: object = select_payload.get(_POLYGLOT_PAYLOAD_FROM) - if isinstance(from_payload, dict): - from_expressions: object = from_payload.get(_POLYGLOT_PAYLOAD_EXPRESSIONS) - if isinstance(from_expressions, list) and len(from_expressions) == 1: - from_table_payload: object = from_expressions[0] - if isinstance(from_table_payload, dict): - table_payload: object = from_table_payload.get(_POLYGLOT_PAYLOAD_TABLE) - if isinstance(table_payload, dict): - alias, table_name = _polyglot_table_payload_alias_and_name(table_payload) - current_aliases.add(alias) - alias_nullability[alias] = InferredNullability.UNKNOWN - _copy_table_facts_to_alias( - alias=alias, - table_name=table_name, - column_nullability_by_table=column_nullability_by_table, - ) - - joins_payload: object = select_payload.get(_POLYGLOT_PAYLOAD_JOINS) - if not isinstance(joins_payload, list): - return alias_nullability - for join_payload in joins_payload: - if not isinstance(join_payload, dict): - continue - this_payload: object = join_payload.get(_POLYGLOT_PAYLOAD_THIS) - if not isinstance(this_payload, dict): - continue - joined_table_payload: object = this_payload.get(_POLYGLOT_PAYLOAD_TABLE) - if not isinstance(joined_table_payload, dict): - continue - joined_alias, joined_table_name = _polyglot_table_payload_alias_and_name( - joined_table_payload - ) - side: str = str(join_payload.get(_POLYGLOT_PAYLOAD_KIND) or "").upper() - if side == _POLYGLOT_JOIN_LEFT: - alias_nullability[joined_alias] = InferredNullability.NULLABLE - elif side == _POLYGLOT_JOIN_RIGHT: - for alias in current_aliases: - alias_nullability[alias] = InferredNullability.NULLABLE - alias_nullability[joined_alias] = InferredNullability.UNKNOWN - elif side == _POLYGLOT_JOIN_FULL: - for alias in current_aliases: - alias_nullability[alias] = InferredNullability.NULLABLE - alias_nullability[joined_alias] = InferredNullability.NULLABLE - else: - alias_nullability[joined_alias] = InferredNullability.UNKNOWN - current_aliases.add(joined_alias) - _copy_table_facts_to_alias( - alias=joined_alias, - table_name=joined_table_name, - column_nullability_by_table=column_nullability_by_table, - ) - return alias_nullability - - -def _polyglot_table_payload_alias_and_name(table_payload: dict[str, object]) -> tuple[str, str]: - table_name: str = _polyglot_name_payload_value(table_payload.get(_POLYGLOT_PAYLOAD_NAME)) - alias: str = ( - _polyglot_name_payload_value(table_payload.get(_POLYGLOT_PAYLOAD_ALIAS)) or table_name - ) - return alias, table_name - - -def _polyglot_name_payload_value(payload: object) -> str: - if isinstance(payload, str): - return payload - if isinstance(payload, dict): - payload_dict: dict[str, object] = cast(dict[str, object], payload) - name: object = payload_dict.get(_POLYGLOT_PAYLOAD_NAME) - if isinstance(name, str): - return name - return "" - - -def substitute_placeholder_defaults(*, query_sql: str, placeholders: dict[str, str]) -> str: - """Replace @@@name tokens with their default values for SQL analysis parsing.""" - - if not placeholders: - return query_sql - - def _replacer(match: re.Match[str]) -> str: - name: str = match.group(1) - return placeholders.get(name, match.group(0)) - - return _PLACEHOLDER_PATTERN.sub(_replacer, query_sql) - - -def _replace_refs_with_stubs( - *, - query_sql: str, - dialect: str | None = None, - relation_stubs: dict[str, str] | None = None, -) -> str: - """Replace SQLBuild marker calls with parseable SQL stubs.""" - - return normalize_analysis_sql(sql=query_sql, dialect=dialect, stubs=relation_stubs) - - -def _qualified_reference_names(*, query_sql: str, reference_names: Iterable[str]) -> frozenset[str]: - """Return qualifier reference names, searching names directly when no token can hide one.""" - - if SQL_QUALIFIER_SEPARATOR_TOKEN not in query_sql: - return frozenset() - names_by_normalized: dict[str, list[str]] = {} - for value in reference_names: - name: str = str(value) - names_by_normalized.setdefault(name.casefold(), []).append(name) - if not names_by_normalized: - return frozenset() - if not query_sql.isascii() or any( - token in query_sql for token in _QUALIFIED_SCAN_CONSUMING_TOKENS - ): - return _scanned_qualified_reference_names( - query_sql=query_sql, names_by_normalized=names_by_normalized - ) - - folded_sql: str = query_sql.lower() - qualified: set[str] = set() - for normalized, names in names_by_normalized.items(): - if _PLAIN_IDENTIFIER_PATTERN.fullmatch(normalized) is not None and _is_qualifier( - folded_sql=folded_sql, name=normalized - ): - qualified.update(names) - return frozenset(qualified) - - -def _is_qualifier(*, folded_sql: str, name: str) -> bool: - length: int = len(folded_sql) - start: int = folded_sql.find(name) - while start != -1: - end: int = start + len(name) - if (start == 0 or folded_sql[start - 1] not in _IDENTIFIER_CHARACTERS) and ( - end == length or folded_sql[end] not in _IDENTIFIER_CHARACTERS - ): - while end < length and folded_sql[end].isspace(): - end += 1 - if end < length and folded_sql[end] == SQL_QUALIFIER_SEPARATOR_TOKEN: - return True - start = folded_sql.find(name, start + 1) - return False - - -def _scanned_qualified_reference_names( - *, query_sql: str, names_by_normalized: dict[str, list[str]] -) -> frozenset[str]: - qualified: set[str] = set() - for match in _QUALIFIED_IDENTIFIER_PATTERN.finditer(query_sql): - identifier: str = next(value for value in match.groups() if value is not None) - qualified.update(names_by_normalized.get(identifier.casefold(), ())) - return frozenset(qualified) - - -def _infer_expression_nullability( - *, - expression: Any, - expressions_module: Any, - alias_nullability: dict[str, InferredNullability], - column_nullability_by_table: dict[str, dict[str, InferredNullability]], - inference_profile: ExpressionInferenceProfile, -) -> InferredNullability: - """Infer only nullability facts SQLBuild can prove statically.""" - - literal_type: type[Any] = expressions_module.Literal - null_type: type[Any] = expressions_module.Null - column_type: type[Any] = expressions_module.Column - cast_type: type[Any] = expressions_module.Cast - try_cast_type: type[Any] = expressions_module.TryCast - coalesce_type: type[Any] = expressions_module.Coalesce - count_type: type[Any] = expressions_module.Count - - if isinstance(expression, null_type): - return InferredNullability.NULLABLE - if isinstance(expression, literal_type): - return InferredNullability.NON_NULL - if isinstance(expression, column_type): - return _infer_column_nullability( - column=expression, - alias_nullability=alias_nullability, - column_nullability_by_table=column_nullability_by_table, - ) - if isinstance(expression, cast_type): - return _infer_expression_nullability( - expression=expression.this, - expressions_module=expressions_module, - alias_nullability=alias_nullability, - column_nullability_by_table=column_nullability_by_table, - inference_profile=inference_profile, - ) - if isinstance(expression, try_cast_type): - return InferredNullability.UNKNOWN - if isinstance(expression, count_type): - return InferredNullability.NON_NULL - if isinstance(expression, coalesce_type): - return _infer_coalesce_nullability( - expression=expression, - expressions_module=expressions_module, - alias_nullability=alias_nullability, - column_nullability_by_table=column_nullability_by_table, - inference_profile=inference_profile, - ) - function_name: str = _expression_function_name(expression) - rule: FunctionNullabilityRule | None = inference_profile.function_nullability_rule( - function_name - ) - if rule is None: - return InferredNullability.UNKNOWN - arg_nullabilities: tuple[InferredNullability, ...] = tuple( - _infer_expression_nullability( - expression=arg, - expressions_module=expressions_module, - alias_nullability=alias_nullability, - column_nullability_by_table=column_nullability_by_table, - inference_profile=inference_profile, - ) - for arg in _expression_function_args(expression) - ) - return rule(arg_nullabilities) - - -def _infer_column_nullability( - *, - column: Any, - alias_nullability: dict[str, InferredNullability], - column_nullability_by_table: dict[str, dict[str, InferredNullability]], -) -> InferredNullability: - table_name: str = str(column.table or "") - column_name: str = str(column.name or "") - if table_name: - table_fact: InferredNullability = alias_nullability.get( - table_name, InferredNullability.UNKNOWN - ) - if table_fact == InferredNullability.NULLABLE: - return InferredNullability.NULLABLE - return column_nullability_by_table.get(table_name, {}).get( - column_name, InferredNullability.UNKNOWN - ) - - matches: list[InferredNullability] = [ - column_facts[column_name] - for column_facts in column_nullability_by_table.values() - if column_name in column_facts - ] - if len(matches) == 1: - return matches[0] - return InferredNullability.UNKNOWN - - -def _infer_coalesce_nullability( - *, - expression: Any, - expressions_module: Any, - alias_nullability: dict[str, InferredNullability], - column_nullability_by_table: dict[str, dict[str, InferredNullability]], - inference_profile: ExpressionInferenceProfile, -) -> InferredNullability: - arg_nullabilities: tuple[InferredNullability, ...] = tuple( - _infer_expression_nullability( - expression=arg, - expressions_module=expressions_module, - alias_nullability=alias_nullability, - column_nullability_by_table=column_nullability_by_table, - inference_profile=inference_profile, - ) - for arg in expression.expressions - ) - if any(value == InferredNullability.NON_NULL for value in arg_nullabilities): - return InferredNullability.NON_NULL - if arg_nullabilities and all( - value == InferredNullability.NULLABLE for value in arg_nullabilities - ): - return InferredNullability.NULLABLE - return InferredNullability.UNKNOWN - - -def _expression_function_name(expression: Any) -> str: - sql_name: object | None = getattr(expression, "sql_name", None) - if callable(sql_name): - return str(sql_name()).upper() - key: object | None = getattr(expression, "key", None) - return str(key or "").upper() - - -def _expression_function_args(expression: Any) -> tuple[Any, ...]: - args: list[Any] = [] - primary_arg: Any | None = getattr(expression, "this", None) - if primary_arg is not None: - args.append(primary_arg) - args.extend(expression.expressions) - return tuple(args) - - -def _copy_table_facts_to_alias( - *, - alias: str, - table_name: str, - column_nullability_by_table: dict[str, dict[str, InferredNullability]], -) -> None: - if alias == table_name: - return - table_facts: dict[str, InferredNullability] | None = column_nullability_by_table.get(table_name) - if table_facts is not None: - alias_facts: dict[str, dict[str, InferredNullability]] = column_nullability_by_table - alias_facts.setdefault(alias, table_facts) diff --git a/src/sqlbuild/compiler/compile/_helpers/analysis/compact.py b/src/sqlbuild/compiler/compile/_helpers/analysis/compact.py deleted file mode 100644 index c2b40d58ef..0000000000 --- a/src/sqlbuild/compiler/compile/_helpers/analysis/compact.py +++ /dev/null @@ -1,1834 +0,0 @@ -"""Required SQL analysis-backed output inference, binding, and lineage facts.""" - -from __future__ import annotations - -import logging -import threading -from collections.abc import Iterator, Sequence -from contextlib import contextmanager -from contextvars import ContextVar, Token -from dataclasses import replace -from typing import Any, cast - -import orjson - -import sqlbuild._native as _native -from sqlbuild.adapter.contract.models import ExpressionInferenceProfile -from sqlbuild.compiler.compile._helpers.analysis.columns import ( - _analysis_reference_name, - _analyze_columns_and_lineage_from_polyglot_ast, - _infer_columns_with_polyglot, - _infer_polyglot_nullability, - _infer_polyglot_shallow_nullability, - _polyglot_alias_nullability_from_select, - _polyglot_expression_type, - _qualified_reference_names, - _replace_refs_with_stubs, - substitute_placeholder_defaults, -) -from sqlbuild.compiler.compile._helpers.analysis.cte_facts import ( - _polyglot_cte_passthrough_facts, - _polyglot_filtered_non_null_outputs, -) -from sqlbuild.compiler.compile._helpers.sharing.binding import ( - binding_query_fields, - lineage_reference_map, - normalized_analysis_sql, - prepare_binding_queries, - relation_stubs_collide, - remembered_shared_results, - reused_shared_results, - shared_result_is_exact, - shared_result_keys, -) -from sqlbuild.compiler.compile.constants import ( - COMPACT_ANALYSIS_FACT_LENGTH, - COMPACT_ANALYSIS_LEGACY_RESPONSE_LENGTH, - COMPACT_ANALYSIS_RESPONSE_LENGTH, - COMPACT_ANALYSIS_SOURCE_LENGTH, - COMPACT_RELATION_STUB_PREFIX, - RESOLVED_SOURCE_CONFIDENCE, - SQL_WILDCARD_TOKEN, - UNKNOWN_SQL_TYPE_NAME, -) -from sqlbuild.compiler.compile.exceptions import CompactAnalysisInputError -from sqlbuild.compiler.compile.models import ( - CompactBatchContext, - CompactBatchExecutionOptions, - CompactBatchInputs, - CompactBatchPreparation, - CompactLineageFacts, - CompactProjectedFacts, - CompactProjectionCaches, - CompiledLineageColumnFact, - CompiledLineageSourceFact, - CompileSqlReference, - CteFactResolvers, - InferredColumn, - NativeCompactAnalysis, - PolyglotAnalysisResult, - PreparedBindingQuery, - ProjectedAnalysisRequest, - SharedBindingQuery, -) -from sqlbuild.compiler.compile.types import CompactBatchResponseCallback, CompiledResourceType -from sqlbuild.compiler.lineage.types import ( - ColumnLineageConfidence, - ColumnTransformKind, - InferredNullability, -) -from sqlbuild.compiler.profiling.main.record import record_compile_timing -from sqlbuild.compiler.sql_analysis.constants import ( - POLYGLOT_ANALYSIS_BASE_TABLES as _POLYGLOT_ANALYSIS_BASE_TABLES, -) -from sqlbuild.compiler.sql_analysis.constants import ( - POLYGLOT_ANALYSIS_CAST_TYPE as _POLYGLOT_ANALYSIS_CAST_TYPE, -) -from sqlbuild.compiler.sql_analysis.constants import ( - POLYGLOT_ANALYSIS_FUNCTION_NAME as _POLYGLOT_ANALYSIS_FUNCTION_NAME, -) -from sqlbuild.compiler.sql_analysis.constants import ( - POLYGLOT_ANALYSIS_IS_STAR as _POLYGLOT_ANALYSIS_IS_STAR, -) -from sqlbuild.compiler.sql_analysis.constants import ( - POLYGLOT_ANALYSIS_NAME as _POLYGLOT_ANALYSIS_NAME, -) -from sqlbuild.compiler.sql_analysis.constants import ( - POLYGLOT_ANALYSIS_NULLABILITY as _POLYGLOT_ANALYSIS_NULLABILITY, -) -from sqlbuild.compiler.sql_analysis.constants import ( - POLYGLOT_ANALYSIS_NULLABILITY_NON_NULL as _POLYGLOT_ANALYSIS_NULLABILITY_NON_NULL, -) -from sqlbuild.compiler.sql_analysis.constants import ( - POLYGLOT_ANALYSIS_NULLABILITY_NULLABLE as _POLYGLOT_ANALYSIS_NULLABILITY_NULLABLE, -) -from sqlbuild.compiler.sql_analysis.constants import ( - POLYGLOT_ANALYSIS_PROJECTIONS as _POLYGLOT_ANALYSIS_PROJECTIONS, -) -from sqlbuild.compiler.sql_analysis.constants import ( - POLYGLOT_ANALYSIS_RELATIONS as _POLYGLOT_ANALYSIS_RELATIONS, -) -from sqlbuild.compiler.sql_analysis.constants import ( - POLYGLOT_ANALYSIS_SHAPE as _POLYGLOT_ANALYSIS_SHAPE, -) -from sqlbuild.compiler.sql_analysis.constants import ( - POLYGLOT_ANALYSIS_SHAPE_SELECT as _POLYGLOT_ANALYSIS_SHAPE_SELECT, -) -from sqlbuild.compiler.sql_analysis.constants import ( - POLYGLOT_ANALYSIS_SHAPE_SET_OPERATION as _POLYGLOT_ANALYSIS_SHAPE_SET_OPERATION, -) -from sqlbuild.compiler.sql_analysis.constants import ( - POLYGLOT_ANALYSIS_SOURCE_ALIAS as _POLYGLOT_ANALYSIS_SOURCE_ALIAS, -) -from sqlbuild.compiler.sql_analysis.constants import ( - POLYGLOT_ANALYSIS_SOURCE_CONFIDENCE as _POLYGLOT_ANALYSIS_SOURCE_CONFIDENCE, -) -from sqlbuild.compiler.sql_analysis.constants import ( - POLYGLOT_ANALYSIS_SOURCE_NAME as _POLYGLOT_ANALYSIS_SOURCE_NAME, -) -from sqlbuild.compiler.sql_analysis.constants import ( - POLYGLOT_ANALYSIS_STAR_PROJECTIONS as _POLYGLOT_ANALYSIS_STAR_PROJECTIONS, -) -from sqlbuild.compiler.sql_analysis.constants import ( - POLYGLOT_ANALYSIS_TABLE as _POLYGLOT_ANALYSIS_TABLE, -) -from sqlbuild.compiler.sql_analysis.constants import ( - POLYGLOT_ANALYSIS_TRANSFORM_AGGREGATION as _POLYGLOT_ANALYSIS_TRANSFORM_AGGREGATION, -) -from sqlbuild.compiler.sql_analysis.constants import ( - POLYGLOT_ANALYSIS_TRANSFORM_CAST as _POLYGLOT_ANALYSIS_TRANSFORM_CAST, -) -from sqlbuild.compiler.sql_analysis.constants import ( - POLYGLOT_ANALYSIS_TRANSFORM_CONSTANT as _POLYGLOT_ANALYSIS_TRANSFORM_CONSTANT, -) -from sqlbuild.compiler.sql_analysis.constants import ( - POLYGLOT_ANALYSIS_TRANSFORM_DIRECT as _POLYGLOT_ANALYSIS_TRANSFORM_DIRECT, -) -from sqlbuild.compiler.sql_analysis.constants import ( - POLYGLOT_ANALYSIS_TRANSFORM_FUNCTION as _POLYGLOT_ANALYSIS_TRANSFORM_FUNCTION, -) -from sqlbuild.compiler.sql_analysis.constants import ( - POLYGLOT_ANALYSIS_TRANSFORM_KIND as _POLYGLOT_ANALYSIS_TRANSFORM_KIND, -) -from sqlbuild.compiler.sql_analysis.constants import ( - POLYGLOT_ANALYSIS_TRANSFORM_STAR as _POLYGLOT_ANALYSIS_TRANSFORM_STAR, -) -from sqlbuild.compiler.sql_analysis.constants import ( - POLYGLOT_ANALYSIS_TYPE_HINT as _POLYGLOT_ANALYSIS_TYPE_HINT, -) -from sqlbuild.compiler.sql_analysis.constants import ( - POLYGLOT_ANALYSIS_UNSAFE_TRANSFORMS as _POLYGLOT_ANALYSIS_UNSAFE_TRANSFORMS, -) -from sqlbuild.compiler.sql_analysis.constants import ( - POLYGLOT_ANALYSIS_UPSTREAM as _POLYGLOT_ANALYSIS_UPSTREAM, -) -from sqlbuild.compiler.sql_analysis.constants import ( - POLYGLOT_PAYLOAD_ALIAS as _POLYGLOT_PAYLOAD_ALIAS, -) -from sqlbuild.compiler.sql_analysis.constants import ( - POLYGLOT_PAYLOAD_COLUMN as _POLYGLOT_PAYLOAD_COLUMN, -) -from sqlbuild.compiler.sql_analysis.exceptions import SqlAnalysisBoundaryError -from sqlbuild.compiler.sql_analysis.main._binding_catalog import create_binding_catalog -from sqlbuild.compiler.sql_analysis.main._decode_schema_validation import decode_schema_validation -from sqlbuild.compiler.sql_analysis.main._normalize_analysis import normalize_analysis_sql -from sqlbuild.compiler.sql_analysis.main._normalize_analysis_batch import ( - normalize_analysis_sql_results, -) -from sqlbuild.compiler.sql_analysis.main._schema_validation import get_schema_validations -from sqlbuild.compiler.sql_analysis.main.import_polyglot_sql import import_polyglot_sql -from sqlbuild.compiler.sql_analysis.models import ( - SqlBindingDiagnostic, - SqlBindingResult, - SqlSchemaValidationRequest, -) -from sqlbuild.compiler.sql_analysis.types import ( - NativeCompactAnalysisJob, - NativeProjectCatalog, - NativeQueryAnalysisModule, -) -from sqlbuild.diagnostics.main.log_debug_event import log_debug_event - -_DEBUG_LOGGER: logging.Logger = logging.getLogger("sqlbuild.compile") -_ANALYSIS_LOCK: ContextVar[threading.Condition | None] = ContextVar( - "sqlbuild_model_analysis_lock", default=None -) -_COMPACT_ANALYSIS_WORKERS: int = 4 -_NATIVE_LEGACY_FALLBACK: str = "native project type recovery requires legacy fallback" - - -@contextmanager -def serialized_analysis(lock: threading.Condition) -> Iterator[None]: - """Mark the held `lock` as the guard of every Python analysis step in this context.""" - - token: Token[threading.Condition | None] = _ANALYSIS_LOCK.set(lock) - try: - yield - finally: - _ANALYSIS_LOCK.reset(token) - - -@contextmanager -def native_section() -> Iterator[None]: - """Release the analysis lock around native work that reads no shared analysis state.""" - - lock: threading.Condition | None = _ANALYSIS_LOCK.get() - if lock is None: - yield - return - lock.release() - try: - yield - finally: - _ = lock.acquire() - - -def infer_columns_with_sql_analysis( - *, - query_sql: str, - placeholders: dict[str, str] | None = None, - column_nullability_by_table: dict[str, dict[str, InferredNullability]] | None = None, - inference_profile: ExpressionInferenceProfile | None = None, -) -> tuple[InferredColumn, ...] | None: - """Infer output columns from model query SQL using SQL analysis.""" - - profile: ExpressionInferenceProfile = inference_profile or ExpressionInferenceProfile() - - cleaned_sql: str = _replace_refs_with_stubs( - query_sql=query_sql, - dialect=profile.sql_analysis_dialect, - ) - if placeholders: - cleaned_sql = substitute_placeholder_defaults( - query_sql=cleaned_sql, placeholders=placeholders - ) - - polyglot_columns: tuple[InferredColumn, ...] | None | bool = _infer_columns_with_polyglot( - cleaned_sql=cleaned_sql, - dialect=profile.sql_analysis_dialect, - column_nullability_by_table=column_nullability_by_table or {}, - inference_profile=profile, - ) - if isinstance(polyglot_columns, tuple): - return polyglot_columns - return None - - -def analyze_columns_and_lineage_with_polyglot( - *, - query_sql: str, - references: tuple[CompileSqlReference, ...] = (), - placeholders: dict[str, str] | None = None, - column_nullability_by_table: dict[str, dict[str, InferredNullability]] | None = None, - column_types_by_table: dict[str, dict[str, str]] | None = None, - inference_profile: ExpressionInferenceProfile | None = None, - allow_compact_analysis: bool = False, - binding_schema: dict[str, dict[str, str]] | None = None, - recover_cte_facts: bool = False, - precomputed: NativeCompactAnalysis | None = None, -) -> PolyglotAnalysisResult: - """Infer columns and compact lineage facts from one Polyglot parse.""" - - profile: ExpressionInferenceProfile = inference_profile or ExpressionInferenceProfile() - cleaned_sql: str = ( - precomputed.cleaned_sql - if precomputed is not None - else _cleaned_analysis_sql( - query_sql=query_sql, - placeholders=placeholders, - dialect=profile.sql_analysis_dialect, - ) - ) - if precomputed is not None and precomputed.projected: - if precomputed.analysis is None and precomputed.compact_rows is None: - return PolyglotAnalysisResult( - analysis_succeeded=False, - binding_diagnostics=precomputed.binding_diagnostics or (), - binding_validated=binding_schema is not None, - ) - return _projected_analysis_result( - request=ProjectedAnalysisRequest( - analysis=precomputed.analysis, - compact_rows=precomputed.compact_rows, - compact_fact_rows=precomputed.compact_fact_rows, - string_pool=precomputed.string_pool, - caches=CompactProjectionCaches( - columns=precomputed.compact_column_cache, - facts=precomputed.compact_fact_cache, - decoded_facts=precomputed.compact_decoded_fact_cache, - ), - template_index=precomputed.compact_template_index, - resource_name_indexes=precomputed.resource_name_indexes, - resource_names=precomputed.resource_names, - binding_diagnostics=( - precomputed.binding_diagnostics - if precomputed.binding_diagnostics is not None - else _validate_complete_binding_schema( - cleaned_sql=cleaned_sql, - dialect=profile.sql_analysis_dialect, - binding_schema=binding_schema, - ) - ), - binding_validated=binding_schema is not None, - ) - ) - polyglot_module: Any = import_polyglot_sql() - compact_result: ( - tuple[tuple[InferredColumn, ...] | None, tuple[CompiledLineageColumnFact, ...], bool] | None - ) = _analyze_columns_and_lineage_with_compact_polyglot( - polyglot_module=polyglot_module, - cleaned_sql=cleaned_sql, - dialect=profile.sql_analysis_dialect, - references=references, - column_nullability_by_table=column_nullability_by_table or {}, - column_types_by_table=column_types_by_table or {}, - inference_profile=profile, - allow_compact_analysis=( - allow_compact_analysis - and not ( - precomputed is not None - and not precomputed.projected - and precomputed.analysis is None - ) - ), - recover_cte_facts=recover_cte_facts, - analysis=precomputed.analysis if precomputed is not None else None, - ) - if compact_result is not None: - return PolyglotAnalysisResult( - analysis_succeeded=True, - columns=compact_result[0], - lineage_columns=compact_result[1], - has_star=compact_result[2], - binding_diagnostics=( - precomputed.binding_diagnostics - if precomputed is not None and precomputed.binding_diagnostics is not None - else _validate_complete_binding_schema( - cleaned_sql=cleaned_sql, - dialect=profile.sql_analysis_dialect, - binding_schema=binding_schema, - ) - ), - binding_validated=binding_schema is not None, - ) - try: - parsed: Any = polyglot_module.parse_one( - cleaned_sql, - dialect=profile.sql_analysis_dialect or "generic", - ) - except polyglot_module.PolyglotError as error: - log_debug_event( - logger=_DEBUG_LOGGER, - message="column and lineage analysis parse failed; falling back", - sqlbuild_error=str(error), - ) - return PolyglotAnalysisResult(analysis_succeeded=False) - columns, legacy_lineage_columns, has_star = _analyze_columns_and_lineage_from_polyglot_ast( - parsed=parsed, - references=references, - column_nullability_by_table=column_nullability_by_table or {}, - column_types_by_table=column_types_by_table or {}, - inference_profile=profile, - recover_cte_facts=recover_cte_facts, - ) - lineage_columns: Sequence[CompiledLineageColumnFact] = legacy_lineage_columns - if precomputed is not None and precomputed.compact_rows is not None: - lineage_columns = _compact_projected_analysis_result( - request=ProjectedAnalysisRequest( - analysis=None, - compact_rows=precomputed.compact_rows, - compact_fact_rows=precomputed.compact_fact_rows, - string_pool=precomputed.string_pool, - caches=CompactProjectionCaches( - columns=precomputed.compact_column_cache, - facts=precomputed.compact_fact_cache, - decoded_facts=precomputed.compact_decoded_fact_cache, - ), - template_index=precomputed.compact_template_index, - resource_name_indexes=precomputed.resource_name_indexes, - resource_names=precomputed.resource_names, - binding_diagnostics=(), - binding_validated=False, - ) - ).lineage_columns - return PolyglotAnalysisResult( - analysis_succeeded=True, - columns=columns, - lineage_columns=lineage_columns, - has_star=has_star, - binding_diagnostics=( - precomputed.binding_diagnostics - if precomputed is not None and precomputed.binding_diagnostics is not None - else _validate_complete_binding_schema( - cleaned_sql=cleaned_sql, - dialect=profile.sql_analysis_dialect, - binding_schema=binding_schema, - ) - ), - binding_validated=binding_schema is not None, - ) - - -def analyze_queries_with_compact_polyglot_batch( - *, - query_sqls: tuple[str, ...], - references: tuple[tuple[CompileSqlReference, ...], ...], - placeholders: tuple[dict[str, str] | None, ...], - column_nullability_by_table: dict[str, dict[str, InferredNullability]], - column_types_by_table: dict[str, dict[str, str]], - inference_profile: ExpressionInferenceProfile, - recover_cte_facts: tuple[bool, ...], - rich_type_inference: bool = True, - cached_batch: tuple[CompactBatchPreparation, object] | None = None, - execution: CompactBatchExecutionOptions | None = None, -) -> tuple[NativeCompactAnalysis, ...]: - """Analyze rendered SQL in one bounded native call, preserving input order.""" - - options: CompactBatchExecutionOptions = execution or CompactBatchExecutionOptions() - binding_schemas: tuple[dict[str, dict[str, str]] | None, ...] | None = options.binding_schemas - - if not (len(query_sqls) == len(references) == len(placeholders) == len(recover_cte_facts)): - raise CompactAnalysisInputError( - "compact query-analysis batch inputs must have equal lengths" - ) - if binding_schemas is not None and len(binding_schemas) != len(query_sqls): - raise CompactAnalysisInputError("binding schemas must match the query batch length") - if cached_batch is not None: - if len(cached_batch[0].cleaned_sql) != len(query_sqls): - raise CompactAnalysisInputError( - "cached compact query-analysis preparation has an invalid length" - ) - with record_compile_timing("analysis_projection_ms"): - return _project_compact_analysis_batch( - preparation=cached_batch[0], response_payload=cached_batch[1] - ) - inputs: CompactBatchInputs = CompactBatchInputs( - query_sqls=query_sqls, - references=references, - placeholders=placeholders, - column_nullability_by_table=column_nullability_by_table, - column_types_by_table=column_types_by_table, - inference_profile=inference_profile, - recover_cte_facts=recover_cte_facts, - rich_type_inference=rich_type_inference, - binding_schemas=binding_schemas, - ) - reuse_results: bool = options.on_response is None and binding_schemas is not None - with record_compile_timing("analysis_preparation_ms"): - context: CompactBatchContext = _compact_batch_context( - inputs=inputs, - share=True, - shareable_prekeys=options.shareable_prekeys if reuse_results else None, - ) - memo: dict[object, object] | None = ( - cast(dict[object, object], context.binding_catalog.shared_analyses) - if reuse_results and context.binding_catalog is not None - else None - ) - memo_keys: tuple[tuple[object, ...] | None, ...] = shared_result_keys( - inputs=inputs, context=context - ) - reused: dict[int, NativeCompactAnalysis] = ( - reused_shared_results(inputs=inputs, context=context, keys=memo_keys, memo=memo) - if memo is not None - else {} - ) - analyzed: tuple[int, ...] = tuple( - index for index in range(len(query_sqls)) if index not in reused - ) - analyzed_results: tuple[NativeCompactAnalysis, ...] = () - if analyzed: - analyzed_inputs: CompactBatchInputs = _batch_input_subset(inputs=inputs, indexes=analyzed) - recomputed: tuple[int, ...] - analyzed_results, recomputed = _analyze_compact_inputs( - inputs=analyzed_inputs, - context=_batch_context_subset(context=context, indexes=analyzed), - on_response=options.on_response if not reused else None, - ) - if memo is not None: - for key, result in remembered_shared_results( - keys=tuple( - None if position in recomputed else memo_keys[index] - for position, index in enumerate(analyzed) - ), - results=analyzed_results, - ).items(): - memo.setdefault(key, result) - results: list[NativeCompactAnalysis | None] = [None] * len(query_sqls) - for index, result in zip(analyzed, analyzed_results, strict=True): - results[index] = result - for index, result in reused.items(): - results[index] = result - return tuple(cast(NativeCompactAnalysis, result) for result in results) - - -def _analyze_compact_inputs( - *, - inputs: CompactBatchInputs, - context: CompactBatchContext, - on_response: CompactBatchResponseCallback | None, -) -> tuple[tuple[NativeCompactAnalysis, ...], tuple[int, ...]]: - """Run one native batch, re-analysing inexact shared members with their own names.""" - - with record_compile_timing("analysis_preparation_ms"): - preparation: CompactBatchPreparation = _prepare_compact_analysis_batch( - inputs=inputs, context=context - ) - with record_compile_timing("analysis_native_ms"): - response_payload: object = _run_compact_analysis_batch(preparation=preparation) - with record_compile_timing("analysis_projection_ms"): - projected: tuple[NativeCompactAnalysis, ...] = _attach_compiled_bindings( - preparation=preparation, - response=response_payload, - analyses=_project_compact_analysis_batch( - preparation=preparation, - response_payload=response_payload, - ), - ) - member_indexes: tuple[int, ...] = _inexact_shared_members( - preparation=preparation, response=response_payload - ) - if member_indexes: - projected = _reanalyze_shared_members( - member_indexes=member_indexes, projected=projected, request=inputs - ) - elif on_response is not None: - on_response(preparation=preparation, response=response_payload) - return projected, member_indexes - - -def _batch_input_subset( - *, inputs: CompactBatchInputs, indexes: tuple[int, ...] -) -> CompactBatchInputs: - if len(indexes) == len(inputs.query_sqls): - return inputs - return replace( - inputs, - query_sqls=tuple(inputs.query_sqls[index] for index in indexes), - references=tuple(inputs.references[index] for index in indexes), - placeholders=tuple(inputs.placeholders[index] for index in indexes), - recover_cte_facts=tuple(inputs.recover_cte_facts[index] for index in indexes), - binding_schemas=( - tuple(inputs.binding_schemas[index] for index in indexes) - if inputs.binding_schemas is not None - else None - ), - ) - - -def _batch_context_subset( - *, context: CompactBatchContext, indexes: tuple[int, ...] -) -> CompactBatchContext: - if len(indexes) == len(context.normalized_sqls): - return context - return replace( - context, - normalized_sqls=[context.normalized_sqls[index] for index in indexes], - binding_queries=tuple(context.binding_queries[index] for index in indexes), - ) - - -def _inexact_shared_members( - *, preparation: CompactBatchPreparation, response: object -) -> tuple[int, ...]: - if not preparation.shared_query_indexes or not isinstance(response, dict): - return () - payload: dict[str, object] = cast(dict[str, object], response) - validations: object = payload.get("validations") - analyses: object = payload.get("analyses") - templates: object = payload.get("templates") - if not isinstance(analyses, list) or not isinstance(templates, list): - return () - members: list[int] = [] - for index, (projection, analysis) in enumerate( - zip(preparation.projections, analyses, strict=True) - ): - template_index: int = cast(int, projection["templateIndex"]) - query_index: int = cast(int, preparation.templates[template_index]["queryIndex"]) - if query_index not in preparation.shared_query_indexes: - continue - template: object = ( - templates[analysis[0]] - if isinstance(analysis, list) - and analysis - and isinstance(analysis[0], int) - and 0 <= analysis[0] < len(templates) - else str(analysis) - ) - validation: object = ( - cast(list[object], validations)[query_index] if isinstance(validations, list) else None - ) - if not shared_result_is_exact(validation=validation, template=template): - members.append(index) - return tuple(members) - - -def _reanalyze_shared_members( - *, - member_indexes: tuple[int, ...], - projected: tuple[NativeCompactAnalysis, ...], - request: CompactBatchInputs, -) -> tuple[NativeCompactAnalysis, ...]: - """Recompute members of inexact shared queries with their own relation names.""" - - with record_compile_timing("analysis_preparation_ms"): - preparation: CompactBatchPreparation = _prepare_compact_analysis_batch( - inputs=_batch_input_subset(inputs=request, indexes=member_indexes), - share_binding_queries=False, - ) - with record_compile_timing("analysis_native_ms"): - response: object = _run_compact_analysis_batch(preparation=preparation) - with record_compile_timing("analysis_projection_ms"): - replacements: tuple[NativeCompactAnalysis, ...] = _attach_compiled_bindings( - preparation=preparation, - response=response, - analyses=_project_compact_analysis_batch( - preparation=preparation, response_payload=response - ), - ) - results: list[NativeCompactAnalysis] = list(projected) - for index, replacement in zip(member_indexes, replacements, strict=True): - results[index] = replacement - return tuple(results) - - -def _compact_batch_context( - *, - inputs: CompactBatchInputs, - share: bool, - shareable_prekeys: frozenset[str] | None, -) -> CompactBatchContext: - """Prepare the catalog, cleaned SQL, and binding references for one batch.""" - - profile: ExpressionInferenceProfile = inputs.inference_profile - dialect: str | None = profile.sql_analysis_dialect - binding_catalog: Any | None = profile.binding_catalog - if binding_catalog is None and inputs.binding_schemas is not None: - binding_catalog = create_binding_catalog( - dialect=dialect or "generic", - quoted_ignore_case=profile.quoted_identifiers_ignore_case, - known_functions=profile.semantic_known_functions, - known_types=profile.semantic_known_types, - relations=inputs.column_types_by_table, - ) - if binding_catalog is not None: - required_tables: set[str] = set() - for query_references in inputs.references: - required_tables.update( - _analysis_reference_name(reference) for reference in query_references - ) - binding_catalog.prepare_analysis( - types={ - name: inputs.column_types_by_table[name] - for name in required_tables - if name in inputs.column_types_by_table - }, - nullability={ - name: inputs.column_nullability_by_table[name] - for name in required_tables - if name in inputs.column_nullability_by_table - }, - ) - requests: list[tuple[str, None, dict[str, str] | None]] = [ - (query_sql, None, query_placeholders) - for query_sql, query_placeholders in zip( - inputs.query_sqls, inputs.placeholders, strict=True - ) - ] - results: list[str | Exception] = normalize_analysis_sql_results( - dialect=dialect, - requests=requests, - catalog=binding_catalog.native if binding_catalog is not None else None, - ) - normalized_sqls: list[str] = [normalized_analysis_sql(result) for result in results] - binding_queries: tuple[PreparedBindingQuery | None, ...] = ( - prepare_binding_queries( - binding_catalog=binding_catalog, - inputs=inputs, - cleaned_sqls=normalized_sqls, - share=share, - shareable_prekeys=shareable_prekeys, - ) - if inputs.binding_schemas is not None and binding_catalog is not None - else (None,) * len(inputs.query_sqls) - ) - return CompactBatchContext( - binding_catalog=binding_catalog, - normalized_sqls=normalized_sqls, - binding_queries=binding_queries, - ) - - -def _prepare_compact_analysis_batch( - *, - inputs: CompactBatchInputs, - share_binding_queries: bool = True, - context: CompactBatchContext | None = None, -) -> CompactBatchPreparation: - query_sqls: tuple[str, ...] = inputs.query_sqls - references: tuple[tuple[CompileSqlReference, ...], ...] = inputs.references - column_nullability_by_table: dict[str, dict[str, InferredNullability]] = ( - inputs.column_nullability_by_table - ) - column_types_by_table: dict[str, dict[str, str]] = inputs.column_types_by_table - inference_profile: ExpressionInferenceProfile = inputs.inference_profile - recover_cte_facts: tuple[bool, ...] = inputs.recover_cte_facts - rich_type_inference: bool = inputs.rich_type_inference - binding_schemas: tuple[dict[str, dict[str, str]] | None, ...] | None = inputs.binding_schemas - dialect: str | None = inference_profile.sql_analysis_dialect - if context is None: - context = _compact_batch_context( - inputs=inputs, share=share_binding_queries, shareable_prekeys=None - ) - binding_catalog: Any | None = context.binding_catalog - prepared: list[str] = [] - queries: list[dict[str, object]] = [] - query_indexes: dict[tuple[object, ...], int] = {} - templates: list[dict[str, object]] = [] - template_indexes: dict[ - tuple[ - int, - tuple[tuple[str, str], ...], - tuple[tuple[str, str], ...], - tuple[str, ...], - bool, - bool, - ], - int, - ] = {} - projections: list[dict[str, object]] = [] - function_return_types: dict[str, str] = dict(inference_profile.function_return_types) - normalized_sqls: list[str] = context.normalized_sqls - member_binding_schemas: tuple[dict[str, dict[str, str]] | None, ...] = ( - binding_schemas if binding_schemas is not None else (None,) * len(query_sqls) - ) - binding_queries: tuple[PreparedBindingQuery | None, ...] = context.binding_queries - shared_query_indexes: set[int] = set() - members: list[tuple[dict[str, tuple[CompiledResourceType, str]], dict[str, str]]] - stubbed_sqls: dict[int, str | Exception] - members, stubbed_sqls = _member_analysis_stubs( - inputs=inputs, - context=context, - binding_schemas=member_binding_schemas, - ) - for index, ( - cleaned_sql, - query_references, - query_recover_cte_facts, - binding_schema, - binding_query, - (lineage_references, canonical_stubs), - ) in enumerate( - zip( - normalized_sqls, - references, - recover_cte_facts, - member_binding_schemas, - binding_queries, - members, - strict=True, - ) - ): - shared: SharedBindingQuery | None = ( - binding_query.shared if binding_query is not None else None - ) - analysis_sql: str = ( - shared.sql - if shared is not None - else cleaned_sql - if binding_schema is not None - else normalized_analysis_sql(stubbed_sqls[index]) - ) - query: dict[str, object] = { - "sql": analysis_sql, - "dialect": dialect or "generic", - } - schema: dict[str, object] | None = None - if binding_catalog is not None: - query["analysis_references"] = [ - (name, canonical_stubs.get(name, name)) - for name in sorted( - lineage_references, key=lambda name: canonical_stubs.get(name, name) - ) - ] - else: - schema = _compact_analysis_schema( - column_nullability_by_table=column_nullability_by_table, - column_types_by_table=column_types_by_table, - table_names=frozenset( - _analysis_reference_name(reference) for reference in query_references - ), - table_name_aliases=canonical_stubs, - ) - if schema is not None: - query["schema"] = schema - binding_payload: dict[str, object] | None = None - shared_key: tuple[object, ...] | None = ( - (shared.key, query_recover_cte_facts) if shared is not None else None - ) - query_index: int | None = query_indexes.get(shared_key) if shared_key is not None else None - if query_index is None and binding_schema is not None: - if binding_query is None or binding_catalog is None: - raise SqlAnalysisBoundaryError("binding schemas require a native project catalog") - binding_fields: dict[str, object] - binding_fields, binding_payload = binding_query_fields( - binding_query=binding_query, binding_catalog=binding_catalog - ) - query.update(binding_fields) - query_key: tuple[object, ...] - if shared_key is not None: - query_key = shared_key - else: - query_key = ( - analysis_sql, - dialect or "generic", - ( - orjson.dumps( - schema or query.get("analysis_references"), option=orjson.OPT_SORT_KEYS - ) - ), - ( - orjson.dumps(binding_payload, option=orjson.OPT_SORT_KEYS) - if binding_payload is not None - else None - ), - ) - query_index = query_indexes.get(query_key) - if query_index is None: - query_index = len(queries) - query_indexes[query_key] = query_index - queries.append(query) - if shared is not None: - shared_query_indexes.add(query_index) - declared_column_order: tuple[str, ...] = ( - tuple( - column_nullability_by_table.get(_analysis_reference_name(query_references[0]), {}) - ) - if len(query_references) == 1 - else () - ) - reference_types: tuple[tuple[str, str], ...] = tuple( - (canonical_stubs[name], resource_type.value) - for name, (resource_type, _) in lineage_references.items() - ) - template_key: tuple[ - int, - tuple[tuple[str, str], ...], - tuple[tuple[str, str], ...], - tuple[str, ...], - bool, - bool, - ] = ( - query_index, - reference_types, - tuple(function_return_types.items()), - declared_column_order, - query_recover_cte_facts, - rich_type_inference, - ) - template_index: int | None = template_indexes.get(template_key) - if template_index is None: - template_index = len(templates) - template_indexes[template_key] = template_index - templates.append( - { - "queryIndex": query_index, - "references": { - name: { - "resourceType": resource_type, - "resourceName": name, - } - for name, resource_type in reference_types - }, - "functionReturnTypes": function_return_types, - "declaredColumnOrder": list(declared_column_order), - "recoverCteFacts": query_recover_cte_facts, - "richTypeInference": rich_type_inference, - } - ) - projections.append( - { - "templateIndex": template_index, - "resourceNames": { - canonical_stubs[name]: resource_name - for name, (_, resource_name) in lineage_references.items() - }, - } - ) - prepared.append(cleaned_sql) - return CompactBatchPreparation( - cleaned_sql=tuple(prepared), - queries=tuple(queries), - templates=tuple(templates), - projections=tuple(projections), - binding_catalog=binding_catalog, - shared_query_indexes=frozenset(shared_query_indexes), - ) - - -def _member_analysis_stubs( - *, - inputs: CompactBatchInputs, - context: CompactBatchContext, - binding_schemas: tuple[dict[str, dict[str, str]] | None, ...], -) -> tuple[ - list[tuple[dict[str, tuple[CompiledResourceType, str]], dict[str, str]]], - dict[int, str | Exception], -]: - """Return each member's relation stubs and, in one native batch, its stubbed SQL.""" - - members: list[tuple[dict[str, tuple[CompiledResourceType, str]], dict[str, str]]] = [] - stubbed_requests: dict[int, tuple[str, dict[str, str], dict[str, str] | None]] = {} - for index, ( - query_sql, - cleaned_sql, - query_references, - query_placeholders, - member_schema, - member_query, - ) in enumerate( - zip( - inputs.query_sqls, - context.normalized_sqls, - inputs.references, - inputs.placeholders, - binding_schemas, - context.binding_queries, - strict=True, - ) - ): - member: tuple[dict[str, tuple[CompiledResourceType, str]], dict[str, str]] = ( - _member_relation_stubs( - cleaned_sql=cleaned_sql, - references=query_references, - binding_schema=member_schema, - binding_query=member_query, - ) - ) - members.append(member) - if member_schema is None and (member_query is None or member_query.shared is None): - stubbed_requests[index] = (query_sql, member[1], query_placeholders) - stubbed_sqls: list[str | Exception] = normalize_analysis_sql_results( - dialect=inputs.inference_profile.sql_analysis_dialect, - requests=tuple(stubbed_requests.values()), - catalog=(context.binding_catalog.native if context.binding_catalog is not None else None), - ) - return members, dict(zip(stubbed_requests, stubbed_sqls, strict=True)) - - -def _member_relation_stubs( - *, - cleaned_sql: str, - references: tuple[CompileSqlReference, ...], - binding_schema: dict[str, dict[str, str]] | None, - binding_query: PreparedBindingQuery | None, -) -> tuple[dict[str, tuple[CompiledResourceType, str]], dict[str, str]]: - """Return a member's lineage references and the relation names its analysis SQL uses.""" - - lineage_references: dict[str, tuple[CompiledResourceType, str]] = lineage_reference_map( - references - ) - if binding_query is not None and binding_query.shared is not None: - return lineage_references, binding_query.shared.stubs - stubbed_reference_names: frozenset[str] = ( - frozenset() - if binding_schema is not None - or relation_stubs_collide(cleaned_sql=cleaned_sql, names=lineage_references) - else frozenset(lineage_references) - - _qualified_reference_names( - query_sql=cleaned_sql, - reference_names=lineage_references.keys(), - ) - ) - return lineage_references, { - name: f"{COMPACT_RELATION_STUB_PREFIX}{index}" if name in stubbed_reference_names else name - for index, name in enumerate(lineage_references) - } - - -def _run_compact_analysis_batch(*, preparation: CompactBatchPreparation) -> object: - """Analyse every project size with the full worker pool; the rules phase sets peak memory.""" - - workers: int = _COMPACT_ANALYSIS_WORKERS - if preparation.binding_catalog is not None: - job: NativeCompactAnalysisJob = cast( - NativeProjectCatalog, preparation.binding_catalog.native - ).prepare_compact( - orjson.dumps( - { - "queries": preparation.queries, - "templates": preparation.templates, - "projections": preparation.projections, - "workers": workers, - } - ) - ) - with native_section(): - return orjson.loads(job.run()) - request_json: str = orjson.dumps( - { - "queries": preparation.queries, - "templates": preparation.templates, - "projections": preparation.projections, - "workers": workers, - }, - option=orjson.OPT_SORT_KEYS, - ).decode() - with native_section(): - return orjson.loads( - cast(NativeQueryAnalysisModule, _native).analyze_project_queries_compact_json( - request_json - ) - ) - - -def _attach_compiled_bindings( - *, - preparation: CompactBatchPreparation, - response: object, - analyses: tuple[NativeCompactAnalysis, ...], -) -> tuple[NativeCompactAnalysis, ...]: - if not isinstance(response, dict): - return analyses - validations: object = cast(dict[str, object], response).get("validations") - if validations is None: - return analyses - if not isinstance(validations, list) or len(validations) != len(preparation.queries): - raise SqlAnalysisBoundaryError("native compilation returned an invalid binding batch") - results: list[NativeCompactAnalysis] = [] - for analysis, projection in zip(analyses, preparation.projections, strict=True): - template_index: int = cast(int, projection["templateIndex"]) - query_index: int = cast(int, preparation.templates[template_index]["queryIndex"]) - validation: object = validations[query_index] - if validation is None: - results.append(analysis) - continue - binding: SqlBindingResult = decode_schema_validation( - sql=analysis.cleaned_sql, - dialect=cast(str, preparation.queries[query_index]["dialect"]), - response=validation, - ) - results.append(replace(analysis, binding_diagnostics=binding.diagnostics)) - return tuple(results) - - -def _project_compact_analysis_batch( - *, preparation: CompactBatchPreparation, response_payload: object -) -> tuple[NativeCompactAnalysis, ...]: - if not isinstance(response_payload, dict): - raise SqlAnalysisBoundaryError( - "native compact query analysis returned an invalid batch response" - ) - response_mapping: dict[str, object] = cast(dict[str, object], response_payload) - raw_strings: object = response_mapping.get("strings") - raw_facts: object = response_mapping.get("facts") - templates: object = response_mapping.get("templates") - responses: object = response_mapping.get("analyses") - if ( - not isinstance(raw_strings, list) - or not all(isinstance(value, str) for value in raw_strings) - or not isinstance(raw_facts, list) - or not isinstance(templates, list) - or not isinstance(responses, list) - or len(responses) != len(preparation.cleaned_sql) - ): - raise SqlAnalysisBoundaryError( - "native compact query analysis returned an invalid batch response" - ) - string_pool: tuple[str, ...] = tuple(cast(list[str], raw_strings)) - column_cache: dict[tuple[int, int | None, int], InferredColumn] = {} - fact_cache: dict[int, CompactProjectedFacts] = {} - decoded_fact_cache: dict[ - int, - tuple[InferredColumn, tuple[int, int, int, tuple[tuple[int, int, int], ...]]], - ] = {} - results: list[NativeCompactAnalysis] = [] - for cleaned_sql, response in zip(preparation.cleaned_sql, responses, strict=True): - if ( - isinstance(response, list) - and len(response) == COMPACT_ANALYSIS_RESPONSE_LENGTH - and isinstance(response[0], int) - and not isinstance(response[0], bool) - and isinstance(response[1], list) - ): - template_index: int = response[0] - if template_index < 0: - raise SqlAnalysisBoundaryError( - "native compact query analysis returned an invalid template index" - ) - try: - template: object = templates[template_index] - except IndexError as error: - raise SqlAnalysisBoundaryError( - "native compact query analysis returned an invalid template index" - ) from error - if isinstance(template, str): - log_debug_event( - logger=_DEBUG_LOGGER, - message="native compact query analysis failed", - sqlbuild_error=template, - ) - results.append( - NativeCompactAnalysis( - cleaned_sql=cleaned_sql, - analysis=None, - projected=template != _NATIVE_LEGACY_FALLBACK, - ) - ) - continue - legacy_type_recovery: bool = ( - isinstance(template, list) - and len(template) == COMPACT_ANALYSIS_LEGACY_RESPONSE_LENGTH - and template[2] == _NATIVE_LEGACY_FALLBACK - ) - if not ( - isinstance(template, list) - and ( - len(template) == COMPACT_ANALYSIS_RESPONSE_LENGTH - or legacy_type_recovery - or ( - len(template) == COMPACT_ANALYSIS_LEGACY_RESPONSE_LENGTH - and isinstance(template[2], bool) - ) - ) - and isinstance(template[0], list) - and isinstance(template[1], bool) - ): - raise SqlAnalysisBoundaryError( - "native compact query analysis returned an invalid template" - ) - resource_name_indexes: dict[int, int] = {} - for raw_mapping in response[1]: - if not ( - isinstance(raw_mapping, list) - and len(raw_mapping) == COMPACT_ANALYSIS_RESPONSE_LENGTH - and all( - isinstance(value, int) and not isinstance(value, bool) - for value in raw_mapping - ) - ): - raise SqlAnalysisBoundaryError( - "native compact query analysis returned an invalid resource mapping" - ) - canonical_index, resource_index = cast(tuple[int, int], tuple(raw_mapping)) - try: - _ = string_pool[canonical_index] - _ = string_pool[resource_index] - except IndexError as error: - raise SqlAnalysisBoundaryError( - "native compact query analysis returned an out-of-range resource index" - ) from error - resource_name_indexes[canonical_index] = resource_index - results.append( - NativeCompactAnalysis( - cleaned_sql=cleaned_sql, - analysis=None - if legacy_type_recovery - else { - "hasStar": template[1], - "starResolved": len(template) == COMPACT_ANALYSIS_LEGACY_RESPONSE_LENGTH - and template[2] is True, - }, - projected=not legacy_type_recovery, - compact_rows=cast(list[object], template[0]), - compact_fact_rows=cast(list[object], raw_facts), - string_pool=string_pool, - compact_column_cache=column_cache, - compact_template_index=template_index, - compact_fact_cache=fact_cache, - compact_decoded_fact_cache=decoded_fact_cache, - resource_name_indexes=resource_name_indexes, - ) - ) - continue - log_debug_event( - logger=_DEBUG_LOGGER, - message="native compact query analysis failed", - sqlbuild_error=str(response or "invalid native response"), - ) - results.append( - NativeCompactAnalysis(cleaned_sql=cleaned_sql, analysis=None, projected=True) - ) - return tuple(results) - - -def _projected_analysis_result(*, request: ProjectedAnalysisRequest) -> PolyglotAnalysisResult: - analysis: dict[str, Any] | None = request.analysis - if request.compact_rows is not None: - return _compact_projected_analysis_result(request=request) - if analysis is None: - raise SqlAnalysisBoundaryError("native project query analysis omitted facts") - raw_columns: object = analysis.get("columns") - raw_lineage: object = analysis.get("lineageColumns") - if not isinstance(raw_columns, list) or not isinstance(raw_lineage, list): - raise SqlAnalysisBoundaryError("native project query analysis returned invalid facts") - columns: list[InferredColumn] = [] - for raw_column in raw_columns: - if not isinstance(raw_column, dict): - raise SqlAnalysisBoundaryError("native project query analysis returned invalid columns") - name: object = raw_column.get("name") - if not isinstance(name, str): - raise SqlAnalysisBoundaryError("native project query analysis omitted a column name") - data_type: object = raw_column.get("type") - columns.append( - InferredColumn( - name=name, - type=data_type if isinstance(data_type, str) else None, - nullability=InferredNullability(str(raw_column.get("nullability") or "unknown")), - ) - ) - lineage_columns: list[CompiledLineageColumnFact] = [] - for raw_column in raw_lineage: - if not isinstance(raw_column, dict): - raise SqlAnalysisBoundaryError("native project query analysis returned invalid lineage") - output_column: object = raw_column.get("outputColumn") - raw_upstream: object = raw_column.get("upstreamColumns") - if not isinstance(output_column, str) or not isinstance(raw_upstream, list): - raise SqlAnalysisBoundaryError("native project query analysis omitted lineage fields") - upstream: list[CompiledLineageSourceFact] = [] - for raw_source in raw_upstream: - if not isinstance(raw_source, dict): - raise SqlAnalysisBoundaryError( - "native project query analysis returned invalid upstream lineage" - ) - upstream.append( - CompiledLineageSourceFact( - resource_type=str(raw_source.get("resourceType") or ""), - resource_name=str(raw_source.get("resourceName") or ""), - column_name=str(raw_source.get("columnName") or ""), - ) - ) - lineage_columns.append( - CompiledLineageColumnFact( - output_column=output_column, - upstream_columns=tuple(upstream), - transform_kind=ColumnTransformKind( - str(raw_column.get("transformKind") or "unknown") - ), - confidence=ColumnLineageConfidence(str(raw_column.get("confidence") or "unknown")), - ) - ) - return PolyglotAnalysisResult( - analysis_succeeded=True, - columns=tuple(columns), - lineage_columns=tuple(lineage_columns), - has_star=bool(analysis.get("hasStar")), - star_resolved=bool(analysis.get("starResolved")), - binding_diagnostics=request.binding_diagnostics, - binding_validated=request.binding_validated, - ) - - -def _compact_projected_analysis_result( - *, request: ProjectedAnalysisRequest -) -> PolyglotAnalysisResult: - rows: list[object] = request.compact_rows or [] - fact_rows: list[object] = request.compact_fact_rows or [] - string_pool: tuple[str, ...] = request.string_pool - cached_facts: CompactProjectedFacts | None = request.caches.fact(request.template_index) - if cached_facts is not None: - return PolyglotAnalysisResult( - analysis_succeeded=True, - columns=cached_facts.columns, - lineage_columns=CompactLineageFacts( - string_pool=string_pool, - rows=cached_facts.lineage_rows, - resource_name_indexes=request.resource_name_indexes, - resource_names=request.resource_names, - ), - has_star=bool(request.analysis and request.analysis.get("hasStar")), - star_resolved=bool(request.analysis and request.analysis.get("starResolved")), - binding_diagnostics=request.binding_diagnostics, - binding_validated=request.binding_validated, - ) - nullability_by_code: tuple[InferredNullability, ...] = ( - InferredNullability.UNKNOWN, - InferredNullability.NON_NULL, - InferredNullability.NULLABLE, - ) - transform_by_code: tuple[ColumnTransformKind, ...] = ( - ColumnTransformKind.DIRECT, - ColumnTransformKind.CAST, - ColumnTransformKind.EXPRESSION, - ColumnTransformKind.AGGREGATION, - ColumnTransformKind.STAR, - ColumnTransformKind.CONSTANT, - ) - confidence_by_code: tuple[ColumnLineageConfidence, ...] = ( - ColumnLineageConfidence.UNKNOWN, - ColumnLineageConfidence.HIGH, - ColumnLineageConfidence.MEDIUM, - ) - - def pooled_string(value: object) -> str: - if not isinstance(value, int) or isinstance(value, bool): - raise SqlAnalysisBoundaryError("native compact analysis returned an invalid index") - try: - return string_pool[value] - except IndexError as error: - raise SqlAnalysisBoundaryError( - "native compact analysis returned an out-of-range index" - ) from error - - columns: list[InferredColumn] = [] - compact_lineage_rows: list[tuple[int, int, int, tuple[tuple[int, int, int], ...]]] = [] - for raw_fact_index in rows: - if ( - not isinstance(raw_fact_index, int) - or isinstance(raw_fact_index, bool) - or raw_fact_index < 0 - ): - raise SqlAnalysisBoundaryError("native compact analysis returned an invalid fact index") - decoded_fact: ( - tuple[ - InferredColumn, - tuple[int, int, int, tuple[tuple[int, int, int], ...]], - ] - | None - ) = request.caches.decoded_fact(raw_fact_index) - if decoded_fact is not None: - column, lineage_row = decoded_fact - columns.append(column) - compact_lineage_rows.append(lineage_row) - continue - try: - raw_row: object = fact_rows[raw_fact_index] - except IndexError as error: - raise SqlAnalysisBoundaryError( - "native compact analysis returned an out-of-range fact index" - ) from error - if not isinstance(raw_row, list) or len(raw_row) != COMPACT_ANALYSIS_FACT_LENGTH: - raise SqlAnalysisBoundaryError("native compact analysis returned an invalid column") - name_index, type_index, nullability_code, transform_code, confidence_code, raw_upstream = ( - raw_row - ) - if ( - not isinstance(nullability_code, int) - or isinstance(nullability_code, bool) - or not isinstance(transform_code, int) - or isinstance(transform_code, bool) - or not isinstance(confidence_code, int) - or isinstance(confidence_code, bool) - or not isinstance(raw_upstream, list) - ): - raise SqlAnalysisBoundaryError("native compact analysis returned invalid column facts") - try: - nullability: InferredNullability = nullability_by_code[nullability_code] - _ = transform_by_code[transform_code] - _ = confidence_by_code[confidence_code] - except IndexError as error: - raise SqlAnalysisBoundaryError( - "native compact analysis returned an invalid fact code" - ) from error - if not isinstance(name_index, int) or isinstance(name_index, bool): - raise SqlAnalysisBoundaryError("native compact analysis returned an invalid name index") - if type_index is not None and ( - not isinstance(type_index, int) or isinstance(type_index, bool) - ): - raise SqlAnalysisBoundaryError("native compact analysis returned an invalid type index") - column_key: tuple[int, int | None, int] = (name_index, type_index, nullability_code) - column: InferredColumn | None = request.caches.column(column_key) - if column is None: - column = InferredColumn( - name=pooled_string(name_index), - type=pooled_string(type_index) if type_index is not None else None, - nullability=nullability, - ) - request.caches.remember_column(key=column_key, column=column) - columns.append(column) - upstream: list[tuple[int, int, int]] = [] - for raw_source in raw_upstream: - if ( - not isinstance(raw_source, list) - or len(raw_source) != COMPACT_ANALYSIS_SOURCE_LENGTH - ): - raise SqlAnalysisBoundaryError( - "native compact analysis returned invalid upstream lineage" - ) - if ( - type(raw_source[0]) is not int - or type(raw_source[1]) is not int - or type(raw_source[2]) is not int - ): - raise SqlAnalysisBoundaryError( - "native compact analysis returned invalid upstream indexes" - ) - source_key: tuple[int, int, int] = cast(tuple[int, int, int], tuple(raw_source)) - _ = pooled_string(source_key[0]) - _ = pooled_string(source_key[1]) - _ = pooled_string(source_key[2]) - upstream.append(source_key) - lineage_row: tuple[int, int, int, tuple[tuple[int, int, int], ...]] = ( - name_index, - transform_code, - confidence_code, - tuple(upstream), - ) - compact_lineage_rows.append(lineage_row) - request.caches.remember_decoded_fact(fact_index=raw_fact_index, fact=(column, lineage_row)) - compact_facts: CompactProjectedFacts = CompactProjectedFacts( - columns=tuple(columns), - lineage_rows=tuple(compact_lineage_rows), - ) - request.caches.remember_fact(template_index=request.template_index, fact=compact_facts) - return PolyglotAnalysisResult( - analysis_succeeded=True, - columns=compact_facts.columns, - lineage_columns=CompactLineageFacts( - string_pool=string_pool, - rows=compact_facts.lineage_rows, - resource_name_indexes=request.resource_name_indexes, - resource_names=request.resource_names, - ), - has_star=bool(request.analysis and request.analysis.get("hasStar")), - star_resolved=bool(request.analysis and request.analysis.get("starResolved")), - binding_diagnostics=request.binding_diagnostics, - binding_validated=request.binding_validated, - ) - - -def _cleaned_analysis_sql( - *, - query_sql: str, - placeholders: dict[str, str] | None, - dialect: str | None, - relation_stubs: dict[str, str] | None = None, -) -> str: - return normalize_analysis_sql( - sql=query_sql, dialect=dialect, stubs=relation_stubs, placeholders=placeholders - ) - - -def get_complete_schema_binding_request( - *, - query_sql: str, - placeholders: dict[str, str] | None, - dialect: str | None, - binding_schema: dict[str, dict[str, str]], - known_functions: tuple[str, ...] = (), - known_types: tuple[str, ...] = (), - cleaned_sql: str | None = None, -) -> SqlSchemaValidationRequest: - """Build one stable native schema-validation request.""" - - if cleaned_sql is None: - cleaned_sql = normalize_analysis_sql( - sql=query_sql, dialect=dialect, placeholders=placeholders - ) - return SqlSchemaValidationRequest( - sql=cleaned_sql, - dialect=dialect, - schema=binding_schema, - known_functions=known_functions, - known_types=known_types, - ) - - -def _validate_complete_binding_schema( - *, - cleaned_sql: str, - dialect: str | None, - binding_schema: dict[str, dict[str, str]] | None, -) -> tuple[SqlBindingDiagnostic, ...]: - if binding_schema is None: - return () - return get_schema_validations( - requests=( - SqlSchemaValidationRequest( - sql=cleaned_sql, - dialect=dialect, - schema=binding_schema, - ), - ) - )[0].diagnostics - - -def _analyze_columns_and_lineage_with_compact_polyglot( - *, - polyglot_module: Any, - cleaned_sql: str, - dialect: str | None, - references: tuple[CompileSqlReference, ...], - column_nullability_by_table: dict[str, dict[str, InferredNullability]], - column_types_by_table: dict[str, dict[str, str]], - inference_profile: ExpressionInferenceProfile, - allow_compact_analysis: bool, - recover_cte_facts: bool, - analysis: dict[str, Any] | None = None, -) -> tuple[tuple[InferredColumn, ...] | None, tuple[CompiledLineageColumnFact, ...], bool] | None: - if not allow_compact_analysis: - return None - try: - options: dict[str, object] = {"dialect": dialect or "generic"} - schema: dict[str, object] | None = _compact_analysis_schema( - column_nullability_by_table=column_nullability_by_table, - column_types_by_table=column_types_by_table, - table_names=frozenset(_analysis_reference_name(reference) for reference in references), - ) - if schema is not None: - options["schema"] = schema - if analysis is None: - analysis = polyglot_module.analyze_query(cleaned_sql, options) - except polyglot_module.PolyglotError as error: - log_debug_event( - logger=_DEBUG_LOGGER, - message="compact query analysis failed; falling back", - sqlbuild_error=str(error), - ) - return None - if not isinstance(analysis, dict): - return None - projections: object = analysis.get(_POLYGLOT_ANALYSIS_PROJECTIONS) - if not isinstance(projections, list): - return None - if not _compact_analysis_is_eligible(analysis=analysis, projections=projections): - return None - reference_map: dict[str, tuple[CompiledResourceType, str]] = lineage_reference_map(references) - relation_alias_by_name: dict[str, str | None] = _compact_relation_alias_by_name(analysis) - cte_passthrough_types, cte_passthrough_nullability, direct_cte_outputs, parsed = ( - _polyglot_cte_passthrough_facts( - polyglot_module=polyglot_module, - cleaned_sql=cleaned_sql, - dialect=dialect, - column_types_by_table=column_types_by_table, - column_nullability_by_table=column_nullability_by_table, - inference_profile=inference_profile, - analysis=analysis, - resolvers=CteFactResolvers( - expression_type=_polyglot_expression_type, - nullability=_infer_polyglot_nullability, - shallow_nullability=_infer_polyglot_shallow_nullability, - alias_nullability=_polyglot_alias_nullability_from_select, - ), - ) - if recover_cte_facts - else ({}, {}, frozenset(), None) - ) - filtered_non_null_outputs: frozenset[str] = _polyglot_filtered_non_null_outputs( - polyglot_module=polyglot_module, - cleaned_sql=cleaned_sql, - dialect=dialect, - analysis=analysis, - column_nullability_by_table=column_nullability_by_table, - parsed=parsed, - ) - columns: list[InferredColumn] = [] - lineage_columns: list[CompiledLineageColumnFact] = [] - has_star: bool = _compact_analysis_has_star(analysis) - infer_nullability: bool = ( - analysis.get(_POLYGLOT_ANALYSIS_SHAPE) != _POLYGLOT_ANALYSIS_SHAPE_SET_OPERATION - ) - for projection in projections: - if not isinstance(projection, dict): - return None - if bool(projection.get(_POLYGLOT_ANALYSIS_IS_STAR)): - continue - output_column: str = str(projection.get(_POLYGLOT_ANALYSIS_NAME) or "") - if not output_column or output_column == SQL_WILDCARD_TOKEN: - continue - columns.append( - InferredColumn( - name=output_column, - type=( - cte_passthrough_types.get(output_column) - if output_column in direct_cte_outputs - else _compact_projection_type( - projection=projection, inference_profile=inference_profile - ) - ), - nullability=( - InferredNullability.NON_NULL - if output_column in filtered_non_null_outputs - else ( - ( - cte_passthrough_nullability.get(output_column) - if output_column in direct_cte_outputs - else None - ) - or _compact_projection_nullability( - projection=projection, - infer_nullability=infer_nullability, - ) - ) - ), - ) - ) - upstream_columns, confidence = _compact_lineage_upstream_columns( - projection=projection, - reference_map=reference_map, - relation_alias_by_name=relation_alias_by_name, - ) - transform_kind: ColumnTransformKind = _compact_transform_kind( - projection=projection, - has_upstream=bool(upstream_columns), - ) - lineage_columns.append( - CompiledLineageColumnFact( - output_column=output_column, - upstream_columns=upstream_columns, - transform_kind=transform_kind, - confidence=confidence - if upstream_columns or transform_kind == ColumnTransformKind.CONSTANT - else ColumnLineageConfidence.UNKNOWN, - ) - ) - if has_star and len(references) == 1: - schema_name: str = _analysis_reference_name(references[0]) - declared_order: dict[str, int] = { - column_name: index - for index, column_name in enumerate(column_nullability_by_table.get(schema_name, {})) - } - fallback_order: int = len(declared_order) - columns.sort(key=lambda column: declared_order.get(column.name, fallback_order)) - lineage_columns.sort( - key=lambda column: declared_order.get(column.output_column, fallback_order) - ) - return tuple(columns), tuple(lineage_columns), has_star - - -def _compact_analysis_is_eligible(*, analysis: dict[str, Any], projections: list[object]) -> bool: - shape: object = analysis.get(_POLYGLOT_ANALYSIS_SHAPE) - if shape not in {_POLYGLOT_ANALYSIS_SHAPE_SELECT, _POLYGLOT_ANALYSIS_SHAPE_SET_OPERATION}: - return False - projection: object - for projection in projections: - if not isinstance(projection, dict): - return False - projection_dict: dict[str, Any] = cast(dict[str, Any], projection) - transform_kind: str = str(projection_dict.get(_POLYGLOT_ANALYSIS_TRANSFORM_KIND) or "") - if transform_kind in _POLYGLOT_ANALYSIS_UNSAFE_TRANSFORMS: - return False - upstream_values: object = projection_dict.get(_POLYGLOT_ANALYSIS_UPSTREAM) - if transform_kind == _POLYGLOT_ANALYSIS_TRANSFORM_CAST and ( - not isinstance(upstream_values, list) or not upstream_values - ): - return False - return True - - -def _compact_analysis_schema( - *, - column_nullability_by_table: dict[str, dict[str, InferredNullability]], - column_types_by_table: dict[str, dict[str, str]], - table_names: frozenset[str] | None = None, - table_name_aliases: dict[str, str] | None = None, -) -> dict[str, object] | None: - tables: list[dict[str, object]] = [] - table_name: str - columns: dict[str, InferredNullability] - selected_tables: tuple[tuple[str, dict[str, InferredNullability]], ...] = ( - tuple(sorted(column_nullability_by_table.items())) - if table_names is None - else tuple( - (table_name, column_nullability_by_table.get(table_name, {})) - for table_name in sorted( - table_names, - key=lambda name: (table_name_aliases or {}).get(name, name), - ) - ) - ) - for table_name, columns in selected_tables: - if not columns: - continue - column_types: dict[str, str] = column_types_by_table.get(table_name, {}) - tables.append( - { - "name": (table_name_aliases or {}).get(table_name, table_name), - "columns": [ - _compact_analysis_schema_column( - column_name=column_name, - column_type=column_types.get(column_name, "UNKNOWN"), - nullability=columns[column_name], - ) - for column_name in columns - ], - } - ) - if not tables: - return None - return {"tables": tables} - - -def _compact_analysis_schema_column( - *, - column_name: str, - column_type: str, - nullability: InferredNullability, -) -> dict[str, object]: - column: dict[str, object] = {"name": column_name, "type": column_type} - if nullability == InferredNullability.NON_NULL: - column["nullable"] = False - elif nullability == InferredNullability.NULLABLE: - column["nullable"] = True - return column - - -def _compact_relation_alias_by_name(analysis: dict[str, Any]) -> dict[str, str | None]: - alias_by_name: dict[str, str | None] = {} - relation_key: str - for relation_key in (_POLYGLOT_ANALYSIS_RELATIONS, _POLYGLOT_ANALYSIS_BASE_TABLES): - relations: object = analysis.get(relation_key) - if not isinstance(relations, list): - continue - relation: object - for relation in relations: - if not isinstance(relation, dict): - continue - name: object = relation.get(_POLYGLOT_ANALYSIS_NAME) - if not isinstance(name, str) or not name: - continue - alias: object = relation.get(_POLYGLOT_PAYLOAD_ALIAS) - alias_by_name[name] = alias if isinstance(alias, str) and alias else None - return alias_by_name - - -def _compact_analysis_has_star(analysis: dict[str, Any]) -> bool: - star_projections: object = analysis.get(_POLYGLOT_ANALYSIS_STAR_PROJECTIONS) - return isinstance(star_projections, list) and bool(star_projections) - - -def _compact_projection_type( - *, projection: dict[str, Any], inference_profile: ExpressionInferenceProfile -) -> str | None: - cast_type: object = projection.get(_POLYGLOT_ANALYSIS_CAST_TYPE) - if isinstance(cast_type, str) and cast_type and cast_type != UNKNOWN_SQL_TYPE_NAME: - return cast_type - transform_function: object = projection.get(_POLYGLOT_ANALYSIS_TRANSFORM_FUNCTION) - if isinstance(transform_function, dict): - function_name: object = transform_function.get(_POLYGLOT_ANALYSIS_FUNCTION_NAME) - if isinstance(function_name, str): - declared_type: str | None = inference_profile.function_return_type(function_name) - if declared_type is not None: - return declared_type - type_hint: object = projection.get(_POLYGLOT_ANALYSIS_TYPE_HINT) - if isinstance(type_hint, str) and type_hint and type_hint != UNKNOWN_SQL_TYPE_NAME: - return type_hint - return None - - -def _compact_projection_nullability( - *, - projection: dict[str, Any], - infer_nullability: bool, -) -> InferredNullability: - if not infer_nullability: - return InferredNullability.UNKNOWN - value: object = projection.get(_POLYGLOT_ANALYSIS_NULLABILITY) - if value == _POLYGLOT_ANALYSIS_NULLABILITY_NON_NULL: - return InferredNullability.NON_NULL - if value == _POLYGLOT_ANALYSIS_NULLABILITY_NULLABLE: - return InferredNullability.NULLABLE - return InferredNullability.UNKNOWN - - -def _compact_lineage_upstream_columns( - *, - projection: dict[str, Any], - reference_map: dict[str, tuple[CompiledResourceType, str]], - relation_alias_by_name: dict[str, str | None], -) -> tuple[tuple[CompiledLineageSourceFact, ...], ColumnLineageConfidence]: - upstream_values: object = projection.get(_POLYGLOT_ANALYSIS_UPSTREAM) - if not isinstance(upstream_values, list): - return (), ColumnLineageConfidence.UNKNOWN - columns: list[CompiledLineageSourceFact] = [] - seen: set[tuple[CompiledResourceType, str, str]] = set() - confidence: ColumnLineageConfidence = ColumnLineageConfidence.HIGH - upstream: object - for upstream in upstream_values: - if not isinstance(upstream, dict): - continue - column_name: object = upstream.get(_POLYGLOT_PAYLOAD_COLUMN) - if not isinstance(column_name, str) or not column_name or column_name == SQL_WILDCARD_TOKEN: - continue - source_name: object = upstream.get(_POLYGLOT_ANALYSIS_SOURCE_NAME) or upstream.get( - _POLYGLOT_ANALYSIS_TABLE - ) - if not isinstance(source_name, str) or not source_name: - confidence = ColumnLineageConfidence.UNKNOWN - continue - resource: tuple[CompiledResourceType, str] | None = reference_map.get(source_name) - if resource is None: - continue - source_confidence: object = upstream.get(_POLYGLOT_ANALYSIS_SOURCE_CONFIDENCE) - source_alias: object = upstream.get(_POLYGLOT_ANALYSIS_SOURCE_ALIAS) - if source_confidence != RESOLVED_SOURCE_CONFIDENCE and not isinstance(source_alias, str): - confidence = ColumnLineageConfidence.MEDIUM - resource_type, resource_name = resource - key: tuple[CompiledResourceType, str, str] = (resource_type, resource_name, column_name) - if key in seen: - continue - seen.add(key) - columns.append( - CompiledLineageSourceFact( - resource_type=resource_type, - resource_name=resource_name, - column_name=column_name, - ) - ) - return tuple( - sorted( - columns, - key=lambda column: ( - column.resource_type.value, - column.resource_name, - column.column_name, - ), - ) - ), confidence - - -def _compact_transform_kind( - *, projection: dict[str, Any], has_upstream: bool -) -> ColumnTransformKind: - transform_kind: str = str(projection.get(_POLYGLOT_ANALYSIS_TRANSFORM_KIND) or "") - if transform_kind == _POLYGLOT_ANALYSIS_TRANSFORM_STAR: - return ColumnTransformKind.STAR - if transform_kind == _POLYGLOT_ANALYSIS_TRANSFORM_CAST: - return ColumnTransformKind.CAST - if transform_kind == _POLYGLOT_ANALYSIS_TRANSFORM_AGGREGATION: - return ColumnTransformKind.AGGREGATION - if transform_kind == _POLYGLOT_ANALYSIS_TRANSFORM_CONSTANT or not has_upstream: - return ColumnTransformKind.CONSTANT - if transform_kind == _POLYGLOT_ANALYSIS_TRANSFORM_DIRECT: - return ColumnTransformKind.DIRECT - return ColumnTransformKind.EXPRESSION diff --git a/src/sqlbuild/compiler/compile/_helpers/analysis/cte_facts.py b/src/sqlbuild/compiler/compile/_helpers/analysis/cte_facts.py deleted file mode 100644 index f9e4616fec..0000000000 --- a/src/sqlbuild/compiler/compile/_helpers/analysis/cte_facts.py +++ /dev/null @@ -1,1196 +0,0 @@ -"""Conservative CTE output fact recovery for SQL analysis.""" - -from __future__ import annotations - -from typing import Any, Protocol, cast - -from sqlbuild.adapter.contract.models import ExpressionInferenceProfile -from sqlbuild.adapter.contract.types import TypeFamily -from sqlbuild.adapter.type_system.main.normalize_type import normalize_type -from sqlbuild.adapter.type_system.main.types_equal import types_equal -from sqlbuild.compiler.compile.constants import SQL_WILDCARD_TOKEN -from sqlbuild.compiler.compile.models import CteFactResolvers, NonNullFilterContext -from sqlbuild.compiler.lineage.types import InferredNullability -from sqlbuild.compiler.sql_analysis.constants import ( - POLYGLOT_ANALYSIS_COLUMN_USES as _POLYGLOT_ANALYSIS_COLUMN_USES, -) -from sqlbuild.compiler.sql_analysis.constants import ( - POLYGLOT_ANALYSIS_CONTEXT as _POLYGLOT_ANALYSIS_CONTEXT, -) -from sqlbuild.compiler.sql_analysis.constants import ( - POLYGLOT_ANALYSIS_CONTEXT_FILTER as _POLYGLOT_ANALYSIS_CONTEXT_FILTER, -) -from sqlbuild.compiler.sql_analysis.constants import ( - POLYGLOT_ANALYSIS_EXPRESSION_SQL as _POLYGLOT_ANALYSIS_EXPRESSION_SQL, -) -from sqlbuild.compiler.sql_analysis.constants import ( - POLYGLOT_BINARY_OPERAND_COUNT as _POLYGLOT_BINARY_OPERAND_COUNT, -) -from sqlbuild.compiler.sql_analysis.constants import ( - POLYGLOT_BOOLEAN_RESULT_KINDS as _POLYGLOT_BOOLEAN_RESULT_KINDS, -) -from sqlbuild.compiler.sql_analysis.constants import POLYGLOT_KIND_ALIAS as _POLYGLOT_KIND_ALIAS -from sqlbuild.compiler.sql_analysis.constants import POLYGLOT_KIND_AND as _POLYGLOT_KIND_AND -from sqlbuild.compiler.sql_analysis.constants import ( - POLYGLOT_KIND_ANNOTATED as _POLYGLOT_KIND_ANNOTATED, -) -from sqlbuild.compiler.sql_analysis.constants import POLYGLOT_KIND_CASE as _POLYGLOT_KIND_CASE -from sqlbuild.compiler.sql_analysis.constants import POLYGLOT_KIND_CAST as _POLYGLOT_KIND_CAST -from sqlbuild.compiler.sql_analysis.constants import ( - POLYGLOT_KIND_COALESCE as _POLYGLOT_KIND_COALESCE, -) -from sqlbuild.compiler.sql_analysis.constants import POLYGLOT_KIND_COLUMN as _POLYGLOT_KIND_COLUMN -from sqlbuild.compiler.sql_analysis.constants import POLYGLOT_KIND_CONCAT as _POLYGLOT_KIND_CONCAT -from sqlbuild.compiler.sql_analysis.constants import ( - POLYGLOT_KIND_FUNCTION as _POLYGLOT_KIND_FUNCTION, -) -from sqlbuild.compiler.sql_analysis.constants import ( - POLYGLOT_KIND_IF_FUNC as _POLYGLOT_KIND_IF_FUNC, -) -from sqlbuild.compiler.sql_analysis.constants import ( - POLYGLOT_KIND_IS_NULL as _POLYGLOT_KIND_IS_NULL, -) -from sqlbuild.compiler.sql_analysis.constants import POLYGLOT_KIND_LITERAL as _POLYGLOT_KIND_LITERAL -from sqlbuild.compiler.sql_analysis.constants import POLYGLOT_KIND_NULL as _POLYGLOT_KIND_NULL -from sqlbuild.compiler.sql_analysis.constants import POLYGLOT_KIND_PAREN as _POLYGLOT_KIND_PAREN -from sqlbuild.compiler.sql_analysis.constants import POLYGLOT_KIND_SELECT as _POLYGLOT_KIND_SELECT -from sqlbuild.compiler.sql_analysis.constants import ( - POLYGLOT_KIND_SUBSTRING as _POLYGLOT_KIND_SUBSTRING, -) -from sqlbuild.compiler.sql_analysis.constants import POLYGLOT_KIND_TABLE as _POLYGLOT_KIND_TABLE -from sqlbuild.compiler.sql_analysis.constants import ( - POLYGLOT_LITERAL_TYPE_STRING as _POLYGLOT_LITERAL_TYPE_STRING, -) -from sqlbuild.compiler.sql_analysis.constants import ( - POLYGLOT_NULLIF_FUNCTION_NAME as _POLYGLOT_NULLIF_FUNCTION_NAME, -) -from sqlbuild.compiler.sql_analysis.constants import ( - POLYGLOT_PAYLOAD_COLUMN as _POLYGLOT_PAYLOAD_COLUMN, -) -from sqlbuild.compiler.sql_analysis.constants import ( - POLYGLOT_PAYLOAD_LEFT as _POLYGLOT_PAYLOAD_LEFT, -) -from sqlbuild.compiler.sql_analysis.constants import ( - POLYGLOT_PAYLOAD_LITERAL_TYPE as _POLYGLOT_PAYLOAD_LITERAL_TYPE, -) -from sqlbuild.compiler.sql_analysis.constants import POLYGLOT_PAYLOAD_NAME as _POLYGLOT_PAYLOAD_NAME -from sqlbuild.compiler.sql_analysis.constants import ( - POLYGLOT_PAYLOAD_NOT as _POLYGLOT_PAYLOAD_NOT, -) -from sqlbuild.compiler.sql_analysis.constants import ( - POLYGLOT_PAYLOAD_RIGHT as _POLYGLOT_PAYLOAD_RIGHT, -) -from sqlbuild.compiler.sql_analysis.constants import ( - POLYGLOT_PAYLOAD_TABLE as _POLYGLOT_PAYLOAD_TABLE, -) -from sqlbuild.compiler.sql_analysis.constants import ( - POLYGLOT_PAYLOAD_THIS as _POLYGLOT_PAYLOAD_THIS, -) -from sqlbuild.compiler.sql_analysis.constants import ( - POLYGLOT_PAYLOAD_WHERE_CLAUSE as _POLYGLOT_PAYLOAD_WHERE_CLAUSE, -) -from sqlbuild.compiler.sql_analysis.constants import ( - POLYGLOT_SET_OPERATION_KINDS as _POLYGLOT_SET_OPERATION_KINDS, -) -from sqlbuild.compiler.sql_analysis.constants import ( - POLYGLOT_TYPE_PASSTHROUGH_KINDS as _POLYGLOT_TYPE_PASSTHROUGH_KINDS, -) -from sqlbuild.compiler.sql_analysis.constants import SQL_NULL_KEYWORD as _SQL_NULL_KEYWORD - -_NULL_SET_OPERATION_TYPE: str = "__SQLBUILD_NULL_SET_OPERATION_TYPE__" - - -class _ExpressionTypeResolver(Protocol): - def __call__( - self, *, expression: Any, inference_profile: ExpressionInferenceProfile - ) -> str | None: ... - - -class _NullabilityResolver(Protocol): - def __call__( - self, - *, - expression: Any, - alias_nullability: dict[str, InferredNullability], - column_nullability_by_table: dict[str, dict[str, InferredNullability]], - inference_profile: ExpressionInferenceProfile, - ) -> InferredNullability: ... - - -class _ShallowNullabilityResolver(Protocol): - def __call__( - self, *, expression: Any, inference_profile: ExpressionInferenceProfile - ) -> InferredNullability: ... - - -class _AliasNullabilityResolver(Protocol): - def __call__( - self, - *, - select: Any, - column_nullability_by_table: dict[str, dict[str, InferredNullability]], - ) -> dict[str, InferredNullability]: ... - - -def _polyglot_cte_passthrough_facts( - *, - polyglot_module: Any, - cleaned_sql: str, - dialect: str | None, - column_types_by_table: dict[str, dict[str, str]], - column_nullability_by_table: dict[str, dict[str, InferredNullability]], - inference_profile: ExpressionInferenceProfile, - analysis: dict[str, Any], - resolvers: CteFactResolvers, -) -> tuple[dict[str, str], dict[str, InferredNullability], frozenset[str], Any | None]: - """Recover facts that compact analysis skips across direct CTE reads.""" - - if not analysis.get("cteFacts") or not (column_types_by_table or column_nullability_by_table): - return {}, {}, frozenset(), None - try: - parsed: Any = polyglot_module.parse_one(cleaned_sql, dialect=dialect or "generic") - except polyglot_module.PolyglotError: - return {}, {}, frozenset(), None - ctes: tuple[tuple[str, Any, bool], ...] = _polyglot_top_level_ctes(parsed) - if not ctes: - return {}, {}, frozenset(), parsed - inferred_types: dict[str, str] = ( - _polyglot_cte_passthrough_types_from_parsed( - parsed=parsed, - column_types_by_table=column_types_by_table, - inference_profile=inference_profile, - expression_type_resolver=resolvers.expression_type, - ) - if column_types_by_table - else {} - ) - inferred_nullability: dict[str, InferredNullability] = ( - _polyglot_cte_passthrough_nullability_from_parsed( - parsed=parsed, - column_nullability_by_table=column_nullability_by_table, - inference_profile=inference_profile, - nullability_resolver=resolvers.nullability, - shallow_nullability_resolver=resolvers.shallow_nullability, - alias_nullability_resolver=resolvers.alias_nullability, - ) - if column_nullability_by_table - else {} - ) - return ( - inferred_types, - inferred_nullability, - _polyglot_direct_cte_output_names( - parsed=parsed, - cte_names=frozenset(name for name, _, _ in ctes), - ), - parsed, - ) - - -def _polyglot_direct_cte_output_names(*, parsed: Any, cte_names: frozenset[str]) -> frozenset[str]: - normalized_cte_names: frozenset[str] = frozenset(name.casefold() for name in cte_names) - terminal_tables: tuple[Any, ...] = _polyglot_direct_select_tables(parsed) - if not any( - str(getattr(table, "name", "") or "").casefold() in normalized_cte_names - for table in terminal_tables - ): - return frozenset() - output_names: set[str] = set() - projection: Any - for projection in getattr(parsed, "expressions", ()): - projection = _unwrap_polyglot_annotations(projection) - expression: Any = ( - projection.this - if str(getattr(projection, "kind", "")) == _POLYGLOT_KIND_ALIAS - else projection - ) - if str(getattr(expression, "kind", "")) != _POLYGLOT_KIND_COLUMN: - continue - output_name: str = str(getattr(projection, "output_name", "") or "") - if output_name and output_name != SQL_WILDCARD_TOKEN: - output_names.add(output_name) - return frozenset(output_names) - - -def _polyglot_cte_passthrough_types_from_parsed( - *, - parsed: Any, - column_types_by_table: dict[str, dict[str, str]], - inference_profile: ExpressionInferenceProfile, - expression_type_resolver: _ExpressionTypeResolver, - top_level_ctes: tuple[tuple[str, Any, bool], ...] | None = None, - referenced_table_names: tuple[str, ...] | None = None, -) -> dict[str, str]: - ctes: tuple[tuple[str, Any, bool], ...] = ( - _polyglot_top_level_ctes(parsed) if top_level_ctes is None else top_level_ctes - ) - if not ctes: - return {} - relation_types: dict[str, dict[str, str]] = _polyglot_referenced_relation_facts( - parsed=parsed, - facts_by_table=column_types_by_table, - table_names=referenced_table_names, - ) - cte_name: str - cte_body: Any - for cte_name, cte_body, has_column_aliases in ctes: - if has_column_aliases: - continue - inferred: dict[str, str] = _polyglot_select_output_types( - select=cte_body, - relation_types=relation_types, - inference_profile=inference_profile, - expression_type_resolver=expression_type_resolver, - ) - if inferred: - relation_types[cte_name] = inferred - if str(getattr(parsed, "kind", "")) in _POLYGLOT_SET_OPERATION_KINDS: - return _polyglot_set_operation_output_types( - operation=parsed, - relation_types=relation_types, - inference_profile=inference_profile, - expression_type_resolver=expression_type_resolver, - ) - return _polyglot_direct_select_output_types( - select=parsed, - relation_types=relation_types, - inference_profile=inference_profile, - expression_type_resolver=expression_type_resolver, - ) - - -def _polyglot_cte_passthrough_nullability_from_parsed( - *, - parsed: Any, - column_nullability_by_table: dict[str, dict[str, InferredNullability]], - inference_profile: ExpressionInferenceProfile, - nullability_resolver: _NullabilityResolver, - shallow_nullability_resolver: _ShallowNullabilityResolver, - alias_nullability_resolver: _AliasNullabilityResolver, - top_level_ctes: tuple[tuple[str, Any, bool], ...] | None = None, - referenced_table_names: tuple[str, ...] | None = None, -) -> dict[str, InferredNullability]: - ctes: tuple[tuple[str, Any, bool], ...] = ( - _polyglot_top_level_ctes(parsed) if top_level_ctes is None else top_level_ctes - ) - if not ctes: - return {} - relation_nullability: dict[str, dict[str, InferredNullability]] = ( - _polyglot_referenced_relation_facts( - parsed=parsed, - facts_by_table=column_nullability_by_table, - table_names=referenced_table_names, - ) - ) - for cte_name, cte_body, has_column_aliases in ctes: - if has_column_aliases: - continue - inferred: dict[str, InferredNullability] = _polyglot_direct_select_output_nullability( - select=cte_body, - relation_nullability=relation_nullability, - inference_profile=inference_profile, - nullability_resolver=nullability_resolver, - shallow_nullability_resolver=shallow_nullability_resolver, - alias_nullability_resolver=alias_nullability_resolver, - ) - if inferred: - relation_nullability[cte_name] = inferred - return _polyglot_direct_select_output_nullability( - select=parsed, - relation_nullability=relation_nullability, - inference_profile=inference_profile, - nullability_resolver=nullability_resolver, - shallow_nullability_resolver=shallow_nullability_resolver, - alias_nullability_resolver=alias_nullability_resolver, - ) - - -def _polyglot_referenced_relation_facts[T]( - *, - parsed: Any, - facts_by_table: dict[str, dict[str, T]], - table_names: tuple[str, ...] | None = None, -) -> dict[str, dict[str, T]]: - referenced_facts: dict[str, dict[str, T]] = {} - names: tuple[str, ...] = ( - tuple( - str(getattr(table, "name", "") or "") for table in parsed.find_all(_POLYGLOT_KIND_TABLE) - ) - if table_names is None - else table_names - ) - for table_name in names: - column_facts: dict[str, T] | None = facts_by_table.get(table_name) - if column_facts is not None: - referenced_facts[table_name] = column_facts - return referenced_facts - - -def _polyglot_direct_select_output_nullability( - *, - select: Any, - relation_nullability: dict[str, dict[str, InferredNullability]], - inference_profile: ExpressionInferenceProfile, - nullability_resolver: _NullabilityResolver, - shallow_nullability_resolver: _ShallowNullabilityResolver, - alias_nullability_resolver: _AliasNullabilityResolver, -) -> dict[str, InferredNullability]: - if str(getattr(select, "kind", "")) != _POLYGLOT_KIND_SELECT: - return {} - direct_table_names: tuple[str, ...] = tuple( - str(getattr(table, "name", "") or "") for table in _polyglot_direct_select_tables(select) - ) - scoped_nullability: dict[str, dict[str, InferredNullability]] = {} - for table_name in direct_table_names: - column_facts: dict[str, InferredNullability] | None = _case_insensitive_mapping_get( - mapping=relation_nullability, - key=table_name, - ) - if column_facts is not None: - scoped_nullability[table_name] = dict(column_facts) - has_known_nullability: bool = _has_known_nullability(scoped_nullability) - alias_nullability: dict[str, InferredNullability] = ( - alias_nullability_resolver( - select=select, - column_nullability_by_table=scoped_nullability, - ) - if has_known_nullability - else {} - ) - non_null_filter_context: NonNullFilterContext | None = _polyglot_non_null_filter_context( - select=select, - column_nullability_by_table=scoped_nullability, - ) - inferred: dict[str, InferredNullability] = {} - projection: Any - for raw_projection in getattr(select, "expressions", ()): - projection: Any = _unwrap_polyglot_annotations(raw_projection) - if bool(getattr(projection, "is_star", False)): - continue - output_name: str = str(getattr(projection, "output_name", "") or "") - if not output_name or output_name == SQL_WILDCARD_TOKEN: - continue - expression: Any = ( - projection.this - if str(getattr(projection, "kind", "")) == _POLYGLOT_KIND_ALIAS - else projection - ) - nullability: InferredNullability = ( - InferredNullability.NON_NULL - if _polyglot_expression_is_non_null_after_filter( - expression=expression, - context=non_null_filter_context, - ) - else ( - nullability_resolver( - expression=expression, - alias_nullability=alias_nullability, - column_nullability_by_table=scoped_nullability, - inference_profile=inference_profile, - ) - if has_known_nullability - else shallow_nullability_resolver( - expression=expression, - inference_profile=inference_profile, - ) - ) - ) - if nullability != InferredNullability.UNKNOWN: - inferred[output_name] = nullability - return inferred - - -def _polyglot_filtered_non_null_outputs( - *, - polyglot_module: Any, - cleaned_sql: str, - dialect: str | None, - analysis: dict[str, Any], - column_nullability_by_table: dict[str, dict[str, InferredNullability]], - parsed: Any | None = None, -) -> frozenset[str]: - column_uses: object = analysis.get(_POLYGLOT_ANALYSIS_COLUMN_USES) - if not isinstance(column_uses, list) or not any( - isinstance(value, dict) - and value.get(_POLYGLOT_ANALYSIS_CONTEXT) == _POLYGLOT_ANALYSIS_CONTEXT_FILTER - and _SQL_NULL_KEYWORD in str(value.get(_POLYGLOT_ANALYSIS_EXPRESSION_SQL) or "").upper() - for value in column_uses - ): - return frozenset() - if parsed is None: - try: - parsed = polyglot_module.parse_one( - cleaned_sql, - dialect=dialect or "generic", - ) - except polyglot_module.PolyglotError: - return frozenset() - select: Any | None = parsed - if str(getattr(select, "kind", "")) != _POLYGLOT_KIND_SELECT: - select = parsed.find(_POLYGLOT_KIND_SELECT) - if select is None or str(getattr(select, "kind", "")) != _POLYGLOT_KIND_SELECT: - return frozenset() - outputs: set[str] = set() - context: NonNullFilterContext | None = _polyglot_non_null_filter_context( - select=select, - column_nullability_by_table=column_nullability_by_table, - ) - for raw_projection in getattr(select, "expressions", ()): - projection: Any = _unwrap_polyglot_annotations(raw_projection) - output_name: str = str(getattr(projection, "output_name", "") or "") - if not output_name or output_name == SQL_WILDCARD_TOKEN: - continue - expression: Any = ( - projection.this - if str(getattr(projection, "kind", "")) == _POLYGLOT_KIND_ALIAS - else projection - ) - if _polyglot_expression_is_non_null_after_filter( - expression=expression, - context=context, - ): - outputs.add(output_name) - return frozenset(outputs) - - -def _polyglot_expression_is_non_null_after_filter( - *, - expression: Any, - context: NonNullFilterContext | None, -) -> bool: - if context is None: - return False - expression_reference: tuple[str, str] | None = _polyglot_direct_column_reference(expression) - if expression_reference is None: - return False - resolved_expression: tuple[str, str] | None = _polyglot_resolved_relation_column( - reference=expression_reference, - relations=context.relations, - ) - return resolved_expression is not None and resolved_expression in context.columns - - -def _polyglot_non_null_filter_context( - *, - select: Any, - column_nullability_by_table: dict[str, dict[str, InferredNullability]], -) -> NonNullFilterContext | None: - where_payload: object = select.arg(_POLYGLOT_PAYLOAD_WHERE_CLAUSE) - if not isinstance(where_payload, dict): - return None - predicate: object = cast(dict[str, object], where_payload).get(_POLYGLOT_PAYLOAD_THIS) - non_null_references: tuple[tuple[str, str], ...] = _polyglot_non_null_conjuncts(predicate) - if not non_null_references: - return None - relations: list[tuple[str, dict[str, InferredNullability]]] = [] - for table in _polyglot_direct_select_tables(select): - table_name: str = str(getattr(table, "name", "") or "") - alias: str = str(getattr(table, "alias_or_name", "") or "") - columns: dict[str, InferredNullability] | None = _case_insensitive_mapping_get( - mapping=column_nullability_by_table, - key=table_name, - ) - if columns is not None: - relations.append((alias or table_name, columns)) - relation_tuple: tuple[tuple[str, dict[str, InferredNullability]], ...] = tuple(relations) - columns: frozenset[tuple[str, str]] = frozenset( - resolved - for reference in non_null_references - if ( - resolved := _polyglot_resolved_relation_column( - reference=reference, - relations=relation_tuple, - ) - ) - ) - return NonNullFilterContext(relations=relation_tuple, columns=columns) if columns else None - - -def _polyglot_direct_column_reference(expression: Any) -> tuple[str, str] | None: - expression = _unwrap_polyglot_annotations(expression) - if str(getattr(expression, "kind", "")) == _POLYGLOT_KIND_CAST: - expression = _unwrap_polyglot_annotations(getattr(expression, "this", None)) - if str(getattr(expression, "kind", "")) != _POLYGLOT_KIND_COLUMN: - return None - column_name: str = str(getattr(expression, "name", "") or "") - if not column_name: - return None - expression_args: object = getattr(expression, "args", None) - table_name: str = "" - if isinstance(expression_args, dict): - table_name = _polyglot_name_payload_value( - cast(dict[str, object], expression_args).get(_POLYGLOT_PAYLOAD_TABLE) - ) - return table_name, column_name - - -def _polyglot_resolved_relation_column( - *, - reference: tuple[str, str], - relations: tuple[tuple[str, dict[str, InferredNullability]], ...], -) -> tuple[str, str] | None: - table_name, column_name = reference - matching: list[tuple[str, str]] = [] - for alias, columns in relations: - if table_name and alias.casefold() != table_name.casefold(): - continue - column_key: str | None = _case_insensitive_mapping_key( - mapping=columns, - key=column_name, - ) - if column_key is not None: - matching.append((alias.casefold(), column_key.casefold())) - return matching[0] if len(matching) == 1 else None - - -def _polyglot_non_null_conjuncts(payload: object) -> tuple[tuple[str, str], ...]: - if not isinstance(payload, dict): - return () - payload_dict: dict[str, object] = cast(dict[str, object], payload) - paren_payload: object = payload_dict.get(_POLYGLOT_KIND_PAREN) - if isinstance(paren_payload, dict): - paren_payload_dict: dict[str, object] = cast(dict[str, object], paren_payload) - return _polyglot_non_null_conjuncts(paren_payload_dict.get(_POLYGLOT_PAYLOAD_THIS)) - and_payload: object = payload_dict.get(_POLYGLOT_KIND_AND) - if isinstance(and_payload, dict): - and_payload_dict: dict[str, object] = cast(dict[str, object], and_payload) - return ( - *_polyglot_non_null_conjuncts(and_payload_dict.get(_POLYGLOT_PAYLOAD_LEFT)), - *_polyglot_non_null_conjuncts(and_payload_dict.get(_POLYGLOT_PAYLOAD_RIGHT)), - ) - is_null_payload: object = payload_dict.get(_POLYGLOT_KIND_IS_NULL) - is_null_payload_dict: dict[str, object] = ( - cast(dict[str, object], is_null_payload) if isinstance(is_null_payload, dict) else {} - ) - if not is_null_payload_dict or is_null_payload_dict.get(_POLYGLOT_PAYLOAD_NOT) is not True: - return () - expression_payload: object = is_null_payload_dict.get(_POLYGLOT_PAYLOAD_THIS) - if not isinstance(expression_payload, dict): - return () - expression_payload_dict: dict[str, object] = cast(dict[str, object], expression_payload) - column_payload: object = expression_payload_dict.get(_POLYGLOT_PAYLOAD_COLUMN) - if not isinstance(column_payload, dict): - return () - column_payload_dict: dict[str, object] = cast(dict[str, object], column_payload) - column_name: str = _polyglot_name_payload_value(column_payload_dict.get(_POLYGLOT_PAYLOAD_NAME)) - table_name: str = _polyglot_name_payload_value(column_payload_dict.get(_POLYGLOT_PAYLOAD_TABLE)) - return ((table_name, column_name),) if column_name else () - - -def _polyglot_star_output_types( - *, projection: Any, types_by_alias: dict[str, dict[str, str]] -) -> dict[str, str]: - if getattr(projection, "args", {}).get("rename"): - return {} - table_payload: object = getattr(projection, "args", {}).get("table") - table_name: str = _polyglot_name_payload_value(table_payload) - source_types: list[dict[str, str]] = [] - if table_name: - column_types: dict[str, str] | None = _case_insensitive_mapping_get( - mapping=types_by_alias, - key=table_name, - ) - if column_types is not None: - source_types.append(column_types) - else: - seen_relations: set[int] = set() - for column_types in types_by_alias.values(): - if id(column_types) in seen_relations: - continue - seen_relations.add(id(column_types)) - source_types.append(column_types) - excluded_names: frozenset[str] = frozenset( - name.casefold() - for value in (getattr(projection, "args", {}).get("except") or ()) - if (name := _polyglot_name_payload_value(value)) - ) - replaced_names: frozenset[str] = frozenset( - name.casefold() - for value in (getattr(projection, "args", {}).get("replace") or ()) - if isinstance(value, dict) - and (name := _polyglot_name_payload_value(cast(dict[str, object], value).get("alias"))) - ) - inferred: dict[str, str] = {} - ambiguous_names: set[str] = set() - for column_types in source_types: - for column_name, column_type in column_types.items(): - normalized_name: str = column_name.casefold() - if normalized_name in excluded_names or normalized_name in replaced_names: - continue - existing_name: str | None = next( - (name for name in inferred if name.casefold() == normalized_name), - None, - ) - if existing_name is not None: - ambiguous_names.add(existing_name) - continue - inferred[column_name] = column_type - for ambiguous_name in ambiguous_names: - inferred.pop(ambiguous_name, None) - return inferred - - -def _polyglot_top_level_ctes(root: Any) -> tuple[tuple[str, Any, bool], ...]: - targeted_ctes: object = getattr(root, "with_ctes", None) - if callable(targeted_ctes): - values: object = targeted_ctes() - if isinstance(values, list): - return tuple( - (str(name), body, bool(has_column_alias)) for name, has_column_alias, body in values - ) - with_payload: object = root.arg("with") - raw_ctes: object = ( - cast(dict[str, object], with_payload).get("ctes") - if isinstance(with_payload, dict) - else None - ) - if not isinstance(raw_ctes, list): - return () - children: tuple[Any, ...] = tuple(root.children()) - if len(children) < len(raw_ctes): - return () - cte_bodies: tuple[Any, ...] = children[-len(raw_ctes) :] - ctes: list[tuple[str, Any, bool]] = [] - for raw_cte, body in zip(raw_ctes, cte_bodies, strict=True): - if not isinstance(raw_cte, dict): - return () - cte_payload: dict[str, object] = cast(dict[str, object], raw_cte) - cte_name: str = _polyglot_name_payload_value(cte_payload.get("alias")) - if not cte_name: - return () - columns: object = cte_payload.get("columns") - ctes.append((cte_name, body, isinstance(columns, list) and bool(columns))) - return tuple(ctes) - - -def _polyglot_select_output_types( - *, - select: Any, - relation_types: dict[str, dict[str, str]], - inference_profile: ExpressionInferenceProfile, - expression_type_resolver: _ExpressionTypeResolver, -) -> dict[str, str]: - select = _unwrap_polyglot_annotations(select) - if _polyglot_top_level_ctes(select): - return _polyglot_cte_passthrough_types_from_parsed( - parsed=select, - column_types_by_table=relation_types, - inference_profile=inference_profile, - expression_type_resolver=expression_type_resolver, - ) - if str(getattr(select, "kind", "")) in _POLYGLOT_SET_OPERATION_KINDS: - return _polyglot_set_operation_output_types( - operation=select, - relation_types=relation_types, - inference_profile=inference_profile, - expression_type_resolver=expression_type_resolver, - ) - return _polyglot_direct_select_output_types( - select=select, - relation_types=relation_types, - inference_profile=inference_profile, - expression_type_resolver=expression_type_resolver, - ) - - -def _polyglot_set_operation_output_types( - *, - operation: Any, - relation_types: dict[str, dict[str, str]], - inference_profile: ExpressionInferenceProfile, - expression_type_resolver: _ExpressionTypeResolver, -) -> dict[str, str]: - if bool(operation.arg("by_name")): - branch_types: list[dict[str, str]] = [] - for side in ("left", "right"): - branch: Any = operation.arg(side) - if branch is None: - return {} - branch_types.append( - _polyglot_select_output_types( - select=branch, - relation_types=relation_types, - inference_profile=inference_profile, - expression_type_resolver=expression_type_resolver, - ) - ) - left_types, right_types = branch_types - return { - name: common_type - for name, left_type in left_types.items() - if ( - common_type := _polyglot_common_set_operation_type( - left=left_type, - right=_case_insensitive_mapping_get(mapping=right_types, key=name), - inference_profile=inference_profile, - ) - ) - is not None - } - branch_slots: list[tuple[tuple[str, str | None], ...]] = [] - for side in ("left", "right"): - branch: Any = operation.arg(side) - if branch is None: - return {} - inferred: tuple[tuple[str, str | None], ...] = _polyglot_select_output_type_slots( - select=branch, - relation_types=relation_types, - inference_profile=inference_profile, - expression_type_resolver=expression_type_resolver, - ) - if not inferred: - return {} - branch_slots.append(inferred) - left_slots, right_slots = branch_slots - if len(left_slots) != len(right_slots): - return {} - return { - left_name: common_type - for (left_name, left_type), (_, right_type) in zip( - left_slots, - right_slots, - strict=True, - ) - if ( - common_type := _polyglot_common_set_operation_type( - left=left_type, - right=right_type, - inference_profile=inference_profile, - ) - ) - is not None - } - - -def _polyglot_select_output_type_slots( - *, - select: Any, - relation_types: dict[str, dict[str, str]], - inference_profile: ExpressionInferenceProfile, - expression_type_resolver: _ExpressionTypeResolver, -) -> tuple[tuple[str, str | None], ...]: - select = _unwrap_polyglot_annotations(select) - if str(getattr(select, "kind", "")) in _POLYGLOT_SET_OPERATION_KINDS: - branch_slots: list[tuple[tuple[str, str | None], ...]] = [] - for side in ("left", "right"): - branch: Any = select.arg(side) - if branch is None: - return () - slots: tuple[tuple[str, str | None], ...] = _polyglot_select_output_type_slots( - select=branch, - relation_types=relation_types, - inference_profile=inference_profile, - expression_type_resolver=expression_type_resolver, - ) - if not slots: - return () - branch_slots.append(slots) - left_slots, right_slots = branch_slots - if bool(select.arg("by_name")): - right_types: dict[str, str | None] = dict(right_slots) - return tuple( - ( - name, - _polyglot_common_set_operation_type( - left=left_type, - right=_case_insensitive_mapping_get(mapping=right_types, key=name), - inference_profile=inference_profile, - ), - ) - for name, left_type in left_slots - ) - if len(left_slots) != len(right_slots): - return () - return tuple( - ( - left_name, - _polyglot_common_set_operation_type( - left=left_type, - right=right_type, - inference_profile=inference_profile, - ), - ) - for (left_name, left_type), (_, right_type) in zip( - left_slots, - right_slots, - strict=True, - ) - ) - if str(getattr(select, "kind", "")) != _POLYGLOT_KIND_SELECT: - return () - inferred: dict[str, str] = _polyglot_direct_select_output_types( - select=select, - relation_types=relation_types, - inference_profile=inference_profile, - expression_type_resolver=expression_type_resolver, - ) - slots: list[tuple[str, str | None]] = [] - for raw_projection in getattr(select, "expressions", ()): - projection: Any = _unwrap_polyglot_annotations(raw_projection) - if bool(getattr(projection, "is_star", False)): - return () - output_name: str = str(getattr(projection, "output_name", "") or "") - if not output_name or output_name == SQL_WILDCARD_TOKEN: - return () - inferred_type: str | None = _case_insensitive_mapping_get( - mapping=inferred, - key=output_name, - ) - if inferred_type is None: - expression: Any = ( - projection.this - if str(getattr(projection, "kind", "")) == _POLYGLOT_KIND_ALIAS - else projection - ) - if str(getattr(expression, "kind", "")) == _POLYGLOT_KIND_NULL: - inferred_type = _NULL_SET_OPERATION_TYPE - slots.append((output_name, inferred_type)) - return tuple(slots) - - -def _polyglot_common_set_operation_type( - *, - left: str | None, - right: str | None, - inference_profile: ExpressionInferenceProfile, -) -> str | None: - if left == _NULL_SET_OPERATION_TYPE and right == _NULL_SET_OPERATION_TYPE: - return None - if left == _NULL_SET_OPERATION_TYPE: - return right - if right == _NULL_SET_OPERATION_TYPE: - return left - if left is None or right is None: - return None - return ( - left - if _polyglot_types_equal( - left=left, - right=right, - inference_profile=inference_profile, - ) - else None - ) - - -def _polyglot_types_equal( - *, - left: str, - right: str, - inference_profile: ExpressionInferenceProfile, -) -> bool: - return left == right or types_equal( - left=left, - right=right, - dialect=inference_profile.sql_analysis_dialect, - ) - - -def _polyglot_direct_select_output_types( - *, - select: Any, - relation_types: dict[str, dict[str, str]], - inference_profile: ExpressionInferenceProfile, - expression_type_resolver: _ExpressionTypeResolver, -) -> dict[str, str]: - if str(getattr(select, "kind", "")) != _POLYGLOT_KIND_SELECT: - return {} - types_by_alias: dict[str, dict[str, str]] = {} - for table in _polyglot_direct_select_tables(select): - table_name: str = str(getattr(table, "name", "") or "") - column_types: dict[str, str] | None = _case_insensitive_mapping_get( - mapping=relation_types, - key=table_name, - ) - if column_types is None: - continue - types_by_alias[table_name] = column_types - alias_or_name: str = str(getattr(table, "alias_or_name", "") or "") - if alias_or_name: - types_by_alias[alias_or_name] = column_types - inferred: dict[str, str] = {} - projection: Any - for projection in getattr(select, "expressions", ()): - projection = _unwrap_polyglot_annotations(projection) - if bool(getattr(projection, "is_star", False)): - inferred.update( - _polyglot_star_output_types( - projection=projection, - types_by_alias=types_by_alias, - ) - ) - continue - output_name: str = str(getattr(projection, "output_name", "") or "") - if not output_name or output_name == SQL_WILDCARD_TOKEN: - continue - expression: Any = ( - projection.this - if str(getattr(projection, "kind", "")) == _POLYGLOT_KIND_ALIAS - else projection - ) - inferred_type: str | None = _polyglot_direct_expression_type( - expression=expression, - types_by_alias=types_by_alias, - inference_profile=inference_profile, - expression_type_resolver=expression_type_resolver, - ) - if inferred_type is not None: - inferred[output_name] = inferred_type - return inferred - - -def _polyglot_direct_expression_type( - *, - expression: Any, - types_by_alias: dict[str, dict[str, str]], - inference_profile: ExpressionInferenceProfile, - expression_type_resolver: _ExpressionTypeResolver, -) -> str | None: - expression = _unwrap_polyglot_annotations(expression) - kind: str = str(getattr(expression, "kind", "")) - inferred_type: str | None = expression_type_resolver( - expression=expression, - inference_profile=inference_profile, - ) - if inferred_type is not None: - return inferred_type - if kind == _POLYGLOT_KIND_COLUMN: - return _polyglot_direct_column_type( - expression=expression, - types_by_alias=types_by_alias, - ) - if kind in _POLYGLOT_BOOLEAN_RESULT_KINDS: - return "BOOLEAN" - if kind == _POLYGLOT_KIND_CONCAT: - operands: tuple[Any, ...] = tuple( - operand - for key in ("left", "right") - if (operand := getattr(expression, "args", {}).get(key)) is not None - ) - if len(operands) != _POLYGLOT_BINARY_OPERAND_COUNT: - return None - operand_types: list[str] = [] - for operand in operands: - if ( - str(getattr(operand, "kind", "")) == _POLYGLOT_KIND_LITERAL - and getattr(operand, "args", {}).get(_POLYGLOT_PAYLOAD_LITERAL_TYPE) - == _POLYGLOT_LITERAL_TYPE_STRING - ): - operand_types.append("TEXT") - continue - operand_type: str | None = _polyglot_direct_expression_type( - expression=operand, - types_by_alias=types_by_alias, - inference_profile=inference_profile, - expression_type_resolver=expression_type_resolver, - ) - if operand_type is None: - return None - operand_types.append(operand_type) - return ( - "TEXT" - if all( - normalize_type( - type_sql=operand_type, - dialect=inference_profile.sql_analysis_dialect, - ).family - == TypeFamily.STRING - for operand_type in operand_types - ) - else None - ) - if kind == _POLYGLOT_KIND_SUBSTRING: - inner: Any | None = getattr(expression, "args", {}).get("this") - return ( - _polyglot_direct_expression_type( - expression=inner, - types_by_alias=types_by_alias, - inference_profile=inference_profile, - expression_type_resolver=expression_type_resolver, - ) - if inner is not None - else None - ) - if kind in _POLYGLOT_TYPE_PASSTHROUGH_KINDS: - inner: Any | None = getattr(expression, "this", None) or getattr( - expression, "args", {} - ).get("this") - return ( - _polyglot_direct_expression_type( - expression=inner, - types_by_alias=types_by_alias, - inference_profile=inference_profile, - expression_type_resolver=expression_type_resolver, - ) - if inner is not None - else None - ) - result_expressions: tuple[Any, ...] = _polyglot_result_expressions(expression) - if result_expressions: - return _polyglot_common_result_type( - expressions=result_expressions, - types_by_alias=types_by_alias, - inference_profile=inference_profile, - expression_type_resolver=expression_type_resolver, - ) - return None - - -def _polyglot_result_expressions(expression: Any) -> tuple[Any, ...]: - kind: str = str(getattr(expression, "kind", "")) - args: dict[str, Any] = getattr(expression, "args", {}) - if kind == _POLYGLOT_KIND_COALESCE: - values: object = args.get("expressions") - return tuple(values) if isinstance(values, list) else () - if kind == _POLYGLOT_KIND_IF_FUNC: - return tuple( - value for key in ("true_value", "false_value") if (value := args.get(key)) is not None - ) - if kind == _POLYGLOT_KIND_CASE: - values: list[Any] = [] - whens: object = args.get("whens") - children: tuple[Any, ...] = tuple(expression.children()) - if isinstance(whens, list): - first_condition_index: int = 1 if args.get("operand") is not None else 0 - values.extend( - children[first_condition_index + (index * 2) + 1] for index in range(len(whens)) - ) - if args.get("else_") is not None and children: - values.append(children[-1]) - return tuple(values) - if ( - kind == _POLYGLOT_KIND_FUNCTION - and str(getattr(expression, "name", "")).upper() == _POLYGLOT_NULLIF_FUNCTION_NAME - ): - values = args.get("args") - return (values[0],) if isinstance(values, list) and values else () - return () - - -def _polyglot_common_result_type( - *, - expressions: tuple[Any, ...], - types_by_alias: dict[str, dict[str, str]], - inference_profile: ExpressionInferenceProfile, - expression_type_resolver: _ExpressionTypeResolver, -) -> str | None: - resolved_types: list[str] = [] - for raw_expression in expressions: - expression: Any = _unwrap_polyglot_annotations(raw_expression) - if str(getattr(expression, "kind", "")) == _POLYGLOT_KIND_NULL: - continue - resolved_type: str | None = _polyglot_direct_expression_type( - expression=expression, - types_by_alias=types_by_alias, - inference_profile=inference_profile, - expression_type_resolver=expression_type_resolver, - ) - if resolved_type is None: - return None - resolved_types.append(resolved_type) - if not resolved_types: - return None - first_type: str = resolved_types[0] - if all( - _polyglot_types_equal( - left=first_type, - right=other_type, - inference_profile=inference_profile, - ) - for other_type in resolved_types[1:] - ): - return first_type - return None - - -def _polyglot_direct_select_tables(select: Any) -> tuple[Any, ...]: - return tuple( - child - for child in select.children() - if str(getattr(child, "kind", "")) == _POLYGLOT_KIND_TABLE - ) - - -def _polyglot_direct_column_type( - *, expression: Any, types_by_alias: dict[str, dict[str, str]] -) -> str | None: - column_name: str = str(getattr(expression, "name", "") or "") - table_name: str = _polyglot_column_table_name(expression) - if table_name: - column_types: dict[str, str] | None = _case_insensitive_mapping_get( - mapping=types_by_alias, - key=table_name, - ) - return ( - _case_insensitive_mapping_get(mapping=column_types, key=column_name) - if column_types is not None - else None - ) - matching_types: list[str] = [] - seen_relations: set[int] = set() - for column_types in types_by_alias.values(): - if id(column_types) in seen_relations: - continue - seen_relations.add(id(column_types)) - inferred_type: str | None = _case_insensitive_mapping_get( - mapping=column_types, - key=column_name, - ) - if inferred_type is not None: - matching_types.append(inferred_type) - return matching_types[0] if len(matching_types) == 1 else None - - -def _case_insensitive_mapping_get[T](*, mapping: dict[str, T], key: str) -> T | None: - direct: T | None = mapping.get(key) - if direct is not None: - return direct - normalized_key: str = key.casefold() - matches: list[T] = [ - value for candidate, value in mapping.items() if candidate.casefold() == normalized_key - ] - return matches[0] if len(matches) == 1 else None - - -def _case_insensitive_mapping_key[T](*, mapping: dict[str, T], key: str) -> str | None: - if key in mapping: - return key - normalized_key: str = key.casefold() - matches: list[str] = [ - candidate for candidate in mapping if candidate.casefold() == normalized_key - ] - return matches[0] if len(matches) == 1 else None - - -def _has_known_nullability( - column_nullability_by_table: dict[str, dict[str, InferredNullability]], -) -> bool: - for column_facts in column_nullability_by_table.values(): - if any(value != InferredNullability.UNKNOWN for value in column_facts.values()): - return True - return False - - -def _unwrap_polyglot_annotations(expression: Any) -> Any: - while str(getattr(expression, "kind", "")) == _POLYGLOT_KIND_ANNOTATED: - expression = expression.this - return expression - - -def _polyglot_column_table_name(column: Any) -> str: - payload: object = column.to_dict().get(_POLYGLOT_PAYLOAD_COLUMN, {}) - if not isinstance(payload, dict): - return "" - table_payload: object = payload.get(_POLYGLOT_PAYLOAD_TABLE) - if not isinstance(table_payload, dict): - return "" - return _polyglot_name_payload_value(table_payload) - - -def _polyglot_name_payload_value(payload: object) -> str: - if isinstance(payload, str): - return payload - if not isinstance(payload, dict): - return "" - name: object = cast(dict[str, object], payload).get(_POLYGLOT_PAYLOAD_NAME) - return name if isinstance(name, str) else "" diff --git a/src/sqlbuild/compiler/compile/_helpers/analysis/cte_scopes.py b/src/sqlbuild/compiler/compile/_helpers/analysis/cte_scopes.py new file mode 100644 index 0000000000..40f141cb09 --- /dev/null +++ b/src/sqlbuild/compiler/compile/_helpers/analysis/cte_scopes.py @@ -0,0 +1,67 @@ +"""Top-level CTEs and direct tables of Polyglot wheel trees, for resolved column reads.""" + +from __future__ import annotations + +from typing import Any, cast + +from sqlbuild.compiler.sql_analysis.constants import ( + POLYGLOT_KIND_ANNOTATED as _POLYGLOT_KIND_ANNOTATED, +) +from sqlbuild.compiler.sql_analysis.constants import POLYGLOT_KIND_TABLE as _POLYGLOT_KIND_TABLE +from sqlbuild.compiler.sql_analysis.constants import POLYGLOT_PAYLOAD_NAME as _POLYGLOT_PAYLOAD_NAME + + +def _polyglot_top_level_ctes(root: Any) -> tuple[tuple[str, Any, bool], ...]: + targeted_ctes: object = getattr(root, "with_ctes", None) + if callable(targeted_ctes): + values: object = targeted_ctes() + if isinstance(values, list): + return tuple( + (str(name), body, bool(has_column_alias)) for name, has_column_alias, body in values + ) + with_payload: object = root.arg("with") + raw_ctes: object = ( + cast(dict[str, object], with_payload).get("ctes") + if isinstance(with_payload, dict) + else None + ) + if not isinstance(raw_ctes, list): + return () + children: tuple[Any, ...] = tuple(root.children()) + if len(children) < len(raw_ctes): + return () + cte_bodies: tuple[Any, ...] = children[-len(raw_ctes) :] + ctes: list[tuple[str, Any, bool]] = [] + for raw_cte, body in zip(raw_ctes, cte_bodies, strict=True): + if not isinstance(raw_cte, dict): + return () + cte_payload: dict[str, object] = cast(dict[str, object], raw_cte) + cte_name: str = _polyglot_name_payload_value(cte_payload.get("alias")) + if not cte_name: + return () + columns: object = cte_payload.get("columns") + ctes.append((cte_name, body, isinstance(columns, list) and bool(columns))) + return tuple(ctes) + + +def _polyglot_direct_select_tables(select: Any) -> tuple[Any, ...]: + return tuple( + child + for child in select.children() + if str(getattr(child, "kind", "")) == _POLYGLOT_KIND_TABLE + ) + + +def _unwrap_polyglot_annotations(expression: Any) -> Any: + while str(getattr(expression, "kind", "")) == _POLYGLOT_KIND_ANNOTATED: + expression = expression.this + return expression + + +def _polyglot_name_payload_value(payload: object) -> str: + if isinstance(payload, str): + return payload + if not isinstance(payload, dict): + return "" + name: object = cast(dict[str, object], payload).get(_POLYGLOT_PAYLOAD_NAME) + return name if isinstance(name, str) else "" diff --git a/src/sqlbuild/compiler/compile/_helpers/analysis/dynamic_pivot.py b/src/sqlbuild/compiler/compile/_helpers/analysis/dynamic_pivot.py deleted file mode 100644 index 5089e2b14d..0000000000 --- a/src/sqlbuild/compiler/compile/_helpers/analysis/dynamic_pivot.py +++ /dev/null @@ -1,728 +0,0 @@ -"""Compiler proof for closed contracts over runtime-dynamic pivot columns.""" - -from __future__ import annotations - -from dataclasses import dataclass -from typing import Any, cast - -from sqlbuild.compiler.compile.models import ( - DynamicColumnContractProof, - DynamicColumnFamilyProof, - InferredColumn, -) -from sqlbuild.compiler.lineage.types import InferredNullability -from sqlbuild.compiler.sql_analysis.main.import_polyglot_sql import import_polyglot_sql -from sqlbuild.spec.contracts.models import SchemaDynamicColumnFamily - -_DUCKDB_DIALECT: str = "duckdb" -_MOTHERDUCK_DIALECT: str = "motherduck" -_SNOWFLAKE_DIALECT: str = "snowflake" -_PIVOT_AST_KIND: str = "pivot" -_SELECT_AST_KIND: str = "select" -_QUERY_AST_KINDS: frozenset[str] = frozenset({"query", "subquery"}) -_CAST_AST_KIND: str = "cast" -_COLUMN_AST_KIND: str = "column" -_TABLE_AST_KIND: str = "table" -_FUNCTION_AST_KIND: str = "function" -_ALIAS_AST_KIND: str = "alias" -_CTE_AST_KIND: str = "cte" -_STAR_AST_KIND: str = "star" -_DYNAMIC_VALUE_SOURCE_KINDS: frozenset[str] = frozenset({"pivot_any", _SELECT_AST_KIND, "query"}) -_DEPENDENCY_FUNCTION_NAMES: frozenset[str] = frozenset({"__ref", "__source", "__seed"}) -_UNKNOWN_DATA_TYPE: str = "UNKNOWN" -_SIMPLIFIED_PIVOT_DIALECTS: frozenset[str] = frozenset({_DUCKDB_DIALECT, _MOTHERDUCK_DIALECT}) -_SUPPORTED_DIALECTS: frozenset[str] = frozenset({*_SIMPLIFIED_PIVOT_DIALECTS, _SNOWFLAKE_DIALECT}) -_TYPE_PRESERVING_AGGREGATES: frozenset[str] = frozenset({"ANY_VALUE", "MAX", "MIN"}) -type _CteMap = dict[str, dict[str, object] | None] - - -@dataclass(frozen=True) -class _ColumnFact: - name: str - type: str | None - nullability: InferredNullability = InferredNullability.UNKNOWN - - -@dataclass(frozen=True) -class _Boundary: - pivot: dict[str, object] | None = None - passthrough_name: str | None = None - - -def analyze_dynamic_column_contract( - *, - query_sql: str, - dialect: str | None, - families: tuple[SchemaDynamicColumnFamily, ...], - column_types_by_table: dict[str, dict[str, str]], - authoritative_column_types_by_table: dict[str, dict[str, str]], - column_nullability_by_table: dict[str, dict[str, InferredNullability]], - dynamic_families_by_table: dict[str, tuple[SchemaDynamicColumnFamily, ...]], -) -> DynamicColumnContractProof | None: - """Prove that a model output is closed over fixed columns and declared pivot families.""" - - if not families: - return None - normalized_dialect: str = (dialect or "").casefold() - if normalized_dialect not in _SUPPORTED_DIALECTS: - return _failure( - f"adapter dialect '{dialect or 'generic'}' does not support compiler-proven " - "dynamic pivots" - ) - parse_dialect: str = ( - _DUCKDB_DIALECT if normalized_dialect == _MOTHERDUCK_DIALECT else normalized_dialect - ) - polyglot: Any = import_polyglot_sql() - try: - parsed: Any = polyglot.parse_one(query_sql, dialect=parse_dialect) - except polyglot.PolyglotError as error: - return _failure(f"dynamic pivot SQL could not be parsed: {error}") - root: object = parsed.to_dict() - if not isinstance(root, dict): - return _failure("dynamic pivot SQL did not produce a structured query") - ctes: _CteMap = _collect_ctes(root) - boundary: _Boundary | None = _resolve_boundary(node=root, ctes=ctes, seen=frozenset()) - if boundary is None: - return _failure( - "output must be a wildcard projection from one supported dynamic pivot or a proven " - "dynamic-family passthrough" - ) - if boundary.passthrough_name is not None: - return _analyze_passthrough( - name=boundary.passthrough_name, - families=families, - column_types_by_table=column_types_by_table, - column_nullability_by_table=column_nullability_by_table, - dynamic_families_by_table=dynamic_families_by_table, - ) - if boundary.pivot is None: - return _failure("dynamic output boundary did not resolve to a pivot") - return _analyze_pivot( - pivot=boundary.pivot, - dialect=normalized_dialect, - families=families, - ctes=ctes, - column_types_by_table=authoritative_column_types_by_table, - column_nullability_by_table=column_nullability_by_table, - bare_dynamic_pivot=_node_key(root) == _PIVOT_AST_KIND, - ) - - -def _analyze_passthrough( - *, - name: str, - families: tuple[SchemaDynamicColumnFamily, ...], - column_types_by_table: dict[str, dict[str, str]], - column_nullability_by_table: dict[str, dict[str, InferredNullability]], - dynamic_families_by_table: dict[str, tuple[SchemaDynamicColumnFamily, ...]], -) -> DynamicColumnContractProof: - upstream_families: tuple[SchemaDynamicColumnFamily, ...] | None = _casefold_lookup( - mapping=dynamic_families_by_table, key=name - ) - if upstream_families is None or not _families_equal(left=families, right=upstream_families): - return _failure( - f"dynamic-family passthrough from '{name}' must redeclare the upstream families exactly" - ) - source_columns: tuple[_ColumnFact, ...] | None = _external_schema( - name=name, - column_types_by_table=column_types_by_table, - column_nullability_by_table=column_nullability_by_table, - ) - if source_columns is None: - return _failure(f"dynamic-family passthrough source '{name}' has no authoritative schema") - return DynamicColumnContractProof( - output_proven=True, - fixed_columns=tuple( - InferredColumn(name=column.name, type=column.type, nullability=column.nullability) - for column in source_columns - ), - families=tuple( - DynamicColumnFamilyProof(name=family.name, inferred_type=family.type) - for family in families - ), - input_relations=(name,), - ) - - -def _analyze_pivot( - *, - pivot: dict[str, object], - dialect: str, - families: tuple[SchemaDynamicColumnFamily, ...], - ctes: _CteMap, - column_types_by_table: dict[str, dict[str, str]], - column_nullability_by_table: dict[str, dict[str, InferredNullability]], - bare_dynamic_pivot: bool, -) -> DynamicColumnContractProof: - if bool(pivot.get("unpivot")): - return _failure("UNPIVOT does not produce a dynamic column family") - pivot_columns, aggregates, dynamic, pivot_columns_valid = _pivot_components( - pivot=pivot, dialect=dialect - ) - if not dynamic: - return _failure("static pivot values must use ordinary exact column declarations") - if len(pivot_columns) != 1: - return _failure("dynamic column contracts currently require exactly one pivot column") - if not pivot_columns_valid: - return _failure("dynamic pivot columns must be direct column references") - source_node: object = pivot.get("this") - source_columns: tuple[_ColumnFact, ...] | None = _relation_schema( - node=source_node, - ctes=ctes, - column_types_by_table=column_types_by_table, - column_nullability_by_table=column_nullability_by_table, - seen=frozenset(), - ) - if source_columns is None: - return _failure("dynamic pivot input does not have an authoritative, explicit schema") - input_relation: str | None = _external_relation_name( - node=source_node, - ctes=ctes, - seen=frozenset(), - ) - if input_relation is None: - return _failure("dynamic pivot input relation could not be resolved") - pivot_column: str = pivot_columns[0] - matched_aggregate_indices: set[int] = set() - family_proofs: list[DynamicColumnFamilyProof] = [] - for family in families: - if not family.pivot_column.casefold() == pivot_column.casefold(): - return _failure( - f"dynamic family '{family.name}' declares pivot_column '{family.pivot_column}' " - f"but the output pivot uses '{pivot_column}'" - ) - matches: list[tuple[int, str | None]] = [] - for index, aggregate in enumerate(aggregates): - aggregate_name, value_name, inferred_type = _aggregate_fact( - aggregate=aggregate, source_columns=source_columns - ) - if ( - aggregate_name.casefold() == family.aggregate.casefold() - and value_name is not None - and value_name.casefold() == family.value_column.casefold() - ): - matches.append((index, inferred_type)) - if len(matches) != 1: - return _failure( - f"dynamic family '{family.name}' must match exactly one " - f"{family.aggregate}({family.value_column}) pivot aggregate" - ) - aggregate_index, inferred_type = matches[0] - if aggregate_index in matched_aggregate_indices: - return _failure("one pivot aggregate cannot satisfy multiple dynamic families") - matched_aggregate_indices.add(aggregate_index) - family_proofs.append( - DynamicColumnFamilyProof(name=family.name, inferred_type=inferred_type) - ) - if len(matched_aggregate_indices) != len(aggregates): - return _failure("every dynamic pivot aggregate must have one declared column family") - fixed_names: tuple[str, ...] - if dialect in _SIMPLIFIED_PIVOT_DIALECTS and isinstance(pivot.get("group"), dict): - fixed_names = tuple( - name - for expression in _nested_list(node=pivot.get("group"), keys=("group", "expressions")) - if (name := _column_name(expression)) is not None - ) - else: - excluded: frozenset[str] = frozenset( - {pivot_column.casefold(), *(family.value_column.casefold() for family in families)} - ) - fixed_names = tuple( - column.name for column in source_columns if column.name.casefold() not in excluded - ) - source_by_name: dict[str, _ColumnFact] = { - column.name.casefold(): column for column in source_columns - } - if any(name.casefold() not in source_by_name for name in fixed_names): - return _failure("dynamic pivot grouping columns are not present in the pivot input") - return DynamicColumnContractProof( - output_proven=True, - fixed_columns=tuple( - InferredColumn( - name=name, - type=source_by_name[name.casefold()].type, - nullability=source_by_name[name.casefold()].nullability, - ) - for name in fixed_names - ), - families=tuple(family_proofs), - input_relations=(input_relation,), - bare_dynamic_pivot=bare_dynamic_pivot, - ) - - -def _pivot_components( - *, pivot: dict[str, object], dialect: str -) -> tuple[tuple[str, ...], tuple[dict[str, object], ...], bool, bool]: - if dialect in _SIMPLIFIED_PIVOT_DIALECTS and pivot.get("using"): - pivot_expressions: tuple[dict[str, object], ...] = _dict_list(pivot.get("expressions")) - pivot_columns: tuple[str, ...] = tuple( - name - for expression in pivot_expressions - if (name := _column_name(expression)) is not None - ) - return ( - pivot_columns, - _dict_list(pivot.get("using")), - not bool(pivot.get("fields")), - len(pivot_columns) == len(pivot_expressions), - ) - fields: tuple[dict[str, object], ...] = _dict_list(pivot.get("fields")) - pivot_columns = tuple( - name - for field in fields - if (name := _column_name(_nested(node=field, keys=("in", "this")))) is not None - ) - dynamic: bool = _has_dynamic_value_source(fields=fields) - return ( - pivot_columns, - _dict_list(pivot.get("expressions")), - dynamic, - len(pivot_columns) == len(fields), - ) - - -def _has_dynamic_value_source(*, fields: tuple[dict[str, object], ...]) -> bool: - for field in fields: - values: tuple[dict[str, object], ...] = _nested_list(node=field, keys=("in", "expressions")) - if any(_node_key(value) in _DYNAMIC_VALUE_SOURCE_KINDS for value in values): - return True - return False - - -def _aggregate_fact( - *, aggregate: dict[str, object], source_columns: tuple[_ColumnFact, ...] -) -> tuple[str, str | None, str | None]: - aggregate_name: str = _node_key(aggregate).upper() - payload: object = aggregate.get(_node_key(aggregate)) - if not isinstance(payload, dict): - return aggregate_name, None, None - payload_dict: dict[str, object] = cast(dict[str, object], payload) - authored_name: object = payload_dict.get("name") - if isinstance(authored_name, str) and authored_name: - aggregate_name = authored_name.upper() - value: object = payload_dict.get("this") - value_name: str | None = _column_name(value) - inferred_type: str | None = None - if _node_key(value) == _CAST_AST_KIND: - cast_payload: object = ( - cast(dict[str, object], value).get("cast") if isinstance(value, dict) else None - ) - if isinstance(cast_payload, dict): - cast_payload_dict: dict[str, object] = cast(dict[str, object], cast_payload) - value_name = _column_name(cast_payload_dict.get("this")) - if aggregate_name in _TYPE_PRESERVING_AGGREGATES: - inferred_type = _render_type(cast_payload_dict.get("to")) - if inferred_type is None and aggregate_name in _TYPE_PRESERVING_AGGREGATES: - source_by_name: dict[str, _ColumnFact] = { - column.name.casefold(): column for column in source_columns - } - source: _ColumnFact | None = ( - source_by_name.get(value_name.casefold()) if value_name is not None else None - ) - inferred_type = source.type if source is not None else None - return aggregate_name, value_name, inferred_type - - -def _resolve_boundary(*, node: object, ctes: _CteMap, seen: frozenset[str]) -> _Boundary | None: - key: str = _node_key(node) - payload: object = cast(dict[str, object], node).get(key) if isinstance(node, dict) else None - if key == _PIVOT_AST_KIND and isinstance(payload, dict): - return _Boundary(pivot=cast(dict[str, object], payload)) - if key in _QUERY_AST_KINDS and isinstance(payload, dict): - return _resolve_boundary( - node=cast(dict[str, object], payload).get("this"), ctes=ctes, seen=seen - ) - if key != _SELECT_AST_KIND or not isinstance(payload, dict): - return None - payload_dict: dict[str, object] = cast(dict[str, object], payload) - if payload_dict.get("joins") or not _is_single_wildcard(payload_dict.get("expressions")): - return None - relations: tuple[dict[str, object], ...] = _nested_dict_list( - node=payload_dict.get("from"), key="expressions" - ) - if len(relations) != 1: - return None - relation: dict[str, object] = relations[0] - if _node_key(relation) == _PIVOT_AST_KIND: - pivot_payload: object = relation.get("pivot") - return ( - _Boundary(pivot=cast(dict[str, object], pivot_payload)) - if isinstance(pivot_payload, dict) - else None - ) - relation_name: str | None = _relation_name(relation) - if relation_name is None: - return None - normalized_name: str = relation_name.casefold() - if normalized_name in ctes: - cte: dict[str, object] | None = ctes[normalized_name] - if cte is None: - return None - if relation_name.casefold() in seen: - return None - resolved: _Boundary | None = _resolve_boundary( - node=cte, - ctes=ctes, - seen=seen | {relation_name.casefold()}, - ) - if resolved is None: - return None - return resolved - return _Boundary(passthrough_name=relation_name) - - -def _relation_schema( - *, - node: object, - ctes: _CteMap, - column_types_by_table: dict[str, dict[str, str]], - column_nullability_by_table: dict[str, dict[str, InferredNullability]], - seen: frozenset[str], -) -> tuple[_ColumnFact, ...] | None: - relation_name: str | None = _relation_name(node) - if relation_name is None: - return None - normalized_name: str = relation_name.casefold() - if normalized_name not in ctes: - return _external_schema( - name=relation_name, - column_types_by_table=column_types_by_table, - column_nullability_by_table=column_nullability_by_table, - ) - cte: dict[str, object] | None = ctes[normalized_name] - if cte is None or normalized_name in seen: - return None - return _select_schema( - node=cte, - ctes=ctes, - column_types_by_table=column_types_by_table, - column_nullability_by_table=column_nullability_by_table, - seen=seen | {normalized_name}, - ) - - -def _external_relation_name( - *, - node: object, - ctes: _CteMap, - seen: frozenset[str], -) -> str | None: - key: str = _node_key(node) - payload: object = cast(dict[str, object], node).get(key) if isinstance(node, dict) else None - if key in _QUERY_AST_KINDS and isinstance(payload, dict): - return _external_relation_name( - node=cast(dict[str, object], payload).get("this"), - ctes=ctes, - seen=seen, - ) - if key == _SELECT_AST_KIND and isinstance(payload, dict): - payload_dict: dict[str, object] = cast(dict[str, object], payload) - if payload_dict.get("joins"): - return None - relations: tuple[dict[str, object], ...] = _nested_dict_list( - node=payload_dict.get("from"), key="expressions" - ) - if len(relations) != 1: - return None - return _external_relation_name(node=relations[0], ctes=ctes, seen=seen) - relation_name: str | None = _relation_name(node) - if relation_name is None: - return None - normalized_name: str = relation_name.casefold() - if normalized_name not in ctes: - return relation_name - cte: dict[str, object] | None = ctes[normalized_name] - if cte is None or normalized_name in seen: - return None - return _external_relation_name( - node=cte, - ctes=ctes, - seen=seen | {normalized_name}, - ) - - -def _select_schema( - *, - node: object, - ctes: _CteMap, - column_types_by_table: dict[str, dict[str, str]], - column_nullability_by_table: dict[str, dict[str, InferredNullability]], - seen: frozenset[str], -) -> tuple[_ColumnFact, ...] | None: - key: str = _node_key(node) - payload: object = cast(dict[str, object], node).get(key) if isinstance(node, dict) else None - if key in _QUERY_AST_KINDS and isinstance(payload, dict): - return _select_schema( - node=cast(dict[str, object], payload).get("this"), - ctes=ctes, - column_types_by_table=column_types_by_table, - column_nullability_by_table=column_nullability_by_table, - seen=seen, - ) - if key != _SELECT_AST_KIND or not isinstance(payload, dict): - return None - payload_dict: dict[str, object] = cast(dict[str, object], payload) - if payload_dict.get("joins"): - return None - relations: tuple[dict[str, object], ...] = _nested_dict_list( - node=payload_dict.get("from"), key="expressions" - ) - if len(relations) != 1: - return None - source: tuple[_ColumnFact, ...] | None = _relation_schema( - node=relations[0], - ctes=ctes, - column_types_by_table=column_types_by_table, - column_nullability_by_table=column_nullability_by_table, - seen=seen, - ) - if source is None: - return None - expressions: object = payload_dict.get("expressions") - if _is_single_wildcard(expressions): - return source - if not isinstance(expressions, list): - return None - source_by_name: dict[str, _ColumnFact] = {column.name.casefold(): column for column in source} - output: list[_ColumnFact] = [] - for raw_expression in expressions: - if not isinstance(raw_expression, dict): - return None - output_name, expression = _projection(cast(dict[str, object], raw_expression)) - source_name: str | None - expression_type: str | None = None - if _node_key(expression) == _CAST_AST_KIND: - cast_payload: object = expression.get("cast") - if not isinstance(cast_payload, dict): - return None - cast_payload_dict: dict[str, object] = cast(dict[str, object], cast_payload) - source_name = _column_name(cast_payload_dict.get("this")) - expression_type = _render_type(cast_payload_dict.get("to")) - else: - source_name = _column_name(expression) - if output_name is None or source_name is None: - return None - source_column: _ColumnFact | None = source_by_name.get(source_name.casefold()) - if source_column is None: - return None - if expression_type is None: - expression_type = source_column.type - output.append( - _ColumnFact( - name=output_name, - type=expression_type, - nullability=source_column.nullability, - ) - ) - return tuple(output) - - -def _external_schema( - *, - name: str, - column_types_by_table: dict[str, dict[str, str]], - column_nullability_by_table: dict[str, dict[str, InferredNullability]], -) -> tuple[_ColumnFact, ...] | None: - types: dict[str, str] | None = _casefold_lookup(mapping=column_types_by_table, key=name) - if types is None: - return None - nullability: dict[str, InferredNullability] = ( - _casefold_lookup(mapping=column_nullability_by_table, key=name) or {} - ) - nullability_by_name: dict[str, InferredNullability] = { - column_name.casefold(): value for column_name, value in nullability.items() - } - return tuple( - _ColumnFact( - name=column_name, - type=None if data_type == _UNKNOWN_DATA_TYPE else data_type, - nullability=nullability_by_name.get( - column_name.casefold(), InferredNullability.UNKNOWN - ), - ) - for column_name, data_type in types.items() - ) - - -def _collect_ctes(root: dict[str, object]) -> _CteMap: - key: str = _node_key(root) - payload: object = root.get(key) - if not isinstance(payload, dict): - return {} - payload_dict: dict[str, object] = cast(dict[str, object], payload) - with_payload: object = payload_dict.get("with") - if not isinstance(with_payload, dict): - return {} - with_payload_dict: dict[str, object] = cast(dict[str, object], with_payload) - ctes: _CteMap = {} - for cte in _dict_list(with_payload_dict.get("ctes")): - cte_payload: object = cte.get("cte") if _node_key(cte) == _CTE_AST_KIND else cte - if not isinstance(cte_payload, dict): - continue - cte_payload_dict: dict[str, object] = cast(dict[str, object], cte_payload) - name: str | None = _identifier_name(cte_payload_dict.get("alias")) - query: object = cte_payload_dict.get("this") - if name is None: - continue - if cte_payload_dict.get("columns"): - ctes[name.casefold()] = None - elif isinstance(query, dict): - ctes[name.casefold()] = cast(dict[str, object], query) - return ctes - - -def _projection(node: dict[str, object]) -> tuple[str | None, dict[str, object]]: - if _node_key(node) != _ALIAS_AST_KIND: - return _column_name(node), node - payload: object = node.get("alias") - if not isinstance(payload, dict): - return None, node - payload_dict: dict[str, object] = cast(dict[str, object], payload) - expression: object = payload_dict.get("this") - return ( - _identifier_name(payload_dict.get("alias")), - cast(dict[str, object], expression) if isinstance(expression, dict) else {}, - ) - - -def _relation_name(node: object) -> str | None: - key: str = _node_key(node) - payload: object = cast(dict[str, object], node).get(key) if isinstance(node, dict) else None - if not isinstance(payload, dict): - return None - payload_dict: dict[str, object] = cast(dict[str, object], payload) - if key == _TABLE_AST_KIND: - return _identifier_name(payload_dict.get("name")) - if key == _COLUMN_AST_KIND: - return _identifier_name(payload_dict.get("name")) - if ( - key == _FUNCTION_AST_KIND - and str(payload_dict.get("name", "")).casefold() in _DEPENDENCY_FUNCTION_NAMES - ): - arguments: tuple[dict[str, object], ...] = _dict_list(payload_dict.get("args")) - return _column_name(arguments[0]) if arguments else None - return None - - -def _column_name(node: object) -> str | None: - key: str = _node_key(node) - payload: object = cast(dict[str, object], node).get(key) if isinstance(node, dict) else None - if key == _COLUMN_AST_KIND and isinstance(payload, dict): - return _identifier_name(cast(dict[str, object], payload).get("name")) - return None - - -def _identifier_name(node: object) -> str | None: - if isinstance(node, str): - return node - if not isinstance(node, dict): - return None - value: object = cast(dict[str, object], node).get("name") - return value if isinstance(value, str) and value else None - - -def _render_type(node: object) -> str | None: - if not isinstance(node, dict): - return None - node_dict: dict[str, object] = cast(dict[str, object], node) - raw_type: object = node_dict.get("data_type") - if not isinstance(raw_type, str) or not raw_type: - return None - names: dict[str, str] = { - "big_int": "BIGINT", - "bool": "BOOLEAN", - "boolean": "BOOLEAN", - "decimal": "DECIMAL", - "double": "DOUBLE", - "float": "FLOAT", - "int": "INT", - "integer": "INT", - "text": "TEXT", - "timestamp": "TIMESTAMP", - "var_char": "VARCHAR", - "varchar": "VARCHAR", - } - rendered: str = names.get(raw_type.casefold(), raw_type.replace("_", " ").upper()) - precision: object = node_dict.get("precision") - scale: object = node_dict.get("scale") - length: object = node_dict.get("length") - if isinstance(length, int): - return f"{rendered}({length})" - if isinstance(precision, int): - return ( - f"{rendered}({precision}, {scale})" - if isinstance(scale, int) - else f"{rendered}({precision})" - ) - return rendered - - -def _families_equal( - *, - left: tuple[SchemaDynamicColumnFamily, ...], - right: tuple[SchemaDynamicColumnFamily, ...], -) -> bool: - def normalize(family: SchemaDynamicColumnFamily) -> tuple[str, str, str, str, str, str | None]: - return ( - family.name.casefold(), - family.pivot_column.casefold(), - family.value_column.casefold(), - family.aggregate.casefold(), - family.type.casefold(), - family.name_pattern, - ) - - return tuple(map(normalize, left)) == tuple(map(normalize, right)) - - -def _failure(reason: str) -> DynamicColumnContractProof: - return DynamicColumnContractProof(output_proven=False, failure_reason=reason) - - -def _node_key(node: object) -> str: - if not isinstance(node, dict) or len(node) != 1: - return "" - return str(next(iter(node))) - - -def _dict_list(value: object) -> tuple[dict[str, object], ...]: - if not isinstance(value, list): - return () - return tuple(cast(dict[str, object], item) for item in value if isinstance(item, dict)) - - -def _nested(*, node: object, keys: tuple[str, ...]) -> object: - current: object = node - for key in keys: - if not isinstance(current, dict): - return None - current = cast(dict[str, object], current).get(key) - return current - - -def _nested_list(*, node: object, keys: tuple[str, ...]) -> tuple[dict[str, object], ...]: - return _dict_list(_nested(node=node, keys=keys)) - - -def _nested_dict_list(*, node: object, key: str) -> tuple[dict[str, object], ...]: - return _dict_list(cast(dict[str, object], node).get(key) if isinstance(node, dict) else None) - - -def _is_single_wildcard(value: object) -> bool: - expressions: tuple[dict[str, object], ...] = _dict_list(value) - if len(expressions) != 1 or _node_key(expressions[0]) != _STAR_AST_KIND: - return False - payload: object = expressions[0].get("star") - if not isinstance(payload, dict): - return False - star: dict[str, object] = cast(dict[str, object], payload) - return not any(star.get(key) for key in ("except", "replace", "rename", "table")) - - -def _casefold_lookup[ValueT](*, mapping: dict[str, ValueT], key: str) -> ValueT | None: - requested: str = key.casefold() - for candidate, value in mapping.items(): - if candidate.casefold() == requested: - return value - return None diff --git a/src/sqlbuild/compiler/compile/_helpers/analysis/fixture_columns.py b/src/sqlbuild/compiler/compile/_helpers/analysis/fixture_columns.py index 77f1c6df1b..05b747a64d 100644 --- a/src/sqlbuild/compiler/compile/_helpers/analysis/fixture_columns.py +++ b/src/sqlbuild/compiler/compile/_helpers/analysis/fixture_columns.py @@ -2,25 +2,16 @@ from __future__ import annotations -from typing import Any, cast - +import sqlbuild._native as _native from sqlbuild.adapter.contract.models import ExpressionInferenceProfile -from sqlbuild.compiler.compile._helpers.analysis.compact import ( - analyze_columns_and_lineage_with_polyglot, -) -from sqlbuild.compiler.compile.constants import ( - POLYGLOT_ARRAY_KIND, - POLYGLOT_FUNCTION_KIND, - POLYGLOT_LITERAL_KIND, - POLYGLOT_STRUCTURED_KINDS, +from sqlbuild.compiler.analysis_session.main._infer_native_query_columns import ( + infer_native_query_columns, ) +from sqlbuild.compiler.analysis_session.models import NativeColumnQuery, NativeQueryColumns from sqlbuild.compiler.compile.models import ( FixtureColumnInference, InferredColumn, - PolyglotAnalysisResult, ) -from sqlbuild.compiler.sql_analysis.constants import POLYGLOT_KIND_NULL -from sqlbuild.compiler.sql_analysis.main.import_polyglot_sql import import_polyglot_sql def infer_fixture_column_facts( @@ -28,11 +19,11 @@ def infer_fixture_column_facts( ) -> FixtureColumnInference | None: """Infer fixture columns and identify explicitly untyped NULL projections.""" - analysis: PolyglotAnalysisResult = analyze_columns_and_lineage_with_polyglot( - query_sql=query_sql, - inference_profile=inference_profile, - ) - if not analysis.analysis_succeeded or analysis.has_star or analysis.columns is None: + analysis: NativeQueryColumns = infer_native_query_columns( + queries=(NativeColumnQuery(sql=query_sql, mode="legacy", recover_cte_facts=False),), + profile=inference_profile, + )[0] + if not analysis.succeeded or analysis.has_star or analysis.columns is None: return None simple_types, null_literal_names, quoted_names = _simple_projection_facts( query_sql=query_sql, @@ -55,97 +46,8 @@ def infer_fixture_column_facts( def _simple_projection_facts( *, query_sql: str, dialect: str | None ) -> tuple[dict[str, str], frozenset[str], frozenset[str]]: - polyglot_sql: Any = import_polyglot_sql() - try: - payload: dict[str, Any] = polyglot_sql.parse_one( - query_sql, dialect=dialect or "generic" - ).to_dict() - except polyglot_sql.PolyglotError: - return {}, frozenset(), frozenset() - direct_select_payload: object = payload.get("select") - select_payload: dict[str, Any] | None = _first_select(payload) - if select_payload is None: - return {}, frozenset(), frozenset() - types, null_literal_names, quoted_names = _collect_projection_facts( - select_payload=select_payload - ) - effective_null_literal_names: frozenset[str] = ( - null_literal_names if isinstance(direct_select_payload, dict) else frozenset() - ) - return types, effective_null_literal_names, quoted_names - - -def _collect_projection_facts( - *, select_payload: dict[str, Any] -) -> tuple[dict[str, str], frozenset[str], frozenset[str]]: - types: dict[str, str] = {} - null_literal_names: set[str] = set() - quoted_names: set[str] = set() - for expression in select_payload.get("expressions", []): - alias_payload: object = expression.get("alias") if isinstance(expression, dict) else None - if not isinstance(alias_payload, dict): - continue - alias: object = alias_payload.get("alias") - value: object = alias_payload.get("this") - if not isinstance(alias, dict) or not isinstance(value, dict): - continue - name: object = alias.get("name") - if not isinstance(name, str): - continue - if alias.get("quoted") is True: - quoted_names.add(name.casefold()) - raw_value_kind: object = next(iter(value), "") - if not isinstance(raw_value_kind, str): - continue - value_payload: object = value.get(raw_value_kind) - if raw_value_kind == POLYGLOT_KIND_NULL: - null_literal_names.add(name.casefold()) - continue - inferred_type: str | None = _simple_expression_type( - value_kind=raw_value_kind, - value_payload=value_payload, - ) - if inferred_type is not None: - types[name.casefold()] = inferred_type - return types, frozenset(null_literal_names), frozenset(quoted_names) - - -def _simple_expression_type(*, value_kind: str, value_payload: object) -> str | None: - if value_kind == POLYGLOT_LITERAL_KIND and isinstance(value_payload, dict): - value_dict: dict[object, object] = cast(dict[object, object], value_payload) - return { - "string": "VARCHAR", - "number": "NUMBER", - "boolean": "BOOLEAN", - }.get(str(value_dict.get("literal_type"))) - if value_kind == POLYGLOT_ARRAY_KIND: - return "ARRAY" - if value_kind in POLYGLOT_STRUCTURED_KINDS: - return "VARIANT" - if value_kind == POLYGLOT_FUNCTION_KIND and isinstance(value_payload, dict): - value_dict = cast(dict[object, object], value_payload) - function_name: str = str(value_dict.get("name") or "").upper() - return { - "ARRAY_CONSTRUCT": "ARRAY", - "OBJECT_CONSTRUCT": "OBJECT", - "PARSE_JSON": "VARIANT", - }.get(function_name) - return None - - -def _first_select(payload: object) -> dict[str, Any] | None: - if isinstance(payload, dict): - payload_dict: dict[object, object] = cast(dict[object, object], payload) - select_payload: object = payload_dict.get("select") - if isinstance(select_payload, dict): - return cast(dict[str, Any], select_payload) - for value in payload_dict.values(): - found: dict[str, Any] | None = _first_select(value) - if found is not None: - return found - if isinstance(payload, list): - for value in payload: - found = _first_select(value) - if found is not None: - return found - return None + types: list[tuple[str, str]] + null_literal_names: list[str] + quoted_names: list[str] + types, null_literal_names, quoted_names = _native.fixture_projection_facts(query_sql, dialect) + return dict(types), frozenset(null_literal_names), frozenset(quoted_names) diff --git a/src/sqlbuild/compiler/compile/_helpers/analysis/pivot_requests.py b/src/sqlbuild/compiler/compile/_helpers/analysis/pivot_requests.py index 9ed2ea2cad..33861ab3aa 100644 --- a/src/sqlbuild/compiler/compile/_helpers/analysis/pivot_requests.py +++ b/src/sqlbuild/compiler/compile/_helpers/analysis/pivot_requests.py @@ -4,7 +4,9 @@ from collections.abc import Mapping -from sqlbuild.compiler.compile._helpers.analysis.columns import substitute_placeholder_defaults +from sqlbuild.compiler.compile._helpers.analysis.reference_names import ( + substitute_placeholder_defaults, +) from sqlbuild.compiler.compile._helpers.analysis.syntax_checks import model_placeholders from sqlbuild.compiler.compile._helpers.render.cursor_intrinsics import ( cursor_intrinsics_analysis_sql, diff --git a/src/sqlbuild/compiler/compile/_helpers/analysis/reference_names.py b/src/sqlbuild/compiler/compile/_helpers/analysis/reference_names.py new file mode 100644 index 0000000000..55f5f5ee44 --- /dev/null +++ b/src/sqlbuild/compiler/compile/_helpers/analysis/reference_names.py @@ -0,0 +1,54 @@ +"""Reference analysis names, lineage resource types, qualified-reference scans and placeholders.""" + +from __future__ import annotations + +import sqlbuild._native as _native +from sqlbuild.compiler.compile.models import ( + CompileSqlReference, +) +from sqlbuild.compiler.compile.types import CompiledResourceType +from sqlbuild.compiler.references.types import SqlReferenceKind +from sqlbuild.compiler.sql_analysis.main._normalize_analysis import normalize_analysis_sql + + +def _lineage_resource_type(reference: CompileSqlReference) -> CompiledResourceType | None: + if reference.ref_kind == SqlReferenceKind.REF: + return CompiledResourceType.MODEL + if reference.ref_kind == SqlReferenceKind.SOURCE: + return CompiledResourceType.SOURCE + if reference.ref_kind == SqlReferenceKind.SEED: + return CompiledResourceType.SEED + if reference.ref_kind == SqlReferenceKind.TABLE_FUNCTION: + return CompiledResourceType.TABLE_FN + return None + + +def _analysis_reference_name(reference: CompileSqlReference) -> str: + if reference.ref_kind == SqlReferenceKind.TABLE_FUNCTION: + return table_function_analysis_name(reference.ref_name) + return reference.ref_name + + +def table_function_analysis_name(function_name: str) -> str: + """Return the stable relation stub used to analyze a table-function call.""" + + return f"__sqlbuild_table_function_{function_name}" + + +def substitute_placeholder_defaults(*, query_sql: str, placeholders: dict[str, str]) -> str: + """Replace @@@name tokens with their default values for SQL analysis parsing.""" + + if not placeholders: + return query_sql + return _native.substitute_placeholder_defaults(query_sql, list(placeholders.items())) + + +def _replace_refs_with_stubs( + *, + query_sql: str, + dialect: str | None = None, + relation_stubs: dict[str, str] | None = None, +) -> str: + """Replace SQLBuild marker calls with parseable SQL stubs.""" + + return normalize_analysis_sql(sql=query_sql, dialect=dialect, stubs=relation_stubs) diff --git a/src/sqlbuild/compiler/compile/_helpers/analysis/required_columns.py b/src/sqlbuild/compiler/compile/_helpers/analysis/required_columns.py index 32c7deb5b4..d137543a4b 100644 --- a/src/sqlbuild/compiler/compile/_helpers/analysis/required_columns.py +++ b/src/sqlbuild/compiler/compile/_helpers/analysis/required_columns.py @@ -5,16 +5,16 @@ from dataclasses import dataclass from typing import Any, cast -from sqlbuild.compiler.compile._helpers.analysis.columns import ( - _analysis_reference_name, - _lineage_resource_type, - _replace_refs_with_stubs, -) -from sqlbuild.compiler.compile._helpers.analysis.cte_facts import ( +from sqlbuild.compiler.compile._helpers.analysis.cte_scopes import ( _polyglot_direct_select_tables, _polyglot_top_level_ctes, _unwrap_polyglot_annotations, ) +from sqlbuild.compiler.compile._helpers.analysis.reference_names import ( + _analysis_reference_name, + _lineage_resource_type, + _replace_refs_with_stubs, +) from sqlbuild.compiler.compile.models import CompiledLineageSourceFact, CompileSqlReference from sqlbuild.compiler.compile.types import CompiledResourceType from sqlbuild.compiler.sql_analysis.constants import ( diff --git a/src/sqlbuild/compiler/compile/_helpers/analysis/validation.py b/src/sqlbuild/compiler/compile/_helpers/analysis/validation.py index 8ef57f338b..80b6228992 100644 --- a/src/sqlbuild/compiler/compile/_helpers/analysis/validation.py +++ b/src/sqlbuild/compiler/compile/_helpers/analysis/validation.py @@ -3,12 +3,8 @@ from __future__ import annotations from pathlib import Path -from typing import Any -from sqlbuild.compiler.compile._helpers.analysis.columns import ( - _replace_refs_with_stubs, - substitute_placeholder_defaults, -) +import sqlbuild._native as _native from sqlbuild.compiler.compile.constants import SQL_ANALYSIS_OPT_OUT_ENTRY from sqlbuild.compiler.compile.exceptions import CompileInputError from sqlbuild.compiler.discovery.constants import ( @@ -17,7 +13,6 @@ SQL_ANALYSIS_CONFIG_KEY, ) from sqlbuild.compiler.discovery.models import PythonHookEntry, SqlHookEntry -from sqlbuild.compiler.sql_analysis.main.import_polyglot_sql import import_polyglot_sql from sqlbuild.errors.setting_help.main.join_helps import join_helps from sqlbuild.errors.setting_help.main.model_header_help import model_header_help from sqlbuild.errors.setting_help.main.setting_help import setting_help @@ -33,13 +28,7 @@ def validate_sql_syntax( ) -> None: """Validate that the model query SQL is parseable by Polyglot.""" - cleaned_sql: str = _replace_refs_with_stubs(query_sql=query_sql, dialect=dialect) - if placeholders: - cleaned_sql = substitute_placeholder_defaults( - query_sql=cleaned_sql, placeholders=placeholders - ) - - error_message: str | None = _validate_sql_with_polyglot(sql=cleaned_sql, dialect=dialect) + error_message: str | None = _native.sql_syntax_error(query_sql, placeholders, dialect) if error_message is None: return raise CompileInputError( @@ -48,21 +37,6 @@ def validate_sql_syntax( ) from None -def _validate_sql_with_polyglot(*, sql: str, dialect: str | None) -> str | None: - polyglot_module: Any = import_polyglot_sql() - try: - result: Any = polyglot_module.validate(sql, dialect=dialect or "generic") - except polyglot_module.PolyglotError as error: - return str(error) - if result: - return None - error_message: str = "invalid SQL" - errors: object = getattr(result, "errors", ()) - if isinstance(errors, list) and errors: - error_message = str(getattr(errors[0], "message", error_message)) - return error_message - - def validate_function_sql_syntax( *, body_sql: str, @@ -187,17 +161,9 @@ def _validate_sql_syntax_with_message( ) -> None: """Parse one SQL expression with Polyglot and raise a contextual error.""" - cleaned_sql: str = _clean_sql_for_validation( - query_sql=query_sql, - placeholders=placeholders, - dialect=dialect, + error_message: str | None = _native.sql_syntax_error( + query_sql, placeholders, dialect, parse_one=True ) - polyglot_module: Any = import_polyglot_sql() - try: - polyglot_module.parse_one(cleaned_sql, dialect=dialect or "generic") - error_message: str | None = None - except polyglot_module.PolyglotError as error: - error_message = str(error) if error_message is not None: _raise_sql_validation_error( error_prefix=error_prefix, error_message=error_message, model_owned=False @@ -213,33 +179,13 @@ def _validate_hook_sql_with_message( ) -> None: """Validate a complete hook execution payload with Polyglot.""" - cleaned_sql: str = _clean_sql_for_validation( - query_sql=query_sql, - placeholders=placeholders, - dialect=dialect, - ) - error_message: str | None = _validate_sql_with_polyglot(sql=cleaned_sql, dialect=dialect) + error_message: str | None = _native.sql_syntax_error(query_sql, placeholders, dialect) if error_message is not None: _raise_sql_validation_error( error_prefix=error_prefix, error_message=error_message, model_owned=True ) -def _clean_sql_for_validation( - *, - query_sql: str, - placeholders: dict[str, str] | None, - dialect: str | None, -) -> str: - cleaned_sql: str = _replace_refs_with_stubs(query_sql=query_sql, dialect=dialect) - if placeholders: - return substitute_placeholder_defaults( - query_sql=cleaned_sql, - placeholders=placeholders, - ) - return cleaned_sql - - def _raise_sql_validation_error( *, error_prefix: str, error_message: str, model_owned: bool ) -> None: diff --git a/src/sqlbuild/compiler/compile/_helpers/assembly/audit_gates.py b/src/sqlbuild/compiler/compile/_helpers/assembly/audit_gates.py deleted file mode 100644 index abce2fc5ab..0000000000 --- a/src/sqlbuild/compiler/compile/_helpers/assembly/audit_gates.py +++ /dev/null @@ -1,67 +0,0 @@ -"""Compile validation for attached audits that gate their target.""" - -from __future__ import annotations - -from pathlib import Path - -from sqlbuild.compiler.compile.constants import ATTACHED_AUDIT_READS_OWN_DEPENDANT_CODE -from sqlbuild.compiler.compile.models import ( - CompiledObjectKey, - CompiledProject, - CompilerDiagnostic, -) -from sqlbuild.compiler.compile.types import ( - CompiledResourceType, - DiagnosticPhase, - DiagnosticSeverity, -) -from sqlbuild.compiler.graph.main._attached_audit_gate_cycles import attached_audit_gate_cycles -from sqlbuild.compiler.graph.models import AttachedAuditGateEdge - -_RESOURCE_LABELS: dict[CompiledResourceType, str] = { - CompiledResourceType.MODEL: "model", - CompiledResourceType.SOURCE: "source", - CompiledResourceType.SEED: "seed", - CompiledResourceType.UDF: "function", - CompiledResourceType.TABLE_FN: "table function", -} - - -def attached_audit_gate_diagnostics(*, project: CompiledProject) -> tuple[CompilerDiagnostic, ...]: - """Return a P005 error for each attached audit that reads a resource built from its target.""" - - audit_paths: dict[str, Path] = { - audit.name: audit.audit_file.relative_path for audit in project.audits - } - return tuple( - _cycle_diagnostic(cycle=cycle, audit_path=audit_paths.get(cycle.audit_name)) - for cycle in attached_audit_gate_cycles(project=project) - ) - - -def _cycle_diagnostic( - *, cycle: AttachedAuditGateEdge, audit_path: Path | None -) -> CompilerDiagnostic: - target: str = _describe(cycle.target) - read: str = _describe(cycle.read) - return CompilerDiagnostic( - phase=DiagnosticPhase.COMPILE, - severity=DiagnosticSeverity.ERROR, - code=ATTACHED_AUDIT_READS_OWN_DEPENDANT_CODE, - message=( - f"Audit '{cycle.audit_name}' on {target} reads {read}, which depends on " - f"'{cycle.target.name}'; an attached audit gates its target, so it cannot wait for a " - "resource built from that target" - ), - resource_type=cycle.target.resource_type, - resource_name=cycle.target.name, - path=audit_path, - help=( - f"write a singular audit under audits/singular/ that references both " - f"'{cycle.target.name}' and '{cycle.read.name}'; it runs once both are built" - ), - ) - - -def _describe(key: CompiledObjectKey) -> str: - return f"{_RESOURCE_LABELS[CompiledResourceType(key.resource_type)]} '{key.name}'" diff --git a/src/sqlbuild/compiler/compile/_helpers/assembly/binding_waves.py b/src/sqlbuild/compiler/compile/_helpers/assembly/binding_waves.py deleted file mode 100644 index b084a8d591..0000000000 --- a/src/sqlbuild/compiler/compile/_helpers/assembly/binding_waves.py +++ /dev/null @@ -1,109 +0,0 @@ -"""Analyze open model inputs after their producers have supplied closed shapes.""" - -from __future__ import annotations - -from collections.abc import Callable -from functools import partial - -from sqlbuild.adapter.contract.models import ExpressionInferenceProfile -from sqlbuild.compiler.compile.classes.binding_dataflow import BindingDataflow -from sqlbuild.compiler.compile.models import CompileModelInput, PolyglotAnalysisResult -from sqlbuild.compiler.compile.models import ( - ModelSqlAnalysis as _ModelSqlAnalysis, -) -from sqlbuild.compiler.compile.models import ( - ModelSqlAnalysisRequest as _ModelSqlAnalysisRequest, -) -from sqlbuild.compiler.lineage.types import InferredNullability -from sqlbuild.compiler.references.types import SqlReferenceKind - -_DATAFLOW_WORKERS: int = 4 -_DATAFLOW_BATCH_MIN: int = 8 -_DATAFLOW_BATCH_LIMIT: int = 64 - - -def analyze_binding_waves( - *, - requests: tuple[_ModelSqlAnalysisRequest, ...], - names: tuple[str, ...], - cached: dict[str, PolyglotAnalysisResult], - previous_signatures: dict[str, str], - shapes: dict[str, dict[str, str]], - types: dict[str, dict[str, str]], - nullability: dict[str, dict[str, InferredNullability]], - profile: ExpressionInferenceProfile, - analyze: Callable[..., tuple[_ModelSqlAnalysis, ...]], - complete: Callable[..., tuple[_ModelSqlAnalysis, ...]], -) -> tuple[tuple[_ModelSqlAnalysis, ...], dict[str, PolyglotAnalysisResult]]: - """Analyze one topological level at a time, the reference for dataflow scheduling.""" - - return BindingDataflow( - requests=requests, - names=names, - cached=cached, - previous_signatures=previous_signatures, - shapes=shapes, - types=types, - nullability=nullability, - profile=profile, - analyze=analyze, - complete=complete, - ).analyze_waves() - - -def analyze_binding_dataflow( - *, - requests: tuple[_ModelSqlAnalysisRequest, ...], - names: tuple[str, ...], - cached: dict[str, PolyglotAnalysisResult], - previous_signatures: dict[str, str], - shapes: dict[str, dict[str, str]], - types: dict[str, dict[str, str]], - nullability: dict[str, dict[str, InferredNullability]], - profile: ExpressionInferenceProfile, - analyze: Callable[..., tuple[_ModelSqlAnalysis, ...]], - complete: Callable[..., tuple[_ModelSqlAnalysis, ...]], -) -> tuple[tuple[_ModelSqlAnalysis, ...], dict[str, PolyglotAnalysisResult]]: - """Analyze each model once its producers are final; replay waves after any error.""" - - create: Callable[[], BindingDataflow] = partial( - BindingDataflow, - requests=requests, - names=names, - cached=cached, - previous_signatures=previous_signatures, - shapes=shapes, - types=types, - nullability=nullability, - profile=profile, - analyze=analyze, - complete=complete, - ) - result: tuple[tuple[_ModelSqlAnalysis, ...], dict[str, PolyglotAnalysisResult]] | None = ( - create().analyze_dataflow( - workers=_DATAFLOW_WORKERS, - batch_min=_DATAFLOW_BATCH_MIN, - batch_limit=_DATAFLOW_BATCH_LIMIT, - ) - ) - return result if result is not None else create().analyze_waves() - - -def downstream_model_names( - *, model_inputs: tuple[CompileModelInput, ...], changed_names: set[str] -) -> set[str]: - downstream_by_name: dict[str, set[str]] = {} - for model_input in model_inputs: - for reference in model_input.references: - if reference.ref_kind == SqlReferenceKind.REF: - downstream_by_name.setdefault(reference.ref_name, set()).add( - model_input.model_file.file_path.stem - ) - downstream_names: set[str] = set() - pending: list[str] = list(changed_names) - while pending: - for downstream_name in downstream_by_name.get(pending.pop(), set()): - if downstream_name not in downstream_names and downstream_name not in changed_names: - downstream_names.add(downstream_name) - pending.append(downstream_name) - return downstream_names diff --git a/src/sqlbuild/compiler/compile/_helpers/assembly/metadata_validation.py b/src/sqlbuild/compiler/compile/_helpers/assembly/metadata_validation.py index 00b756a42c..6a3fdff5fd 100644 --- a/src/sqlbuild/compiler/compile/_helpers/assembly/metadata_validation.py +++ b/src/sqlbuild/compiler/compile/_helpers/assembly/metadata_validation.py @@ -3,185 +3,37 @@ from __future__ import annotations import re -from collections.abc import Iterator from functools import lru_cache -from typing import Any, cast from sqlbuild.adapter.contract.models import ExpressionInferenceProfile -from sqlbuild.adapter.contract.types import TypeFamily -from sqlbuild.adapter.type_system.main.normalize_type import normalize_type -from sqlbuild.compiler.compile._helpers.analysis.columns import _polyglot_expression_type -from sqlbuild.compiler.compile._helpers.analysis.compact import ( - analyze_columns_and_lineage_with_polyglot, - analyze_queries_with_compact_polyglot_batch, - get_complete_schema_binding_request, +from sqlbuild.compiler.analysis_session.main._infer_native_query_columns import ( + infer_native_query_columns, ) +from sqlbuild.compiler.analysis_session.models import NativeColumnQuery, NativeQueryColumns from sqlbuild.compiler.compile._helpers.assembly.native_declarations import ( known_declared_types, known_function_names, ) -from sqlbuild.compiler.compile._helpers.assembly.semantic_shapes import semantic_shapes -from sqlbuild.compiler.compile._helpers.diagnostics.resource_sql import get_resource_sql_diagnostics from sqlbuild.compiler.compile.models import ( - CompiledFunction, CompiledModel, CompiledModelSqlTestPayload, CompiledProject, CompilerDiagnostic, - NativeCompactAnalysis, - PolyglotAnalysisResult, ) from sqlbuild.compiler.compile.types import ( CompiledResourceType, DiagnosticPhase, DiagnosticSeverity, ) -from sqlbuild.compiler.references.types import SqlReferenceKind from sqlbuild.compiler.sql_analysis.constants import BINDING_UNKNOWN_TABLE_INTERNAL_CODE from sqlbuild.compiler.sql_analysis.main._resolve_binding_column import resolve_binding_column from sqlbuild.compiler.sql_analysis.main._schema_validation import get_schema_validations -from sqlbuild.compiler.sql_analysis.main.import_polyglot_sql import import_polyglot_sql from sqlbuild.compiler.sql_analysis.models import SqlBindingResult, SqlSchemaValidationRequest -from sqlbuild.spec.contracts.models import SchemaAuditInstance, SourceLocation +from sqlbuild.spec.contracts.models import SchemaAuditInstance -_UNKNOWN_TYPE: str = "UNKNOWN" _EXPRESSION_AUDIT: str = "expression_is_true" _RELATIONSHIPS_AUDIT: str = "relationships" _ACCEPTED_VALUES_AUDIT: str = "accepted_values" -_SELECT_KIND: str = "select" -_FUNCTION_KIND: str = "function" -_CURSOR_FAMILIES: dict[str, frozenset[TypeFamily]] = { - "integer": frozenset({TypeFamily.INTEGER, TypeFamily.DECIMAL}), - "timestamp": frozenset({TypeFamily.TIMESTAMP, TypeFamily.DATETIME, TypeFamily.DATE}), - "date": frozenset({TypeFamily.TIMESTAMP, TypeFamily.DATETIME, TypeFamily.DATE}), -} - - -def get_semantic_metadata_diagnostics( - *, - project: CompiledProject, - profile: ExpressionInferenceProfile, - resource_sql_analysis: bool = True, -) -> tuple[CompilerDiagnostic, ...]: - """Reject metadata names only where absence can be proven; resource SQL only when analysed.""" - - if not project.settings.sql_analysis: - return () - shapes: dict[str, dict[str, str]] = semantic_shapes(project=project, profile=profile) - functions: dict[str, CompiledFunction] = { - function.name.casefold(): function for function in project.functions - } - diagnostics: list[CompilerDiagnostic] = [] - for model in project.models: - if model.config.values.get("sql_analysis") is False or not model.binding_validated: - continue - diagnostics.extend( - _function_errors( - model=model, - functions=functions, - shapes=shapes, - profile=profile, - ) - ) - shape: dict[str, str] | None = shapes.get(model.name) - if shape is None: - continue - diagnostics.extend( - _audit_errors(model=model, project=project, shape=shape, shapes=shapes, profile=profile) - ) - values: dict[str, object] = model.config.values - references: list[tuple[str, str, dict[str, str]]] = [] - for key in ("unique_key", "cursor", "partition_column", "row_diff_exclude_columns"): - references.extend((key, name, shape) for name in _names(values.get(key))) - custom: object = values.get("config") - if isinstance(custom, dict): - references.extend( - ("partition_column", name, shape) - for name in _names(cast(dict[str, object], custom).get("partition_column")) - ) - tolerances: object = values.get("row_diff_tolerances") - by_column: object = ( - cast(dict[str, object], tolerances).get("by_column") - if isinstance(tolerances, dict) - else None - ) - if isinstance(by_column, dict): - references.extend(("row_diff_tolerances", str(name), shape) for name in by_column) - cursor_inputs: object = values.get("cursor_inputs") - if isinstance(cursor_inputs, dict): - for upstream, columns in cursor_inputs.items(): - upstream_shape: dict[str, str] | None = shapes.get(str(upstream)) - if upstream_shape is not None: - references.extend( - (f"cursor_inputs {upstream}", name, upstream_shape) - for name in _names(columns) - ) - for key, name, reference_shape in references: - if name.casefold() not in {column.casefold() for column in reference_shape}: - diagnostics.append( - _model_error( - model=model, - code="B300", - name=name, - message=f"{key} references unknown column '{name}'", - ) - ) - cursor: object = values.get("cursor") - cursor_type: object = values.get("cursor_type") - if isinstance(cursor, str) and isinstance(cursor_type, str): - actual: str = next( - (value for key, value in shape.items() if key.casefold() == cursor.casefold()), - "UNKNOWN", - ) - if cursor_type.lower() in _CURSOR_FAMILIES: - family: TypeFamily = normalize_type( - type_sql=actual, dialect=profile.sql_analysis_dialect - ).family - if ( - family != TypeFamily.OTHER - and family not in _CURSOR_FAMILIES[cursor_type.lower()] - ): - diagnostics.append( - _model_error( - model=model, - code="B301", - name=cursor, - message=( - f"cursor_type {cursor_type} does not match " - f"column '{cursor}' type {actual}" - ), - ) - ) - for source in project.sources: - cursor = source.source_entry.cursor_column - shape = shapes.get(source.name) - if ( - cursor - and shape is not None - and cursor.casefold() not in {name.casefold() for name in shape} - ): - line: int - column: int - line, column = _text_position(text=source.source_file.contents, name=cursor) - diagnostics.append( - CompilerDiagnostic( - phase=DiagnosticPhase.COMPILE, - severity=DiagnosticSeverity.ERROR, - code="B300", - message=f"cursor_column references unknown column '{cursor}'", - resource_type=CompiledResourceType.SOURCE, - resource_name=source.name, - path=source.source_file.relative_path, - line=line, - column=column, - ) - ) - diagnostics.extend(_sql_test_errors(project=project, shapes=shapes, profile=profile)) - if resource_sql_analysis: - diagnostics.extend( - get_resource_sql_diagnostics(project=project, shapes=shapes, profile=profile) - ) - return tuple(diagnostics) def _audit_errors( @@ -293,22 +145,6 @@ def _audit_errors( return tuple(diagnostics) -def _different_argument_families( - *, left: str, right: str, profile: ExpressionInferenceProfile -) -> bool: - families: set[TypeFamily] = { - normalize_type(type_sql=value, dialect=profile.sql_analysis_dialect).family - for value in (left, right) - } - different_families: bool = ( - len(families) > 1 - and TypeFamily.OTHER not in families - and not families <= {TypeFamily.INTEGER, TypeFamily.DECIMAL, TypeFamily.FLOAT} - and not families <= {TypeFamily.TIMESTAMP, TypeFamily.DATE, TypeFamily.DATETIME} - ) - return different_families - - @lru_cache(maxsize=256) def _comparison_result(*, left: str, right: str, dialect: str | None) -> SqlBindingResult: return get_schema_validations( @@ -349,57 +185,6 @@ def _accepted_values_result( )[0] -def _sql_test_errors( - *, - project: CompiledProject, - shapes: dict[str, dict[str, str]], - profile: ExpressionInferenceProfile, -) -> tuple[CompilerDiagnostic, ...]: - diagnostics: list[CompilerDiagnostic] = [] - columns_by_sql: dict[str, tuple[str, ...]] = _sql_test_columns(project=project, profile=profile) - for test in project.sql_tests: - if not isinstance(test.payload, CompiledModelSqlTestPayload): - continue - for cte in (*test.payload.authored_ctes, *test.payload.expected_ctes): - match: re.Match[str] | None = re.match( - r"__(?:expected|ref|source|seed)__(.+)$", cte.name - ) - shape: dict[str, str] | None = shapes.get(match.group(1)) if match else None - if shape is None: - continue - available: set[str] = {name.casefold() for name in shape} - for column_name in columns_by_sql[cte.sql_body]: - if column_name.casefold() not in available: - line: int - column_position: int - line, column_position = _text_position( - text=test.test_file.contents, - name=column_name, - offset=max(test.test_file.contents.find(cte.name), 0), - ) - diagnostics.append( - CompilerDiagnostic( - phase=DiagnosticPhase.COMPILE, - severity=DiagnosticSeverity.ERROR, - code="B302", - message=f"SQL test '{cte.name}' names unknown column '{column_name}'", - resource_type=CompiledResourceType.SQL_TEST, - resource_name=test.name, - path=test.test_file.relative_path, - line=line, - column=column_position, - location=SourceLocation( - path=test.test_file.relative_path, - line=line, - column=column_position, - end_line=line, - end_column=column_position + len(column_name), - ), - ) - ) - return tuple(diagnostics) - - def _sql_test_columns( *, project: CompiledProject, profile: ExpressionInferenceProfile ) -> dict[str, tuple[str, ...]]: @@ -412,28 +197,22 @@ def _sql_test_columns( queries: tuple[str, ...] = tuple(bodies) if not queries: return {} - prepared: tuple[NativeCompactAnalysis, ...] = analyze_queries_with_compact_polyglot_batch( - query_sqls=queries, - references=((),) * len(queries), - placeholders=(None,) * len(queries), - column_nullability_by_table={}, - column_types_by_table={}, - inference_profile=profile, - recover_cte_facts=(False,) * len(queries), + analyses: tuple[NativeQueryColumns, ...] = infer_native_query_columns( + queries=tuple( + NativeColumnQuery(sql=sql, mode="batch", recover_cte_facts=False) for sql in queries + ), + profile=profile, ) - result: dict[str, tuple[str, ...]] = {} - for sql, native in zip(queries, prepared, strict=True): - analysis: PolyglotAnalysisResult = analyze_columns_and_lineage_with_polyglot( - query_sql=sql, - references=(), - inference_profile=profile, - allow_compact_analysis=True, - precomputed=native, - ) - result[sql] = tuple(column.name for column in analysis.columns or ()) + result: dict[str, tuple[str, ...]] = { + sql: _column_names(analysis) for sql, analysis in zip(queries, analyses, strict=True) + } return result +def _column_names(analysis: NativeQueryColumns) -> tuple[str, ...]: + return tuple(column.name for column in analysis.columns or ()) + + def _names(value: object) -> tuple[str, ...]: if isinstance(value, str): return (value,) @@ -442,182 +221,6 @@ def _names(value: object) -> tuple[str, ...]: return () -def _function_errors( - *, - model: CompiledModel, - functions: dict[str, CompiledFunction], - shapes: dict[str, dict[str, str]], - profile: ExpressionInferenceProfile, -) -> tuple[CompilerDiagnostic, ...]: - if not functions or not any( - reference.ref_kind in {SqlReferenceKind.UDF, SqlReferenceKind.TABLE_FUNCTION} - for reference in model.references - ): - return () - module: Any = import_polyglot_sql() - request: SqlSchemaValidationRequest = get_complete_schema_binding_request( - query_sql=model.query_sql, - placeholders=None, - dialect=profile.sql_analysis_dialect, - binding_schema=shapes, - ) - try: - parsed: Any = module.parse_one(request.sql, dialect=profile.sql_analysis_dialect) - except module.PolyglotError: - return () - calls: list[tuple[Any, Any, dict[str, Any], CompiledFunction]] = list( - _declared_function_calls(root=parsed, functions=functions) - ) - column_selects: dict[int, Any] = { - id(select): select - for _, select, payload, function in calls - if select is not None and _resolves_argument_columns(payload=payload, function=function) - } - relations_by_select: dict[int, list[dict[str, Any]]] = { - key: _select_relations(select=select) for key, select in column_selects.items() - } - table_names: set[str] = set() - for relations in relations_by_select.values(): - table_names.update(map(_relation_table_name, relations)) - folded_shapes: dict[str, dict[str, list[str]]] = { - table_name: _folded_columns(shapes[table_name]) - for table_name in table_names - if table_name in shapes - } - diagnostics: list[CompilerDiagnostic] = [] - for call, select, payload, function in calls: - name: str = str(payload.get("name", "")).removeprefix("__sqlbuild_udf_") - arguments: list[dict[str, Any]] = payload.get("args", []) - if len(arguments) != len(function.arguments): - diagnostics.append( - _model_error( - model=model, - code="B102", - name=name, - message=( - f"Function '{name}' expects {len(function.arguments)} arguments " - f"but received {len(arguments)}" - ), - ) - ) - continue - argument_expressions: list[Any] = call.expressions - for argument, expression, declaration in zip( - arguments, argument_expressions, function.arguments, strict=True - ): - actual: str = ( - _polyglot_expression_type(expression=expression, inference_profile=profile) - or _UNKNOWN_TYPE - ) - literal: Any = argument.get("literal") - column: Any = argument.get("column") - if literal: - actual = {"string": "VARCHAR", "number": "DOUBLE", "boolean": "BOOLEAN"}.get( - literal.get("literal_type"), "UNKNOWN" - ) - elif column: - actual = _argument_column_type( - column=column, - relations=None if select is None else relations_by_select[id(select)], - folded_shapes=folded_shapes, - ) - if actual != _UNKNOWN_TYPE and _different_argument_families( - left=actual, right=declaration.type, profile=profile - ): - diagnostics.append( - _model_error( - model=model, - code="B301", - severity=DiagnosticSeverity.ERROR, - name=name, - message=( - f"Function '{name}' argument '{declaration.name}' " - f"expects {declaration.type}, received {actual}; " - "convert the argument explicitly" - ), - ) - ) - return tuple(diagnostics) - - -def _declared_function_calls( - *, root: Any, functions: dict[str, CompiledFunction] -) -> Iterator[tuple[Any, Any, dict[str, Any], CompiledFunction]]: - """Yield calls of declared functions with their nearest select and serialised payload.""" - - for call, select in _function_scopes(root): - payload: dict[str, Any] = call.to_dict().get("function", {}) - name: str = str(payload.get("name", "")).removeprefix("__sqlbuild_udf_") - function: CompiledFunction | None = functions.get(name.casefold()) - if function is not None: - yield call, select, payload, function - - -def _resolves_argument_columns(*, payload: dict[str, Any], function: CompiledFunction) -> bool: - arguments: list[dict[str, Any]] = payload.get("args", []) - return len(arguments) == len(function.arguments) and any( - not argument.get("literal") and argument.get("column") for argument in arguments - ) - - -def _function_scopes(root: Any) -> Iterator[tuple[Any, Any]]: - pending: list[tuple[Any, Any]] = [(root, None)] - node: Any - select: Any - while pending: - node, select = pending.pop() - if node.kind == _SELECT_KIND: - select = node - if node.kind == _FUNCTION_KIND: - yield node, select - pending.extend((child, select) for child in reversed(node.children())) - - -def _select_relations(*, select: Any) -> list[dict[str, Any]]: - payload: dict[str, Any] = select.to_dict().get("select", {}) - relations: list[dict[str, Any]] = list((payload.get("from") or {}).get("expressions", [])) - relations.extend(join.get("this", {}) for join in payload.get("joins", [])) - return relations - - -def _relation_table_name(relation: dict[str, Any]) -> str: - return str(relation.get("table", {}).get("name", {}).get("name", "")) - - -def _folded_columns(shape: dict[str, str]) -> dict[str, list[str]]: - """Index column types by case-folded name, preserving declaration order per name.""" - - folded: dict[str, list[str]] = {} - for key, value in shape.items(): - folded.setdefault(key.casefold(), []).append(value) - return folded - - -def _argument_column_type( - *, - column: dict[str, Any], - relations: list[dict[str, Any]] | None, - folded_shapes: dict[str, dict[str, list[str]]], -) -> str: - if relations is None: - return _UNKNOWN_TYPE - qualifier: str | None = (column.get("table") or {}).get("name") - name: str = str(column.get("name", {}).get("name", "")) - folded_name: str = name.casefold() - candidates: list[str] = [] - for relation in relations: - table: dict[str, Any] = relation.get("table", {}) - table_name: str = _relation_table_name(relation) - alias: str = str((table.get("alias") or {}).get("name", table_name)) - if qualifier is not None and qualifier.casefold() != alias.casefold(): - continue - shape: dict[str, list[str]] | None = folded_shapes.get(table_name) - if shape is None: - return _UNKNOWN_TYPE - candidates.extend(shape.get(folded_name, ())) - return candidates[0] if len(candidates) == 1 else _UNKNOWN_TYPE - - def _model_error( *, model: CompiledModel, diff --git a/src/sqlbuild/compiler/compile/_helpers/assembly/project.py b/src/sqlbuild/compiler/compile/_helpers/assembly/project.py index 8d13e10215..711b6e09ff 100644 --- a/src/sqlbuild/compiler/compile/_helpers/assembly/project.py +++ b/src/sqlbuild/compiler/compile/_helpers/assembly/project.py @@ -2,40 +2,23 @@ from __future__ import annotations -import re from collections.abc import Sequence from dataclasses import dataclass, replace -from functools import partial -from graphlib import CycleError, TopologicalSorter from pathlib import Path from typing import Any, cast +import sqlbuild._native as _native from sqlbuild.adapter.contract.models import ExpressionInferenceProfile from sqlbuild.adapter.contract.types import BuiltinAdapter -from sqlbuild.compiler.compile._helpers.analysis.cache import ( - build_analysis_cache_context, - build_compact_analysis_cache_plan, - compact_analysis_batch_response_writer, - model_analysis_cache_key, - model_analysis_output_signature, - read_compact_analysis_cache_candidate, - read_model_analyses, - record_analysis_cache_metrics, - write_model_analyses, +from sqlbuild.compiler.analysis_session.main._infer_native_query_columns import ( + infer_native_query_columns, ) -from sqlbuild.compiler.compile._helpers.analysis.compact import ( - NativeCompactAnalysis, - analyze_columns_and_lineage_with_polyglot, - analyze_queries_with_compact_polyglot_batch, +from sqlbuild.compiler.analysis_session.models import NativeColumnQuery, NativeModelAnalysisRequest +from sqlbuild.compiler.compile._helpers.analysis.binding_requests import ( get_complete_schema_binding_request, - infer_columns_with_sql_analysis, -) -from sqlbuild.compiler.compile._helpers.analysis.dynamic_pivot import ( - analyze_dynamic_column_contract, ) -from sqlbuild.compiler.compile._helpers.analysis.pivot_requests import ( - model_dynamic_families, - model_pivot_sql, +from sqlbuild.compiler.compile._helpers.analysis.cache import ( + build_analysis_cache_context, ) from sqlbuild.compiler.compile._helpers.analysis.syntax_checks import ( model_placeholders as _model_placeholders, @@ -48,46 +31,24 @@ get_authored_binding_location, query_line_offset, ) -from sqlbuild.compiler.compile._helpers.assembly.binding_waves import analyze_binding_dataflow -from sqlbuild.compiler.compile._helpers.assembly.binding_waves import ( - downstream_model_names as _downstream_model_names, -) from sqlbuild.compiler.compile._helpers.assembly.native_declarations import ( known_declared_types, known_function_names, ) from sqlbuild.compiler.compile._helpers.assembly.semantic_shapes import ( - binding_required_names, - binding_schema_for_model, build_column_nullability_by_table, build_complete_binding_schemas, - published_model_shape, - upstream_signatures, ) from sqlbuild.compiler.compile._helpers.assembly.semantic_shapes import ( build_declared_column_types as _build_column_types_by_table, ) -from sqlbuild.compiler.compile._helpers.assembly.semantic_shapes import ( - referenced_model_names as _referenced_model_names, -) from sqlbuild.compiler.compile._helpers.assembly.targets import ( build_model_relation_target, - build_seed_relation_target, -) -from sqlbuild.compiler.compile._helpers.config.namespace_validation import ( - validate_preserved_logical_namespace, -) -from sqlbuild.compiler.compile._helpers.deps.dependencies import ( - audit_scope_deps, - function_build_deps, - model_build_deps, - sql_test_scope_deps, ) from sqlbuild.compiler.compile._helpers.diagnostics.recovery import complete_semantic_diagnostics from sqlbuild.compiler.compile._helpers.diagnostics.scope import report_scope_index_errors from sqlbuild.compiler.compile._helpers.native_stages.assembly import ( - analyze_model_sql_by_engine, - dynamic_column_contract_by_engine, + analyze_model_sql, expression_source_shapes_by_engine, project_facts_by_engine, ) @@ -106,43 +67,22 @@ expand_sql_macros, find_macro_call_names, ) -from sqlbuild.compiler.compile._helpers.render.templating import expand_template_data -from sqlbuild.compiler.compile._helpers.sharing.binding import shareable_binding_prekeys -from sqlbuild.compiler.compile._helpers.sql_tests.helper_ctes import ( - report_mocks_reading_referencing_helpers, -) -from sqlbuild.compiler.compile._helpers.sql_tests.identity import build_sql_test_case_fingerprint -from sqlbuild.compiler.compile._helpers.sql_tests.scope_deps import ( - function_sql_test_scope_deps, - macro_sql_test_scope_deps, - udf_sql_test_scope_deps, -) from sqlbuild.compiler.compile.main._scope_index_with_compile_usages import ( scope_index_with_compile_usages, ) from sqlbuild.compiler.compile.models import ( AnalysisCacheContext, - CompactAnalysisCacheCandidate, - CompactAnalysisCacheModel, - CompactAnalysisCachePlan, - CompactBatchExecutionOptions, - CompactBatchPreparation, CompileAuditInput, CompiledAudit, - CompiledDirectLogicSqlTestPayload, CompiledFunction, - CompileDirectLogicSqlTestInputPayload, CompiledLineageColumnFact, CompiledModel, - CompiledModelSqlTestPayload, CompiledObjectKey, CompiledProject, CompiledRelationLocation, CompiledSeed, CompiledSource, CompiledSqlScenario, - CompiledSqlTest, - CompiledSqlTestResource, CompileModelInput, CompileModelSqlTestInputPayload, CompileProjectInputs, @@ -161,21 +101,18 @@ from sqlbuild.compiler.compile.models import ( ModelSqlAnalysis as _ModelSqlAnalysis, ) -from sqlbuild.compiler.compile.models import ( - ModelSqlAnalysisRequest as _ModelSqlAnalysisRequest, -) from sqlbuild.compiler.compile.types import ( AttachedAuditTargetKind, - CompactBatchResponseCallback, CompiledResourceType, DiagnosticPhase, DiagnosticSeverity, - SqlTestMode, ) from sqlbuild.compiler.lineage.types import ColumnLineageMode, InferredNullability from sqlbuild.compiler.planner.types import ContractPolicy from sqlbuild.compiler.profiling.main._record_cpu import record_compile_cpu_timing from sqlbuild.compiler.profiling.main.record import record_compile_timing +from sqlbuild.compiler.project_assembly.constants import AUDIT_SLOT, SEED_SLOT, SOURCE_SLOT +from sqlbuild.compiler.project_assembly.main._native_resource import native_resource from sqlbuild.compiler.project_assembly.models import ( NativeModelFacts, NativeProjectFacts, @@ -186,15 +123,12 @@ from sqlbuild.compiler.sql_analysis.constants import ( BINDING_UNKNOWN_TABLE_INTERNAL_CODE, NATIVE_DIALECT_ALIASES, + NATIVE_FAILURE_PREFIX, ) -from sqlbuild.compiler.sql_analysis.exceptions import SqlAnalysisBoundaryError from sqlbuild.compiler.sql_analysis.main._binding_catalog import create_binding_catalog from sqlbuild.compiler.sql_analysis.main._identifier_case import ignores_quoted_case -from sqlbuild.compiler.sql_analysis.main._schema_validation import get_schema_validations from sqlbuild.compiler.sql_analysis.models import ( SqlBindingDiagnostic, - SqlBindingResult, - SqlSchemaValidationRequest, ) from sqlbuild.spec.contracts.main.resolve_effective_adapter_name import ( resolve_effective_adapter_name, @@ -203,11 +137,9 @@ resolve_effective_scenario_config, ) from sqlbuild.spec.contracts.models import ( - DefaultsConfig, SchemaDynamicColumnFamily, SourceEntry, SourceLocation, - TargetConfig, ) @@ -217,10 +149,6 @@ class _DynamicContractAnalysisInputs: authoritative_column_types_by_table: dict[str, dict[str, str]] -_COMPACT_BATCH_CACHE_MIN_MODEL_COUNT: int = 256 -_COMPACT_BATCH_ENTRY_REUSE_MIN_PERCENT: int = 10 - - def assemble_compiled_project( *, inputs: CompileProjectInputs, @@ -235,9 +163,6 @@ def assemble_compiled_project( sql_analysis_enabled: bool = ( inputs.effective_settings.sql_analysis and not skip_column_inference ) - seed_names: frozenset[str] = frozenset( - seed_input.schema_entry.name for seed_input in inputs.seed_inputs - ) column_nullability_by_table: dict[str, dict[str, InferredNullability]] = ( build_column_nullability_by_table(inputs) ) @@ -344,34 +269,32 @@ def assemble_compiled_project( record_compile_timing("model_analysis_ms"), record_compile_cpu_timing("model_analysis_cpu_ms"), ): - python_analysis: partial[dict[str, _ModelSqlAnalysis]] = partial( - _analyze_model_sql_in_parallel, - known_functions=known_function_names(inputs.sql_function_inputs), - known_types=known_declared_types( - functions=inputs.sql_function_inputs, column_types=column_types_by_table - ), - model_inputs=tuple( - model_input - for model_input in inputs.model_inputs - if model_input.sql_validation_enabled - and ( - analysis_model_names is None - or _model_name(model_input) in analysis_model_names - ) - ), - column_nullability_by_table=column_nullability_by_table, - column_types_by_table=column_types_by_table, - inference_profile=profile, - allow_compact_analysis=allow_compact_analysis, - rich_type_inference=rich_type_inference, - analysis_cache=analysis_cache, - complete_binding_schemas=complete_binding_schemas, - ) - model_sql_analysis_by_name, native_session = analyze_model_sql_by_engine( - python_analysis=python_analysis, - dynamic_families_by_table=dynamic_families_by_table, + model_sql_analysis_by_name, native_session = analyze_model_sql( + NativeModelAnalysisRequest( + known_functions=known_function_names(inputs.sql_function_inputs), + known_types=known_declared_types( + functions=inputs.sql_function_inputs, column_types=column_types_by_table + ), + model_inputs=tuple( + model_input + for model_input in inputs.model_inputs + if model_input.sql_validation_enabled + and ( + analysis_model_names is None + or _model_name(model_input) in analysis_model_names + ) + ), + column_nullability_by_table=column_nullability_by_table, + column_types_by_table=column_types_by_table, + inference_profile=profile, + allow_compact_analysis=allow_compact_analysis, + rich_type_inference=rich_type_inference, + analysis_cache=analysis_cache, + complete_binding_schemas=complete_binding_schemas, + dynamic_families_by_table=dynamic_families_by_table, + ) ) - native: NativeProjectFacts | None = project_facts_by_engine( + native: NativeProjectFacts = project_facts_by_engine( inputs=inputs, dialect=profile.sql_analysis_dialect, analysis_model_names=analysis_model_names, @@ -382,7 +305,7 @@ def assemble_compiled_project( column_nullability_by_table=column_nullability_by_table, dynamic_families_by_table=dynamic_families_by_table, ) - resources: NativeProjectResources | None = native.resources if native else None + resources: NativeProjectResources = native.resources scope_index: ScopeIndex = scope_index_with_compile_usages(inputs=inputs) report_scope_index_errors(index=scope_index) effective_target_values: dict[str, object] = resolve_early_model_templates( @@ -435,7 +358,7 @@ def assemble_compiled_project( sql_validation_enabled=( analysis_model_names is None or _model_name(model_input) in analysis_model_names ), - native_model=native.models[index] if native else None, + native_model=native.models[index], column_nullability_by_table=column_nullability_by_table, column_types_by_table=column_types_by_table, dynamic_contract_analysis_inputs=dynamic_contract_analysis_inputs, @@ -448,40 +371,49 @@ def assemble_compiled_project( sources=tuple( _assemble_compiled_source( source_input=source_input, - target_config=inputs.effective_target, - effective_vars=inputs.effective_vars, - native_entry=resources.source_entries[index] if resources else None, + native_entry=native_resource( + resources=resources, + slot=SOURCE_SLOT, + items=resources.source_entries, + index=index, + ), ) for index, source_input in enumerate(inputs.source_inputs) ), seeds=tuple( _assemble_compiled_seed( seed_input=seed_input, - defaults=inputs.project_config.defaults, - target_config=inputs.effective_target, - effective_vars=inputs.effective_vars, - native_destination=resources.seed_destinations[index] if resources else None, + native_destination=native_resource( + resources=resources, + slot=SEED_SLOT, + items=resources.seed_destinations, + index=index, + ), ) for index, seed_input in enumerate(inputs.seed_inputs) ), functions=tuple( _assemble_compiled_function( function_input=function_input, - seed_names=seed_names, - native_deps=resources.function_deps[index] if resources else None, + native_deps=resources.function_deps[index], ) for index, function_input in enumerate(inputs.sql_function_inputs) ), audits=tuple( _assemble_compiled_audit( audit_input=audit_input, - native_scope_deps=resources.audit_scope_deps[index] if resources else None, + native_scope_deps=native_resource( + resources=resources, + slot=AUDIT_SLOT, + items=resources.audit_scope_deps, + index=index, + ), ) for index, audit_input in enumerate(inputs.audit_inputs) ), sql_tests=assemble_sql_tests_by_engine( inputs=inputs, - assemble_python_test=lambda test_input: _assemble_compiled_sql_test( + macro_mock_queries=lambda test_input: _build_test_model_query_overrides( test_input=test_input, model_inputs=inputs.model_inputs, inputs=inputs ), ), @@ -539,7 +471,7 @@ def _assemble_compiled_model( model_input: CompileModelInput, sql_analysis_enabled: bool, sql_validation_enabled: bool = True, - native_model: NativeModelFacts | None = None, + native_model: NativeModelFacts, column_nullability_by_table: dict[str, dict[str, InferredNullability]] | None = None, column_types_by_table: dict[str, dict[str, str]] | None = None, dynamic_contract_analysis_inputs: _DynamicContractAnalysisInputs | None = None, @@ -548,8 +480,7 @@ def _assemble_compiled_model( allow_compact_analysis: bool = False, ) -> CompiledModel: model_name: str = model_input.model_file.file_path.stem - native_deps: tuple[CompiledObjectKey, ...] | None = native_model.deps if native_model else None - syntax_validated: bool = native_deps is not None + syntax_validated: bool = native_model.syntax_valid profile: ExpressionInferenceProfile = inference_profile or ExpressionInferenceProfile() analysis_query_sql: str = cursor_intrinsics_analysis_sql( sql=model_input.query_sql, @@ -573,19 +504,12 @@ def _assemble_compiled_model( dialect=profile.sql_analysis_dialect, ) if sql_analysis_enabled: - polyglot_analysis: PolyglotAnalysisResult = ( - sql_analysis.polyglot_analysis - if sql_analysis is not None - else analyze_columns_and_lineage_with_polyglot( - query_sql=analysis_query_sql, - references=model_input.references, - placeholders=placeholders, - column_nullability_by_table=column_nullability_by_table, - column_types_by_table=column_types_by_table, - inference_profile=profile, - allow_compact_analysis=allow_compact_analysis, + if sql_analysis is None: + raise _native.NativeCompilerError( + f"{NATIVE_FAILURE_PREFIX}native model analysis: the session returned no " + f"analysis for model '{model_name}'" ) - ) + polyglot_analysis: PolyglotAnalysisResult = sql_analysis.polyglot_analysis if polyglot_analysis.analysis_succeeded: inferred_columns = polyglot_analysis.columns fast_lineage_columns = polyglot_analysis.lineage_columns @@ -600,12 +524,15 @@ def _assemble_compiled_model( placeholders=placeholders, dialect=profile.sql_analysis_dialect, ) - inferred_columns = infer_columns_with_sql_analysis( - query_sql=analysis_query_sql, - placeholders=placeholders, + inferred_columns = infer_native_query_columns( + queries=( + NativeColumnQuery( + sql=analysis_query_sql, mode="parse", placeholders=placeholders + ), + ), + profile=profile, column_nullability_by_table=column_nullability_by_table, - inference_profile=profile, - ) + )[0].columns elif sql_validation_enabled and model_input.sql_validation_enabled and not syntax_validated: validate_sql_syntax( query_sql=analysis_query_sql, @@ -614,38 +541,17 @@ def _assemble_compiled_model( placeholders=placeholders, dialect=profile.sql_analysis_dialect, ) - dynamic_column_contract: DynamicColumnContractProof | None = dynamic_column_contract_by_engine( - sql_analysis=sql_analysis, - native_proof=native_model.dynamic_contract if native_model else None, - python_proof=partial( - analyze_dynamic_column_contract, - query_sql=model_pivot_sql(query_sql=analysis_query_sql, placeholders=placeholders), - dialect=profile.sql_analysis_dialect, - families=model_dynamic_families(model_input), - column_types_by_table=column_types_by_table or {}, - authoritative_column_types_by_table=( - dynamic_contract_analysis_inputs.authoritative_column_types_by_table - if dynamic_contract_analysis_inputs is not None - else {} - ), - column_nullability_by_table=column_nullability_by_table or {}, - dynamic_families_by_table=( - dynamic_contract_analysis_inputs.families_by_table - if dynamic_contract_analysis_inputs is not None - else {} - ), - ), + dynamic_column_contract: DynamicColumnContractProof | None = ( + sql_analysis.dynamic_column_contract + if sql_analysis is not None and sql_analysis.dynamic_column_contract is not None + else native_model.dynamic_contract ) if dynamic_column_contract is not None and dynamic_column_contract.output_proven: inferred_columns = dynamic_column_contract.fixed_columns fast_lineage_has_star = True return CompiledModel( key=CompiledObjectKey(resource_type=CompiledResourceType.MODEL, name=model_name), - deps=( - native_deps - if native_deps is not None - else model_build_deps(references=model_input.references) - ), + deps=native_model.deps, name=model_name, relative_path=model_input.model_file.relative_path, query_sql=model_input.query_sql, @@ -677,734 +583,6 @@ def _assemble_compiled_model( ) -def _analyze_model_sql_in_parallel( - *, - known_functions: tuple[str, ...], - known_types: tuple[str, ...], - model_inputs: tuple[CompileModelInput, ...], - column_nullability_by_table: dict[str, dict[str, InferredNullability]], - column_types_by_table: dict[str, dict[str, str]], - inference_profile: ExpressionInferenceProfile, - allow_compact_analysis: bool, - rich_type_inference: bool, - analysis_cache: AnalysisCacheContext | None, - complete_binding_schemas: dict[str, dict[str, str]], -) -> dict[str, _ModelSqlAnalysis]: - if not model_inputs: - return {} - analyzed_model_names: frozenset[str] = frozenset( - _model_name(model_input) for model_input in model_inputs - ) - requests: tuple[_ModelSqlAnalysisRequest, ...] = tuple( - _model_sql_analysis_request( - model_input=model_input, - analysis_cache=analysis_cache, - column_nullability_by_table=column_nullability_by_table, - column_types_by_table=column_types_by_table, - complete_binding_schemas=complete_binding_schemas, - ) - for model_input in model_inputs - ) - request_cache_keys: tuple[str, ...] = tuple( - request.cache_key for request in requests if request.cache_key is not None - ) - dependency_ordered: bool = allow_compact_analysis and any( - request.binding_schema is not None and not all(request.binding_schema.values()) - for request in requests - ) - compact_batch_plan: CompactAnalysisCachePlan | None = None - if analysis_cache is not None: - compact_batch_plan = build_compact_analysis_cache_plan( - context=analysis_cache, - models=tuple( - CompactAnalysisCacheModel( - name=_model_name(request.model_input), - cache_key=request.cache_key, - upstream_names=_referenced_model_names( - model_input=request.model_input, - available_names=analyzed_model_names, - ), - ) - for request in requests - ), - min_model_count=_COMPACT_BATCH_CACHE_MIN_MODEL_COUNT, - ) - compact_cached_analyses: dict[str, PolyglotAnalysisResult] = {} - compact_batch_hit_count: int = 0 - compact_candidate: CompactAnalysisCacheCandidate | None = ( - read_compact_analysis_cache_candidate( - plan=compact_batch_plan, - expected_count=len(requests), - min_model_count=_COMPACT_BATCH_CACHE_MIN_MODEL_COUNT, - ) - if compact_batch_plan is not None and not dependency_ordered - else None - ) - if compact_candidate is not None: - completed_analyses: dict[str, PolyglotAnalysisResult] = {} - if analysis_cache is not None: - completed_analyses, _, _ = read_model_analyses( - context=analysis_cache, - cache_keys=request_cache_keys, - model_names=tuple(_model_name(request.model_input) for request in requests), - upstream_model_names_by_key={ - request.cache_key: _referenced_model_names( - model_input=request.model_input, - available_names=analyzed_model_names, - ) - for request in requests - if request.cache_key is not None - }, - ) - if all(key in completed_analyses for key in request_cache_keys): - record_analysis_cache_metrics( - batch_hits=len(requests), entry_hits=0, misses=0, bypasses=0 - ) - return { - _model_name(request.model_input): _ModelSqlAnalysis( - polyglot_analysis=completed_analyses[cache_key], - placeholders=request.placeholders, - ) - for request, cache_key in zip(requests, request_cache_keys, strict=True) - } - try: - compact_analyses: tuple[_ModelSqlAnalysis, ...] = _analyze_model_sql_requests( - requests=requests, - cached_analyses=completed_analyses, - column_nullability_by_table=column_nullability_by_table, - column_types_by_table=column_types_by_table, - inference_profile=inference_profile, - allow_compact_analysis=allow_compact_analysis, - rich_type_inference=rich_type_inference, - cached_compact_batch=( - compact_candidate.preparation, - compact_candidate.response, - ), - ) - except SqlAnalysisBoundaryError: - pass - else: - compact_cached_analyses = { - request_cache_keys[index]: compact_analyses[index].polyglot_analysis - for index in compact_candidate.matching_indexes - } - compact_batch_hit_count = len(compact_candidate.matching_indexes) - if compact_batch_hit_count == len(requests): - record_analysis_cache_metrics( - batch_hits=compact_batch_hit_count, - entry_hits=0, - misses=0, - bypasses=0, - ) - compact_analyses = _complete_inferred_bindings( - known_functions=known_functions, - known_types=known_types, - requests=requests, - analyses=compact_analyses, - complete_binding_schemas=complete_binding_schemas, - inference_profile=inference_profile, - ) - return { - _model_name(model_input): analysis - for model_input, analysis in zip(model_inputs, compact_analyses, strict=True) - } - entry_cache_keys: tuple[str, ...] = tuple( - cache_key for cache_key in request_cache_keys if cache_key not in compact_cached_analyses - ) - cached_analyses: dict[str, PolyglotAnalysisResult] - previous_signatures: dict[str, str] - cached_output_signatures_by_key: dict[str, str] - cached_analyses, previous_signatures, cached_output_signatures_by_key = ( - read_model_analyses( - context=analysis_cache, - cache_keys=entry_cache_keys, - model_names=tuple(_model_name(request.model_input) for request in requests), - upstream_model_names_by_key={ - request.cache_key: _referenced_model_names( - model_input=request.model_input, - available_names=analyzed_model_names, - ) - for request in requests - if request.cache_key is not None - and request.cache_key not in compact_cached_analyses - }, - ) - if analysis_cache is not None - else ({}, {}, {}) - ) - entry_cache_hit_count: int = sum( - request.cache_key is not None and request.cache_key in cached_analyses - for request in requests - ) - if ( - compact_batch_plan is not None - and compact_batch_hit_count == 0 - and entry_cache_hit_count > 0 - and entry_cache_hit_count * 100 < len(requests) * _COMPACT_BATCH_ENTRY_REUSE_MIN_PERCENT - ): - cached_analyses.clear() - cached_output_signatures_by_key.clear() - entry_cache_hit_count = 0 - cached_analyses.update(compact_cached_analyses) - cached_output_signatures_by_key.update( - { - cache_key: model_analysis_output_signature(analysis) - for cache_key, analysis in compact_cached_analyses.items() - } - ) - analyses: tuple[_ModelSqlAnalysis, ...] - if dependency_ordered: - analyses, cached_analyses = analyze_binding_dataflow( - requests=requests, - names=tuple(_model_name(request.model_input) for request in requests), - cached=cached_analyses, - previous_signatures=previous_signatures, - shapes=complete_binding_schemas, - types=column_types_by_table, - nullability=column_nullability_by_table, - profile=inference_profile, - analyze=partial( - _analyze_model_sql_requests, - inference_profile=inference_profile, - allow_compact_analysis=allow_compact_analysis, - rich_type_inference=rich_type_inference, - shareable_prekeys=shareable_binding_prekeys(requests=requests), - ), - complete=partial( - _complete_inferred_bindings, - known_functions=known_functions, - known_types=known_types, - inference_profile=inference_profile, - ), - ) - if compact_batch_plan is not None: - compact_batch_hit_count = sum(analysis.cached for analysis in analyses) - entry_cache_hit_count -= compact_batch_hit_count - else: - analyses = _analyze_model_sql_requests( - requests=requests, - cached_analyses=cached_analyses, - column_nullability_by_table=column_nullability_by_table, - column_types_by_table=column_types_by_table, - inference_profile=inference_profile, - allow_compact_analysis=allow_compact_analysis, - rich_type_inference=rich_type_inference, - on_compact_response=( - compact_analysis_batch_response_writer( - plan=compact_batch_plan, - count=len(requests), - ) - if compact_batch_plan is not None and not cached_analyses - else None - ), - shareable_prekeys=shareable_binding_prekeys(requests=requests), - ) - analyses = _complete_inferred_bindings( - known_functions=known_functions, - known_types=known_types, - requests=requests, - analyses=analyses, - complete_binding_schemas=complete_binding_schemas, - inference_profile=inference_profile, - ) - record_analysis_cache_metrics( - batch_hits=compact_batch_hit_count, - entry_hits=entry_cache_hit_count, - misses=( - len(requests) - compact_batch_hit_count - entry_cache_hit_count - if analysis_cache is not None - else 0 - ), - bypasses=(len(requests) if analysis_cache is None else 0), - ) - if analysis_cache is None: - return { - _model_name(model_input): analysis - for model_input, analysis in zip(model_inputs, analyses, strict=True) - } - current_analyses_by_name: dict[str, PolyglotAnalysisResult] = { - _model_name(request.model_input): analysis.polyglot_analysis - for request, analysis in zip(requests, analyses, strict=True) - } - current_signatures_by_name: dict[str, str] = { - _model_name(request.model_input): ( - cached_output_signatures_by_key[request.cache_key] - if request.cache_key is not None and request.cache_key in cached_analyses - else model_analysis_output_signature(analysis.polyglot_analysis) - ) - for request, analysis in zip(requests, analyses, strict=True) - } - analyses_to_record_by_name: dict[str, PolyglotAnalysisResult] = { - _model_name(request.model_input): analysis.polyglot_analysis - for request, analysis in zip(requests, analyses, strict=True) - if request.cache_key is None or request.cache_key not in cached_analyses - } - changed_signature_names: set[str] = { - _model_name(request.model_input) - for request, analysis in zip(requests, analyses, strict=True) - if ( - previous_signatures.get(_model_name(request.model_input)) - != current_signatures_by_name[_model_name(request.model_input)] - or ( - not analysis.polyglot_analysis.analysis_succeeded - and request.cache_key not in cached_analyses - ) - ) - } - analyses_to_record_by_name.update( - {model_name: current_analyses_by_name[model_name] for model_name in changed_signature_names} - ) - invalidated_names: set[str] = _downstream_model_names( - model_inputs=model_inputs, - changed_names=changed_signature_names, - ) - if invalidated_names and not dependency_ordered: - invalidated_requests: tuple[_ModelSqlAnalysisRequest, ...] = tuple( - request - for request in requests - if ( - _model_name(request.model_input) in invalidated_names - and request.cache_key is not None - and request.cache_key in cached_analyses - ) - ) - invalidated_analyses_by_name: dict[str, _ModelSqlAnalysis] = { - _model_name(request.model_input): analysis - for request, analysis in zip( - invalidated_requests, - _analyze_model_sql_requests( - requests=invalidated_requests, - cached_analyses={}, - column_nullability_by_table=column_nullability_by_table, - column_types_by_table=column_types_by_table, - inference_profile=inference_profile, - allow_compact_analysis=allow_compact_analysis, - rich_type_inference=rich_type_inference, - ), - strict=True, - ) - } - analyses = tuple( - invalidated_analyses_by_name.get(_model_name(request.model_input), analysis) - for request, analysis in zip(requests, analyses, strict=True) - ) - analyses = _complete_inferred_bindings( - known_functions=known_functions, - known_types=known_types, - requests=requests, - analyses=analyses, - complete_binding_schemas=complete_binding_schemas, - inference_profile=inference_profile, - ) - invalidated_analyses_by_name = { - _model_name(request.model_input): analysis - for request, analysis in zip(requests, analyses, strict=True) - if _model_name(request.model_input) in invalidated_names - } - analyses_to_record_by_name.update( - { - _model_name(request.model_input): analysis.polyglot_analysis - for request, analysis in zip(requests, analyses, strict=True) - if _model_name(request.model_input) in invalidated_names - } - ) - current_analyses_by_name = { - _model_name(request.model_input): analysis.polyglot_analysis - for request, analysis in zip(requests, analyses, strict=True) - } - current_signatures_by_name.update( - { - model_name: model_analysis_output_signature(invalidated_analysis.polyglot_analysis) - for model_name, invalidated_analysis in invalidated_analyses_by_name.items() - } - ) - with record_compile_timing("cache_publication_ms"): - write_model_analyses( - context=analysis_cache, - analyses_by_key={ - request.cache_key: analysis.polyglot_analysis - for request, analysis in zip(requests, analyses, strict=True) - if request.cache_key is not None - and ( - request.cache_key not in cached_analyses - or _model_name(request.model_input) in invalidated_names - ) - }, - latest_analyses_by_model=analyses_to_record_by_name, - dependency_signatures_by_key={ - request.cache_key: upstream_signatures( - model_input=request.model_input, - signatures=current_signatures_by_name, - available_names=analyzed_model_names, - ) - for request in requests - if request.cache_key is not None - and ( - request.cache_key not in cached_analyses - or _model_name(request.model_input) in invalidated_names - ) - }, - ) - return { - _model_name(model_input): analysis - for model_input, analysis in zip(model_inputs, analyses, strict=True) - } - - -def _analyze_model_sql_requests( - *, - requests: tuple[_ModelSqlAnalysisRequest, ...], - cached_analyses: dict[str, PolyglotAnalysisResult], - column_nullability_by_table: dict[str, dict[str, InferredNullability]], - column_types_by_table: dict[str, dict[str, str]], - inference_profile: ExpressionInferenceProfile, - allow_compact_analysis: bool, - rich_type_inference: bool, - cached_compact_batch: tuple[CompactBatchPreparation, object] | None = None, - on_compact_response: CompactBatchResponseCallback | None = None, - shareable_prekeys: frozenset[str] | None = None, -) -> tuple[_ModelSqlAnalysis, ...]: - if allow_compact_analysis: - uncached: tuple[tuple[int, _ModelSqlAnalysisRequest], ...] = tuple( - (index, request) - for index, request in enumerate(requests) - if request.cache_key is None or request.cache_key not in cached_analyses - ) - prepared_by_index: dict[int, NativeCompactAnalysis] = {} - diagnostics_by_index: dict[int, tuple[SqlBindingDiagnostic, ...]] = {} - if uncached: - batch_requests: tuple[tuple[int, _ModelSqlAnalysisRequest], ...] = ( - tuple(enumerate(requests)) if cached_compact_batch is not None else uncached - ) - prepared: tuple[NativeCompactAnalysis, ...] = ( - analyze_queries_with_compact_polyglot_batch( - query_sqls=tuple(request.query_sql for _, request in batch_requests), - references=tuple( - request.model_input.references for _, request in batch_requests - ), - placeholders=tuple(request.placeholders for _, request in batch_requests), - column_nullability_by_table=column_nullability_by_table, - column_types_by_table=column_types_by_table, - inference_profile=inference_profile, - recover_cte_facts=tuple( - _should_recover_cte_facts(request.model_input) - for _, request in batch_requests - ), - rich_type_inference=rich_type_inference, - cached_batch=cached_compact_batch, - execution=CompactBatchExecutionOptions( - on_response=( - on_compact_response if len(uncached) == len(requests) else None - ), - binding_schemas=tuple( - request.binding_schema for _, request in batch_requests - ), - shareable_prekeys=shareable_prekeys, - ), - ) - ) - prepared_by_index = { - index: value for (index, _), value in zip(batch_requests, prepared, strict=True) - } - validation_indices: tuple[int, ...] = tuple( - index - for index, request in uncached - if request.binding_schema is not None - and prepared_by_index[index].binding_diagnostics is None - ) - with record_compile_timing("binding_validation_ms"): - validation_results: tuple[SqlBindingResult, ...] = get_schema_validations( - requests=tuple( - SqlSchemaValidationRequest( - sql=prepared_by_index[index].cleaned_sql, - dialect=inference_profile.sql_analysis_dialect, - schema=requests[index].binding_schema or {}, - known_functions=inference_profile.semantic_known_functions, - known_types=inference_profile.semantic_known_types, - quoted_identifiers_ignore_case=inference_profile.quoted_identifiers_ignore_case, - catalog=inference_profile.binding_catalog, - ) - for index in validation_indices - ) - ) - diagnostics_by_index = { - index: result.diagnostics - for index, result in zip(validation_indices, validation_results, strict=True) - } - return tuple( - _analyze_model_sql( - request=request, - cached_analysis=( - cached_analyses.get(request.cache_key) - if request.cache_key is not None - else None - ), - column_nullability_by_table=column_nullability_by_table, - column_types_by_table=column_types_by_table, - inference_profile=inference_profile, - allow_compact_analysis=True, - precomputed=( - replace( - prepared_by_index[index], - binding_diagnostics=diagnostics_by_index.get( - index, prepared_by_index[index].binding_diagnostics - ), - ) - if index in prepared_by_index - else None - ), - ) - for index, request in enumerate(requests) - ) - - def analyze(request: _ModelSqlAnalysisRequest) -> _ModelSqlAnalysis: - return _analyze_model_sql( - request=request, - cached_analysis=( - cached_analyses.get(request.cache_key) if request.cache_key is not None else None - ), - column_nullability_by_table=column_nullability_by_table, - column_types_by_table=column_types_by_table, - inference_profile=inference_profile, - allow_compact_analysis=allow_compact_analysis, - ) - - return tuple(analyze(request) for request in requests) - - -def _complete_inferred_bindings( - *, - known_functions: tuple[str, ...], - known_types: tuple[str, ...], - requests: tuple[_ModelSqlAnalysisRequest, ...], - analyses: tuple[_ModelSqlAnalysis, ...], - complete_binding_schemas: dict[str, dict[str, str]], - inference_profile: ExpressionInferenceProfile, - supplied_relations: frozenset[str] = frozenset(), -) -> tuple[_ModelSqlAnalysis, ...]: - """Bind each scope independently, preserving open inputs as empty tables.""" - - complete_schemas: dict[str, dict[str, str]] = dict(complete_binding_schemas) - results: list[_ModelSqlAnalysis] = list(analyses) - indexes: dict[str, int] = { - _model_name(request.model_input): index for index, request in enumerate(requests) - } - available_names: frozenset[str] = frozenset(indexes) - graph: dict[str, tuple[str, ...]] = { - name: _referenced_model_names( - model_input=requests[index].model_input, available_names=available_names - ) - for name, index in indexes.items() - } - try: - ordered_names: tuple[str, ...] = tuple(TopologicalSorter(graph).static_order()) - except CycleError: - return analyses - for name in ordered_names: - index: int = indexes[name] - request: _ModelSqlAnalysisRequest = requests[index] - required_names: frozenset[str] | None = binding_required_names(request.model_input) - if required_names is None: - continue - analysis: PolyglotAnalysisResult = results[index].polyglot_analysis - inputs_known: bool = bool(required_names) and required_names <= complete_schemas.keys() - star_pending: bool = analysis.has_star and not analysis.star_resolved and inputs_known - stars_expanded_natively: bool = required_names <= supplied_relations - if star_pending and analysis.columns and stars_expanded_natively: - analysis = replace(analysis, star_resolved=True) - results[index] = replace(results[index], polyglot_analysis=analysis) - star_pending = False - if ( - not results[index].cached - and required_names - and (any(column.type is None for column in analysis.columns or ()) or star_pending) - and not re.search(r"\b(?:UNION|INTERSECT|EXCEPT)\b", request.query_sql, re.IGNORECASE) - ): - input_schemas: dict[str, dict[str, str]] = { - table: complete_schemas[table] - for table in required_names - if table in complete_schemas - } - nullability: dict[str, dict[str, InferredNullability]] = { - table: dict.fromkeys(columns, InferredNullability.UNKNOWN) - for table, columns in input_schemas.items() - } - enriched: PolyglotAnalysisResult = analyze_columns_and_lineage_with_polyglot( - query_sql=request.query_sql, - references=request.model_input.references, - placeholders=request.placeholders, - column_types_by_table=input_schemas, - column_nullability_by_table=nullability, - inference_profile=inference_profile, - allow_compact_analysis=True, - recover_cte_facts=_should_recover_cte_facts(request.model_input), - ) - recovered_types: dict[str, str | None] = { - column.name: column.type - for column in (*(enriched.columns or ()), *(analysis.columns or ())) - if column.type is not None - } - star_expanded: bool = star_pending and enriched.analysis_succeeded - if (not analysis.columns or star_expanded) and enriched.analysis_succeeded: - analysis = replace( - enriched, - binding_diagnostics=analysis.binding_diagnostics, - binding_validated=analysis.binding_validated, - ) - analysis = replace( - analysis, - columns=tuple( - replace(column, type=column.type or recovered_types.get(column.name)) - for column in analysis.columns or () - ), - star_resolved=analysis.star_resolved or star_expanded, - ) - results[index] = replace(results[index], polyglot_analysis=analysis) - star_known: bool = not analysis.has_star or (analysis.star_resolved and inputs_known) - if analysis.columns and star_known and name not in complete_schemas: - complete_schemas.setdefault( - name, - published_model_shape( - sql=results[index].cleaned_sql or request.query_sql, - profile=inference_profile, - columns={column.name: column.type or "UNKNOWN" for column in analysis.columns}, - inputs={table: complete_schemas.get(table, {}) for table in required_names}, - config_values=request.model_input.config.values, - ), - ) - deferred_validation_indices: list[int] = [] - deferred_validation_requests: list[SqlSchemaValidationRequest] = [] - for index, request in enumerate(requests): - if results[index].cached: - continue - required_names = binding_required_names(request.model_input) - if required_names is None: - continue - if results[index].fused_binding_validated and ( - results[index].validated_schema or request.binding_schema - ) == {name: complete_schemas.get(name, {}) for name in required_names}: - continue - deferred_validation_indices.append(index) - deferred_validation_requests.append( - replace( - get_complete_schema_binding_request( - query_sql=request.query_sql, - cleaned_sql=results[index].cleaned_sql, - known_functions=known_functions, - known_types=known_types, - placeholders=request.placeholders, - dialect=inference_profile.sql_analysis_dialect, - binding_schema={ - name: complete_schemas.get(name, {}) for name in required_names - }, - ), - quoted_identifiers_ignore_case=inference_profile.quoted_identifiers_ignore_case, - catalog=inference_profile.binding_catalog, - ) - ) - with record_compile_timing("binding_validation_ms"): - validation_results: tuple[SqlBindingResult, ...] = get_schema_validations( - requests=tuple(deferred_validation_requests) - ) - for index, validation_result in zip( - deferred_validation_indices, validation_results, strict=True - ): - current: _ModelSqlAnalysis = results[index] - results[index] = replace( - current, - polyglot_analysis=replace( - current.polyglot_analysis, - binding_diagnostics=validation_result.diagnostics, - binding_validated=True, - ), - ) - return tuple(results) - - -def _analyze_model_sql( - *, - request: _ModelSqlAnalysisRequest, - cached_analysis: PolyglotAnalysisResult | None, - column_nullability_by_table: dict[str, dict[str, InferredNullability]], - column_types_by_table: dict[str, dict[str, str]], - inference_profile: ExpressionInferenceProfile, - allow_compact_analysis: bool, - precomputed: NativeCompactAnalysis | None = None, -) -> _ModelSqlAnalysis: - if cached_analysis is not None: - return _ModelSqlAnalysis( - polyglot_analysis=cached_analysis, - placeholders=request.placeholders, - cached=True, - ) - polyglot_analysis: PolyglotAnalysisResult = analyze_columns_and_lineage_with_polyglot( - query_sql=request.query_sql, - references=request.model_input.references, - placeholders=request.placeholders, - column_nullability_by_table=column_nullability_by_table, - column_types_by_table=column_types_by_table, - inference_profile=inference_profile, - allow_compact_analysis=allow_compact_analysis, - binding_schema=request.binding_schema, - recover_cte_facts=_should_recover_cte_facts(request.model_input), - precomputed=precomputed, - ) - return _ModelSqlAnalysis( - polyglot_analysis=polyglot_analysis, - cleaned_sql=precomputed.cleaned_sql if precomputed is not None else None, - placeholders=request.placeholders, - validated_schema=request.binding_schema, - fused_binding_validated=precomputed is not None - and precomputed.binding_diagnostics is not None, - ) - - -def _model_sql_analysis_request( - *, - model_input: CompileModelInput, - analysis_cache: AnalysisCacheContext | None, - column_nullability_by_table: dict[str, dict[str, InferredNullability]], - column_types_by_table: dict[str, dict[str, str]], - complete_binding_schemas: dict[str, dict[str, str]], -) -> _ModelSqlAnalysisRequest: - placeholders: dict[str, str] | None = _model_placeholders(model_input) - query_sql: str = cursor_intrinsics_analysis_sql( - sql=model_input.query_sql, - cursor_type=model_input.config.values.get("cursor_type"), - ) - binding_schema: dict[str, dict[str, str]] | None = binding_schema_for_model( - model_input=model_input, - complete_binding_schemas=complete_binding_schemas, - ) - cache_key: str | None = ( - model_analysis_cache_key( - context=analysis_cache, - query_sql=query_sql, - references=model_input.references, - placeholders=placeholders, - column_nullability_by_table=column_nullability_by_table, - column_types_by_table=column_types_by_table, - binding_schema=binding_schema, - recover_cte_facts=_should_recover_cte_facts(model_input), - ) - if analysis_cache is not None - else None - ) - return _ModelSqlAnalysisRequest( - model_input=model_input, - query_sql=query_sql, - placeholders=placeholders, - cache_key=cache_key, - binding_schema=binding_schema, - ) - - -def _should_recover_cte_facts(model_input: CompileModelInput) -> bool: - return model_input.config.values.get("contract") == ContractPolicy.ENFORCED or ( - model_input.schema_entry is not None and bool(model_input.schema_entry.type_enforcement) - ) - - def _model_name(model_input: CompileModelInput) -> str: return model_input.model_file.file_path.stem @@ -1515,103 +693,20 @@ def _binding_compiler_diagnostics( def _assemble_compiled_source( - *, - source_input: CompileSourceInput, - target_config: TargetConfig | None, - effective_vars: dict[str, object], - native_entry: SourceEntry | None = None, + *, source_input: CompileSourceInput, native_entry: SourceEntry ) -> CompiledSource: - source_entry: SourceEntry = ( - native_entry - if native_entry is not None - else _build_source_relation_entry( - source_entry=source_input.source_entry, - target_config=target_config, - effective_vars=effective_vars, - ) - ) return CompiledSource( - key=CompiledObjectKey(resource_type=CompiledResourceType.SOURCE, name=source_entry.name), + key=CompiledObjectKey(resource_type=CompiledResourceType.SOURCE, name=native_entry.name), deps=(), - name=source_entry.name, - source_entry=source_entry, + name=native_entry.name, + source_entry=native_entry, source_file=source_input.source_file, ) -def _build_source_relation_entry( - *, - source_entry: SourceEntry, - target_config: TargetConfig | None, - effective_vars: dict[str, object], -) -> SourceEntry: - if source_entry.loader is None or target_config is None: - return source_entry - loader_target_config: TargetConfig = replace( - target_config, - schema=target_config.loader_schema or target_config.schema, - ) - validate_preserved_logical_namespace( - resource_label=f"Managed source '{source_entry.name}'", - logical_database=source_entry.database, - logical_schema=source_entry.schema, - target_config=loader_target_config, - ) - return replace( - source_entry, - database=( - source_entry.database - if source_entry.database is not None - else _expand_target_value( - value=target_config.database, - effective_vars=effective_vars, - ) - ), - schema=( - source_entry.schema - if source_entry.schema is not None - else _expand_target_value( - value=target_config.loader_schema or target_config.schema, - effective_vars=effective_vars, - ) - ), - ) - - -def _expand_target_value(*, value: str | None, effective_vars: dict[str, object]) -> str | None: - if value is None: - return None - return str( - expand_template_data( - value=value, - variables=effective_vars, - context_values={}, - context_label="managed source target", - allow_context=False, - preserve_context_tokens=False, - preserve_unknown_context=False, - ) - ) - - def _assemble_compiled_seed( - *, - seed_input: CompileSeedInput, - defaults: DefaultsConfig, - target_config: TargetConfig | None, - effective_vars: dict[str, object], - native_destination: CompiledRelationLocation | None = None, + *, seed_input: CompileSeedInput, native_destination: CompiledRelationLocation ) -> CompiledSeed: - target: CompiledRelationLocation = ( - native_destination - if native_destination is not None - else build_seed_relation_target( - seed_entry=seed_input.schema_entry, - defaults=defaults, - target_config=target_config, - effective_vars=effective_vars, - ) - ) return CompiledSeed( key=CompiledObjectKey( resource_type=CompiledResourceType.SEED, name=seed_input.schema_entry.name @@ -1621,15 +716,14 @@ def _assemble_compiled_seed( seed_file=seed_input.seed_file, schema_entry=seed_input.schema_entry, schema_file=seed_input.schema_file, - destination=target, + destination=native_destination, ) def _assemble_compiled_function( *, function_input: CompileSqlFunctionInput, - seed_names: frozenset[str] = frozenset(), - native_deps: tuple[CompiledObjectKey, ...] | None = None, + native_deps: tuple[CompiledObjectKey, ...], ) -> CompiledFunction: return CompiledFunction( key=CompiledObjectKey( @@ -1638,11 +732,7 @@ def _assemble_compiled_function( ), name=function_input.name, ), - deps=( - native_deps - if native_deps is not None - else function_build_deps(references=function_input.references, seed_names=seed_names) - ), + deps=native_deps, name=function_input.name, relative_path=function_input.function_file.relative_path, arguments=function_input.arguments, @@ -1679,7 +769,7 @@ def _assemble_compiled_function( def _assemble_compiled_audit( *, audit_input: CompileAuditInput, - native_scope_deps: tuple[CompiledObjectKey, ...] | None = None, + native_scope_deps: tuple[CompiledObjectKey, ...], ) -> CompiledAudit: audit_name: str = _resolve_audit_name(audit_input) normalized_target_kind: AttachedAuditTargetKind | None = None @@ -1687,15 +777,7 @@ def _assemble_compiled_audit( normalized_target_kind = AttachedAuditTargetKind(audit_input.attached_target_kind) return CompiledAudit( key=CompiledObjectKey(resource_type=CompiledResourceType.AUDIT, name=audit_name), - scope_deps=( - native_scope_deps - if native_scope_deps is not None - else audit_scope_deps( - references=audit_input.references, - attached_target_kind=audit_input.attached_target_kind, - attached_target_name=audit_input.attached_target_name, - ) - ), + scope_deps=native_scope_deps, name=audit_name, definition_name=(audit_input.audit_block.name or audit_input.audit_file.file_path.stem), audit_file=audit_input.audit_file, @@ -1719,149 +801,6 @@ def _assemble_compiled_audit( ) -def _assemble_compiled_sql_test( - *, - test_input: CompileSqlTestInput, - model_inputs: tuple[CompileModelInput, ...], - inputs: CompileProjectInputs, -) -> CompiledSqlTest: - test_name: str = _resolve_test_name(test_input) - compiled_payload: CompiledModelSqlTestPayload | CompiledDirectLogicSqlTestPayload - scope_deps: tuple[CompiledObjectKey, ...] - target_model_names: tuple[str, ...] = () - if isinstance(test_input.payload, CompileDirectLogicSqlTestInputPayload): - if test_input.payload.mode == SqlTestMode.MACRO: - scope_deps = macro_sql_test_scope_deps( - tested_macro_names=test_input.payload.tested_resource_names, - model_inputs=model_inputs, - ) - elif test_input.payload.mode == SqlTestMode.UDF: - scope_deps = udf_sql_test_scope_deps( - tested_udf_names=test_input.payload.tested_resource_names, - model_inputs=model_inputs, - ) - else: - scope_deps = function_sql_test_scope_deps( - tested_function_names=test_input.payload.tested_resource_names, - ) - compiled_payload = CompiledDirectLogicSqlTestPayload( - mode=test_input.payload.mode, - helper_ctes=test_input.payload.helper_ctes, - actual_cte=test_input.payload.actual_cte, - expected_cte=test_input.payload.expected_cte, - tested_resource_names=test_input.payload.tested_resource_names, - ) - else: - model_payload: CompileModelSqlTestInputPayload = test_input.payload - target_model_names = tuple( - dict.fromkeys( - ( - *model_payload.expected_model_names, - *model_payload.assertion_target_model_names, - *model_payload.reference_target_model_names, - ) - ) - ) - report_mocks_reading_referencing_helpers( - authored_ctes=model_payload.authored_ctes, - reader_ctes=(*model_payload.expected_ctes, *model_payload.assertion_ctes), - model_inputs=model_inputs, - target_model_names=target_model_names, - mock_model_names=model_payload.mock_model_names, - test_file=test_input.test_file, - test_block=test_input.test_block, - syntax=inputs.sql_lexical_syntax, - ) - scope_deps = sql_test_scope_deps(expected_model_names=target_model_names) - compiled_payload = CompiledModelSqlTestPayload( - authored_ctes=model_payload.authored_ctes, - macro_mocks=model_payload.macro_mocks, - model_query_overrides=_build_test_model_query_overrides( - test_input=test_input, - model_inputs=model_inputs, - inputs=inputs, - ), - mock_model_names=model_payload.mock_model_names, - mock_source_names=model_payload.mock_source_names, - mock_seed_names=model_payload.mock_seed_names, - mock_dbt_ref_names=model_payload.mock_dbt_ref_names, - mock_table_function_names=model_payload.mock_table_function_names, - expected_ctes=model_payload.expected_ctes, - expected_model_names=model_payload.expected_model_names, - assertion_ctes=model_payload.assertion_ctes, - assertion_names=model_payload.assertion_names, - ) - tested_resources: tuple[CompiledSqlTestResource, ...] = ( - tuple( - CompiledSqlTestResource(kind=test_input.payload.mode, name=name) - for name in test_input.payload.tested_resource_names - ) - if isinstance(test_input.payload, CompileDirectLogicSqlTestInputPayload) - else () - ) - case_fingerprint: str | None = ( - build_sql_test_case_fingerprint( - source_path=test_input.test_file.relative_path, - block_index=test_input.test_block.test_index, - case_name=test_input.case_name, - parameter_schema=test_input.parameter_schema, - parameter_values=test_input.parameter_values, - expanded_sql=test_input.sql_body, - scope_deps=scope_deps, - tested_resources=tested_resources, - ) - if test_input.case_name is not None - else None - ) - return CompiledSqlTest( - key=CompiledObjectKey(resource_type=CompiledResourceType.SQL_TEST, name=test_name), - scope_deps=scope_deps, - name=test_name, - test_file=test_input.test_file, - test_block=test_input.test_block, - sql_body=test_input.sql_body, - mode=test_input.mode, - payload=compiled_payload, - source_path=test_input.test_file.relative_path, - ownership_root=test_input.test_file.ownership_root, - block_index=test_input.test_block.test_index, - explicit_name=test_input.test_block.name, - parent_name=test_input.parent_name, - case_name=test_input.case_name, - case_index=test_input.case_index, - case_fingerprint=case_fingerprint, - parameter_schema=test_input.parameter_schema, - parameter_values=test_input.parameter_values, - expected_model_names=( - test_input.payload.expected_model_names - if isinstance(test_input.payload, CompileModelSqlTestInputPayload) - else () - ), - assertion_names=( - test_input.payload.assertion_names - if isinstance(test_input.payload, CompileModelSqlTestInputPayload) - else () - ), - assertion_target_model_names=( - test_input.payload.assertion_target_model_names - if isinstance(test_input.payload, CompileModelSqlTestInputPayload) - else () - ), - read_helper_names=( - test_input.payload.read_helper_names - if isinstance(test_input.payload, CompileModelSqlTestInputPayload) - else () - ), - reference_target_model_names=( - test_input.payload.reference_target_model_names - if isinstance(test_input.payload, CompileModelSqlTestInputPayload) - else () - ), - target_model_names=target_model_names, - tested_resources=tested_resources, - ) - - def _build_test_model_query_overrides( *, test_input: CompileSqlTestInput, @@ -1948,10 +887,3 @@ def _resolve_audit_name(audit_input: CompileAuditInput) -> str: if audit_input.audit_block.name is not None: return audit_input.audit_block.name return audit_input.audit_file.file_path.stem - - -def _resolve_test_name(test_input: CompileSqlTestInput) -> str: - parent_name: str = test_input.test_block.name or test_input.test_file.file_path.stem - if test_input.case_name is not None: - return f"{parent_name} [{test_input.case_name}]" - return parent_name diff --git a/src/sqlbuild/compiler/compile/_helpers/assembly/semantic_shapes.py b/src/sqlbuild/compiler/compile/_helpers/assembly/semantic_shapes.py index 0513354e15..b36912be17 100644 --- a/src/sqlbuild/compiler/compile/_helpers/assembly/semantic_shapes.py +++ b/src/sqlbuild/compiler/compile/_helpers/assembly/semantic_shapes.py @@ -3,15 +3,13 @@ from __future__ import annotations from dataclasses import replace -from typing import Any, cast +from typing import Any from sqlbuild.adapter.contract.models import ExpressionInferenceProfile -from sqlbuild.compiler.compile._helpers.analysis.columns import table_function_analysis_name -from sqlbuild.compiler.compile._helpers.analysis.compact import ( - NativeCompactAnalysis, - analyze_columns_and_lineage_with_polyglot, - analyze_queries_with_compact_polyglot_batch, +from sqlbuild.compiler.analysis_session.main._infer_native_expression_source_shapes import ( + infer_native_expression_source_shapes, ) +from sqlbuild.compiler.compile._helpers.analysis.reference_names import table_function_analysis_name from sqlbuild.compiler.compile.constants import NOT_NULL_AUDIT_NAME from sqlbuild.compiler.compile.models import ( CompiledModel, @@ -19,7 +17,6 @@ CompileModelInput, CompileProjectInputs, CompileSqlReference, - PolyglotAnalysisResult, ) from sqlbuild.compiler.lineage.types import InferredNullability from sqlbuild.compiler.planner.constants import ( @@ -30,7 +27,6 @@ from sqlbuild.compiler.references.types import SqlReferenceKind from sqlbuild.compiler.sql_analysis.constants import ( CASE_SENSITIVE_BINDING_DIALECTS, - NATIVE_DIALECT_ALIASES, ) from sqlbuild.compiler.sql_analysis.main._binding_catalog import create_binding_catalog from sqlbuild.compiler.sql_analysis.main._normalize_analysis import normalize_analysis_sql @@ -258,7 +254,7 @@ def semantic_shapes( } elif entry.expression: expression_sources.append((source.name, entry.expression)) - source_shapes: tuple[dict[str, str] | None, ...] = get_expression_source_shapes( + source_shapes: tuple[dict[str, str] | None, ...] = infer_native_expression_source_shapes( expressions=tuple(expression for _, expression in expression_sources), profile=profile ) for (source_name, _), source_shape in zip(expression_sources, source_shapes, strict=True): @@ -316,67 +312,6 @@ def semantic_shapes( return shapes -def get_expression_source_shapes( - *, expressions: tuple[str, ...], profile: ExpressionInferenceProfile | None -) -> tuple[dict[str, str] | None, ...]: - """Infer expression-source shapes in one native batch, reusing the compile catalog's answers.""" - effective_profile: ExpressionInferenceProfile = profile or ExpressionInferenceProfile() - effective_profile = replace( - effective_profile, - sql_analysis_dialect=NATIVE_DIALECT_ALIASES.get( - effective_profile.sql_analysis_dialect or "generic", - effective_profile.sql_analysis_dialect, - ), - ) - catalog: Any = effective_profile.binding_catalog - cache: dict[str, dict[str, str] | None] = ( - catalog.expression_shapes if catalog is not None else {} - ) - pending: tuple[str, ...] = tuple( - dict.fromkeys(expression for expression in expressions if expression not in cache) - ) - if pending: - prepared: tuple[NativeCompactAnalysis, ...] = analyze_queries_with_compact_polyglot_batch( - query_sqls=pending, - references=tuple(() for _ in pending), - placeholders=tuple(None for _ in pending), - column_nullability_by_table={}, - column_types_by_table={}, - inference_profile=effective_profile, - recover_cte_facts=tuple(True for _ in pending), - rich_type_inference=True, - ) - for expression, precomputed in zip(pending, prepared, strict=True): - cache[expression] = _expression_source_shape( - expression=expression, profile=effective_profile, precomputed=precomputed - ) - return tuple( - None if cache[expression] is None else dict(cast(dict[str, str], cache[expression])) - for expression in expressions - ) - - -def _expression_source_shape( - *, expression: str, profile: ExpressionInferenceProfile, precomputed: NativeCompactAnalysis -) -> dict[str, str] | None: - analysis: PolyglotAnalysisResult = analyze_columns_and_lineage_with_polyglot( - query_sql=expression, - references=(), - inference_profile=profile, - allow_compact_analysis=True, - recover_cte_facts=True, - precomputed=precomputed, - ) - if not analysis.columns or analysis.has_star: - return None - return inferred_binding_shape( - sql=expression, - profile=profile, - columns={column.name: column.type or "UNKNOWN" for column in analysis.columns}, - inputs={}, - ) - - def referenced_model_names( *, model_input: CompileModelInput, available_names: frozenset[str] | None = None ) -> tuple[str, ...]: diff --git a/src/sqlbuild/compiler/compile/_helpers/assembly/source_bindings.py b/src/sqlbuild/compiler/compile/_helpers/assembly/source_bindings.py index df2eb07e2d..5fdc739a92 100644 --- a/src/sqlbuild/compiler/compile/_helpers/assembly/source_bindings.py +++ b/src/sqlbuild/compiler/compile/_helpers/assembly/source_bindings.py @@ -7,8 +7,11 @@ from typing import Any from sqlbuild.adapter.contract.models import ColumnInfo, ExpressionInferenceProfile -from sqlbuild.compiler.compile._helpers.analysis.compact import ( - analyze_columns_and_lineage_with_polyglot, +from sqlbuild.compiler.analysis_session.main._infer_native_query_columns import ( + infer_native_query_columns, +) +from sqlbuild.compiler.analysis_session.models import NativeColumnQuery, NativeQueryColumns +from sqlbuild.compiler.compile._helpers.analysis.binding_requests import ( get_complete_schema_binding_request, ) from sqlbuild.compiler.compile._helpers.assembly.binding_positions import ( @@ -32,7 +35,6 @@ CompiledProject, CompiledSqlExpansion, CompilerDiagnostic, - PolyglotAnalysisResult, ) from sqlbuild.compiler.compile.types import ( CompiledResourceType, @@ -125,16 +127,19 @@ def get_source_binding_diagnostics( table: dict.fromkeys(shape, InferredNullability.UNKNOWN) for table, shape in inputs.items() } - analysis: PolyglotAnalysisResult = analyze_columns_and_lineage_with_polyglot( - query_sql=model.query_sql, - references=model.references, - placeholders=_placeholders(model), + analysis: NativeQueryColumns = infer_native_query_columns( + queries=( + NativeColumnQuery( + sql=model.query_sql, + mode="reanalysis", + placeholders=_placeholders(model), + references=model.references, + ), + ), + profile=profile, column_types_by_table=inputs, column_nullability_by_table=nullability, - inference_profile=profile, - allow_compact_analysis=True, - recover_cte_facts=True, - ) + )[0] if analysis.columns and (not analysis.has_star or all(inputs.values())): shapes[model.name] = published_model_shape( sql=model.query_sql, diff --git a/src/sqlbuild/compiler/compile/_helpers/assembly/targets.py b/src/sqlbuild/compiler/compile/_helpers/assembly/targets.py index 28bd9e7bed..8912228100 100644 --- a/src/sqlbuild/compiler/compile/_helpers/assembly/targets.py +++ b/src/sqlbuild/compiler/compile/_helpers/assembly/targets.py @@ -2,13 +2,7 @@ from __future__ import annotations -from sqlbuild.compiler.compile._helpers.config.namespace_validation import ( - validate_preserved_logical_namespace, -) -from sqlbuild.compiler.compile._helpers.render.templating import expand_template_data -from sqlbuild.compiler.compile.constants import PRESERVE_TARGET_VALUE from sqlbuild.compiler.compile.models import CompiledRelationLocation, CompileModelInput -from sqlbuild.spec.contracts.models import DefaultsConfig, SchemaSeedEntry, TargetConfig def build_model_relation_target( @@ -30,181 +24,3 @@ def build_model_relation_target( logical_schema=model_input.config.logical_schema, logical_database=model_input.config.logical_database, ) - - -def build_seed_relation_target( - *, - seed_entry: SchemaSeedEntry, - defaults: DefaultsConfig, - target_config: TargetConfig | None, - effective_vars: dict[str, object], -) -> CompiledRelationLocation: - """Resolve one seed's target-aware physical and logical destination.""" - - logical_namespace: tuple[str | None, str | None] = _resolve_seed_logical_namespace( - defaults=defaults, - effective_vars=effective_vars, - ) - logical_database: str | None = logical_namespace[0] - logical_schema: str | None = logical_namespace[1] - if seed_entry.database is not None: - logical_database = _expand_seed_target_value( - raw_value=seed_entry.database, - seed_name=seed_entry.name, - database=logical_database, - schema=logical_schema, - effective_vars=effective_vars, - context_label=f"seed '{seed_entry.name}' database", - ) - if seed_entry.schema is not None: - logical_schema = _expand_seed_target_value( - raw_value=seed_entry.schema, - seed_name=seed_entry.name, - database=logical_database, - schema=logical_schema, - effective_vars=effective_vars, - context_label=f"seed '{seed_entry.name}' schema", - ) - validate_preserved_logical_namespace( - resource_label=f"Seed '{seed_entry.name}'", - logical_database=logical_database, - logical_schema=logical_schema, - target_config=target_config, - ) - database, schema = _apply_seed_target_overrides( - logical_database=logical_database, - logical_schema=logical_schema, - target_config=target_config, - effective_vars=effective_vars, - ) - return CompiledRelationLocation( - database=database, - schema=schema, - name=seed_entry.name, - qualified_name=None, - logical_database=logical_database, - logical_schema=logical_schema, - ) - - -def _resolve_seed_logical_namespace( - *, - defaults: DefaultsConfig, - effective_vars: dict[str, object], -) -> tuple[str | None, str | None]: - database: str | None = _expand_seed_default_value( - raw_value=( - defaults.seed_database if defaults.seed_database is not None else defaults.database - ), - effective_vars=effective_vars, - context_label="default seed database", - ) - schema: str | None = _expand_seed_default_value( - raw_value=defaults.seed_schema if defaults.seed_schema is not None else defaults.schema, - effective_vars=effective_vars, - context_label="default seed schema", - ) - return database, schema - - -def _apply_seed_target_overrides( - *, - logical_database: str | None, - logical_schema: str | None, - target_config: TargetConfig | None, - effective_vars: dict[str, object], -) -> tuple[str | None, str | None]: - if target_config is None: - return logical_database, logical_schema - database: str | None = logical_database - schema: str | None = logical_schema - if target_config.database is not None and target_config.database != PRESERVE_TARGET_VALUE: - database = _expand_seed_environment_value( - raw_value=target_config.database, - effective_vars=effective_vars, - context_label="target database", - ) - if target_config.schema is not None and target_config.schema != PRESERVE_TARGET_VALUE: - schema = _expand_seed_environment_value( - raw_value=target_config.schema, - effective_vars=effective_vars, - context_label="target schema", - ) - return database, schema - - -def _expand_seed_default_value( - *, raw_value: str | None, effective_vars: dict[str, object], context_label: str -) -> str | None: - if raw_value is None: - return None - return _expand_seed_environment_value( - raw_value=raw_value, - effective_vars=effective_vars, - context_label=context_label, - ) - - -def _expand_seed_environment_value( - *, raw_value: str, effective_vars: dict[str, object], context_label: str -) -> str | None: - if raw_value == PRESERVE_TARGET_VALUE: - return None - return str( - expand_template_data( - value=raw_value, - variables=effective_vars, - context_values={}, - context_label=context_label, - allow_context=False, - preserve_context_tokens=False, - preserve_unknown_context=False, - ) - ) - - -def _expand_seed_target_value( - *, - raw_value: str, - seed_name: str, - database: str | None, - schema: str | None, - effective_vars: dict[str, object], - context_label: str, -) -> str | None: - if raw_value == PRESERVE_TARGET_VALUE: - return None - return str( - expand_template_data( - value=raw_value, - variables=effective_vars, - context_values={ - "model.name": seed_name, - "model.database": database, - "model.schema": schema, - "model.alias": seed_name, - "destination.database": database, - "destination.schema": schema, - "destination.table": seed_name, - "destination.qualified": _build_seed_destination_qualified_context( - database=database, - schema=schema, - name=seed_name, - ), - }, - context_label=context_label, - allow_context=True, - preserve_context_tokens=False, - preserve_unknown_context=False, - ) - ) - - -def _build_seed_destination_qualified_context( - *, database: str | None, schema: str | None, name: str -) -> str | None: - if database is not None and schema is not None: - return f"{database}.{schema}.{name}" - if schema is not None: - return f"{schema}.{name}" - return None diff --git a/src/sqlbuild/compiler/compile/_helpers/attachment/audits.py b/src/sqlbuild/compiler/compile/_helpers/attachment/audits.py index 1013e3e9fe..4f063906f9 100644 --- a/src/sqlbuild/compiler/compile/_helpers/attachment/audits.py +++ b/src/sqlbuild/compiler/compile/_helpers/attachment/audits.py @@ -69,8 +69,6 @@ DiscoveredAuditFile, DiscoveredProjectInputs, ) -from sqlbuild.compiler.frontier.main.report_native_answer import report_native_answer -from sqlbuild.compiler.frontier.types import NativeStage from sqlbuild.compiler.references.types import SqlReferenceKind from sqlbuild.compiler.scopes.models import ( DeclarationIdentity, @@ -653,7 +651,6 @@ def build_attached_audit_input( explicit_arguments=audit_instance.arguments, policies=_native_audit_policies(audit_instance=audit_instance, context=context), ) - report_native_answer(stage=NativeStage.ATTACHMENTS, kind="audit_renderings") if native_rendering.render_error is not None: raise CompileInputError(native_rendering.render_error) rendered_sql_body: str = native_rendering.sql_body diff --git a/src/sqlbuild/compiler/compile/_helpers/attachment/core.py b/src/sqlbuild/compiler/compile/_helpers/attachment/core.py index c3f33a7fe7..fd6285d374 100644 --- a/src/sqlbuild/compiler/compile/_helpers/attachment/core.py +++ b/src/sqlbuild/compiler/compile/_helpers/attachment/core.py @@ -127,9 +127,6 @@ PythonHookEntry, SqlHookEntry, ) -from sqlbuild.compiler.frontier.main.native_stage_enabled import native_stage_enabled -from sqlbuild.compiler.frontier.main.report_native_answer import report_native_answer -from sqlbuild.compiler.frontier.types import NativeStage from sqlbuild.compiler.model_loop.main._scan_native_declaration_references import ( scan_native_declaration_references, ) @@ -524,9 +521,6 @@ def _build_model_inputs( for model_file in render_files if interpolations[model_file.file_path].error is None ) - report_native_answer( - stage=NativeStage.MODEL_LOOP, kind="variable_substitutions", units=len(prepared_files) - ) loop: _ModelInputLoop = _ModelInputLoop( discovered_inputs=discovered_inputs, context=context, @@ -666,7 +660,6 @@ def _build_model_input( value_renderer=context.value_renderer, collection_rendering=context.collection_rendering, ) - report_native_answer(stage=NativeStage.MODEL_LOOP, kind="declaration_expansions") declaration_expanded_sql: str = declaration_expansion.sql try: macro_expansion: MacroExpansionResult = expand_sql_macros_result( @@ -1103,34 +1096,9 @@ def build_seed_inputs(discovered_inputs: DiscoveredProjectInputs) -> tuple[Compi for seed_entry in schema_file.seed_entries: seed_declarations.append((seed_entry, schema_file)) - if native_stage_enabled(NativeStage.ATTACHMENTS): - return _native_seed_inputs( - seed_declarations=seed_declarations, seed_files=discovered_inputs.seed_files - ) - seed_files_by_name: dict[str, DiscoveredSeedFile] = { - seed_file.file_path.stem: seed_file for seed_file in discovered_inputs.seed_files - } - - seed_inputs: list[CompileSeedInput] = [] - seed_entry: SchemaSeedEntry - seed_schema_file: DiscoveredSchemaFile - for seed_entry, seed_schema_file in seed_declarations: - seed_file: DiscoveredSeedFile | None = seed_files_by_name.get(seed_entry.name) - if seed_file is None: - raise CompileInputError( - f"Seed declaration '{seed_entry.name}' in {seed_schema_file.relative_path} " - "has no matching CSV file under seeds/" - ) - - seed_inputs.append( - CompileSeedInput( - seed_file=seed_file, - schema_entry=seed_entry, - schema_file=seed_schema_file, - ) - ) - - return tuple(seed_inputs) + return _native_seed_inputs( + seed_declarations=seed_declarations, seed_files=discovered_inputs.seed_files + ) def _native_seed_inputs( @@ -1150,7 +1118,6 @@ def _native_seed_inputs( f"Seed declaration '{seed_entry.name}' in {seed_schema_file.relative_path} " "has no matching CSV file under seeds/", ) - report_native_answer(stage=NativeStage.ATTACHMENTS, kind="seed_pairs", units=len(pairs)) return tuple( CompileSeedInput( seed_file=seed_files[file_index], diff --git a/src/sqlbuild/compiler/compile/_helpers/attachment/declaration_scope.py b/src/sqlbuild/compiler/compile/_helpers/attachment/declaration_scope.py index 8d718c5ef0..6ae2824615 100644 --- a/src/sqlbuild/compiler/compile/_helpers/attachment/declaration_scope.py +++ b/src/sqlbuild/compiler/compile/_helpers/attachment/declaration_scope.py @@ -24,8 +24,6 @@ LoadedMacro, ) from sqlbuild.compiler.discovery.models import DiscoveredProjectInputs -from sqlbuild.compiler.frontier.main.report_native_answer import report_native_answer -from sqlbuild.compiler.frontier.types import NativeStage from sqlbuild.compiler.scopes.classes.native_scope_index import NativeScopeIndex from sqlbuild.compiler.scopes.exceptions import ScopeValidationError from sqlbuild.compiler.scopes.main._open_native_scope_index import open_native_scope_index @@ -90,7 +88,6 @@ def _build_native_declaration_scope( native.grant(facts) index: ScopeIndex = native.index_with_relationships() lookup: ScopeLookup = native.lookup(index=index) - report_native_answer(stage=NativeStage.DECLARATION_SCOPES, kind="scope_indexes") return DeclarationScopeBuild( loaded_macros=loaded_macros, index=index, diff --git a/src/sqlbuild/compiler/compile/_helpers/attachment/functions.py b/src/sqlbuild/compiler/compile/_helpers/attachment/functions.py index 2d6365c585..78ea48e8a6 100644 --- a/src/sqlbuild/compiler/compile/_helpers/attachment/functions.py +++ b/src/sqlbuild/compiler/compile/_helpers/attachment/functions.py @@ -7,6 +7,11 @@ from typing import cast import sqlbuild._native as _native +from sqlbuild.adapter.contract.models import ExpressionInferenceProfile +from sqlbuild.compiler.analysis_session.main._infer_native_query_columns import ( + infer_native_query_columns, +) +from sqlbuild.compiler.analysis_session.models import NativeColumnQuery from sqlbuild.compiler.attachments.constants import ( HEADER_ARGUMENTS_STAGE, HEADER_METADATA_STAGE, @@ -25,7 +30,6 @@ NativeFunctionNamespace, NativeFunctionNamespaceInputs, ) -from sqlbuild.compiler.compile._helpers.analysis.compact import infer_columns_with_sql_analysis from sqlbuild.compiler.compile._helpers.analysis.validation import ( validate_function_sql_syntax, ) @@ -72,8 +76,6 @@ DiscoveredPythonFunctionFile, DiscoveredSqlFunctionFile, ) -from sqlbuild.compiler.frontier.main.report_native_answer import report_native_answer -from sqlbuild.compiler.frontier.types import NativeStage from sqlbuild.compiler.scopes.models import ResourceIdentity from sqlbuild.compiler.scopes.types import ResourceKind from sqlbuild.compiler.sql_analysis.models import SqlLexicalSyntax @@ -317,7 +319,6 @@ def _sql_function_header( python=False, relative_path=function_file.relative_path, ) - report_native_answer(stage=NativeStage.ATTACHMENTS, kind="function_headers") _raise_header_failure(header=native_header, stage=HEADER_START_STAGE) arguments: tuple[FunctionArgument, ...] = _expanded_native_arguments( header=native_header, @@ -407,9 +408,10 @@ def _validate_table_function_output_contract( return_columns: tuple[FunctionReturnColumn, ...], function_file: DiscoveredSqlFunctionFile, ) -> None: - inferred_columns: tuple[InferredColumn, ...] | None = infer_columns_with_sql_analysis( - query_sql=body_sql - ) + inferred_columns: tuple[InferredColumn, ...] | None = infer_native_query_columns( + queries=(NativeColumnQuery(sql=body_sql, mode="parse"),), + profile=ExpressionInferenceProfile(), + )[0].columns if not inferred_columns: return declared_count: int = len(return_columns) @@ -435,7 +437,6 @@ def _build_python_function_input( python=True, relative_path=python_function_file.relative_path, ) - report_native_answer(stage=NativeStage.ATTACHMENTS, kind="function_headers") _raise_header_failure(header=native_header, stage=HEADER_START_STAGE) arguments: tuple[FunctionArgument, ...] = _expanded_native_arguments( header=native_header, diff --git a/src/sqlbuild/compiler/compile/_helpers/attachment/model_config.py b/src/sqlbuild/compiler/compile/_helpers/attachment/model_config.py index 409ae03a68..be34fdd96c 100644 --- a/src/sqlbuild/compiler/compile/_helpers/attachment/model_config.py +++ b/src/sqlbuild/compiler/compile/_helpers/attachment/model_config.py @@ -51,8 +51,6 @@ PythonHookEntry, SqlHookEntry, ) -from sqlbuild.compiler.frontier.main.report_native_answer import report_native_answer -from sqlbuild.compiler.frontier.types import NativeStage from sqlbuild.compiler.model_config.main._native_config_error import native_config_error from sqlbuild.compiler.model_config.main._parse_native_header_metadata import ( parse_native_header_metadata, @@ -238,7 +236,6 @@ def build_model_header_schema_entry( column_locations=column_locations or {}, file_path=file_path, ) - report_native_answer(stage=NativeStage.MODEL_CONFIG, kind="header_metadata_parses") if native.columns_error is not None: raise native_config_error(error=native.columns_error) local_columns: tuple[SchemaColumn, ...] = native.columns @@ -706,7 +703,6 @@ def build_native_model_config( built: _BuiltConfig | _native.NativeConfigError = session.builder.build( model_file.header_values, matched_path_default, model_file.file_path.stem ) - report_native_answer(stage=NativeStage.MODEL_CONFIG, kind="config_builds") if isinstance(built, _native.NativeConfigError): raise native_config_error(error=built) values, header_keys, namespace, overrides, reads = built @@ -800,7 +796,6 @@ def validate_model_config( request=request, rejected=[error is not None for error in external_errors], ) - report_native_answer(stage=NativeStage.MODEL_CONFIG, kind="validations") _raise_validation_outcome( outcome=outcome, external_errors=external_errors, values=request.config.values ) diff --git a/src/sqlbuild/compiler/compile/_helpers/attachment/scope_relationships.py b/src/sqlbuild/compiler/compile/_helpers/attachment/scope_relationships.py index 6c9669aff8..b248915873 100644 --- a/src/sqlbuild/compiler/compile/_helpers/attachment/scope_relationships.py +++ b/src/sqlbuild/compiler/compile/_helpers/attachment/scope_relationships.py @@ -33,8 +33,6 @@ ) from sqlbuild.compiler.compile.types import SqlTestMode from sqlbuild.compiler.discovery.models import DiscoveredProjectInputs, DiscoveredSqlTestFile -from sqlbuild.compiler.frontier.main.report_native_answer import report_native_answer -from sqlbuild.compiler.frontier.types import NativeStage from sqlbuild.compiler.scopes.main._native_expected_model_names import ( native_expected_model_names, ) @@ -151,11 +149,6 @@ def extract_scope_relationship_facts( scenario=True, syntax=sql_lexical_syntax, ) - report_native_answer( - stage=NativeStage.DECLARATION_SCOPES, - kind="relationship_scans", - units=len(scenario_names) + len(macro_blocks), - ) for scenario, scanned in zip(discovered_inputs.scenario_files, scenario_names, strict=True): if isinstance(scanned, str): faults.append(ScopeRelationshipFault(scenario.relative_path, scanned)) @@ -290,9 +283,6 @@ def _scanned_expected_names( scenario=False, syntax=syntax, ) - report_native_answer( - stage=NativeStage.DECLARATION_SCOPES, kind="relationship_scans", units=len(scanned) - ) return { position: CompileInputError(names) if isinstance(names, str) else names for position, names in zip(pending, scanned, strict=True) diff --git a/src/sqlbuild/compiler/compile/_helpers/attachment/sql_tests.py b/src/sqlbuild/compiler/compile/_helpers/attachment/sql_tests.py index c26f1fb311..512861d990 100644 --- a/src/sqlbuild/compiler/compile/_helpers/attachment/sql_tests.py +++ b/src/sqlbuild/compiler/compile/_helpers/attachment/sql_tests.py @@ -84,8 +84,6 @@ DiscoveredSqlTestFile, EnumDeclaration, ) -from sqlbuild.compiler.frontier.main.native_stage_enabled import native_stage_enabled -from sqlbuild.compiler.frontier.types import NativeStage from sqlbuild.compiler.profiling.main.record import record_compile_timing from sqlbuild.compiler.references.types import ExternalSqlReferenceResolver, SqlReferenceKind from sqlbuild.compiler.scopes.models import ( @@ -327,16 +325,12 @@ def build_test_inputs( test_block=failed.test_block, sql=failed.sql_body, ) from None - target_catalog: _native.SqlTestTargetCatalog | None = ( - native_test_target_catalog( - models=known_model_names, - sources=known_source_names, - seeds=known_seed_names, - table_functions=known_table_function_names, - macros=loaded_macros, - ) - if native_stage_enabled(NativeStage.ATTACHMENTS) - else None + target_catalog: _native.SqlTestTargetCatalog = native_test_target_catalog( + models=known_model_names, + sources=known_source_names, + seeds=known_seed_names, + table_functions=known_table_function_names, + macros=loaded_macros, ) for test, test_ctes in zip(expanded_tests, test_ctes_batch, strict=True): assertion_target_model_names: tuple[str, ...] = ( @@ -700,10 +694,8 @@ def build_scenario_inputs( ) ) scenario_inputs: list[CompileSqlScenarioInput] = [] - source_catalog: _native.SqlTestTargetCatalog | None = ( - native_test_target_catalog(sources=known_source_names) - if native_stage_enabled(NativeStage.ATTACHMENTS) - else None + source_catalog: _native.SqlTestTargetCatalog = native_test_target_catalog( + sources=known_source_names ) scenario_file: DiscoveredSqlScenarioFile for scenario_file in discovered_inputs.scenario_files: @@ -792,49 +784,19 @@ def _validate_scenario_source_references( syntax: SqlLexicalSyntax, target_catalog: _native.SqlTestTargetCatalog | None = None, ) -> None: - if native_stage_enabled(NativeStage.ATTACHMENTS): - cte_sources: list[tuple[str, bool, list[str]]] - extraction_error: CompileInputError | None - cte_sources, extraction_error = _scenario_cte_sources( - scenario_ctes=scenario_ctes, scenario_file=scenario_file, syntax=syntax - ) - error: str | None = ( - target_catalog or native_test_target_catalog(sources=known_source_names) - ).scenario_source_error(str(scenario_file.relative_path), cte_sources) - if error is not None: - raise CompileInputError(error) - if extraction_error is not None: - raise extraction_error - return - cte: CompileSqlScenarioCte - for cte in (*scenario_ctes.expected_ctes, *scenario_ctes.assertion_ctes): - references: tuple[CompileSqlReference, ...] = extract_sql_references( - sql=cte.sql_body, syntax=syntax, origin=_sql_file_reference_origin(scenario_file) - ) - reference: CompileSqlReference - for reference in references: - if reference.ref_kind != SqlReferenceKind.SOURCE: - continue - raise CompileInputError( - f"SQL scenario file {scenario_file.relative_path} CTE '{cte.name}' must not " - f"reference project source '{reference.ref_name}' with " - f"{SqlReferenceKind.SOURCE.placeholder_call()}; source-backed scenario data " - "is only allowed in helper and fixture CTEs" - ) - - for cte in scenario_ctes.authored_ctes: - references = extract_sql_references( - sql=cte.sql_body, syntax=syntax, origin=_sql_file_reference_origin(scenario_file) - ) - for reference in references: - if reference.ref_kind != SqlReferenceKind.SOURCE: - continue - if reference.ref_name in known_source_names: - continue - raise CompileInputError( - f"SQL scenario file {scenario_file.relative_path} references unknown source " - f"'{reference.ref_name}'" - ) + cte_sources: list[tuple[str, bool, list[str]]] + extraction_error: CompileInputError | None + cte_sources, extraction_error = _scenario_cte_sources( + scenario_ctes=scenario_ctes, scenario_file=scenario_file, syntax=syntax + ) + error: str | None = ( + target_catalog or native_test_target_catalog(sources=known_source_names) + ).scenario_source_error(str(scenario_file.relative_path), cte_sources) + if error is not None: + raise CompileInputError(error) + if extraction_error is not None: + raise extraction_error + return def _scenario_cte_sources( @@ -889,73 +851,25 @@ def validate_test_ctes( return model_payload: CompileModelSqlTestCtes = test_ctes.payload - if native_stage_enabled(NativeStage.ATTACHMENTS): - catalog: _native.SqlTestTargetCatalog = target_catalog or native_test_target_catalog( - models=known_model_names, - sources=known_source_names, - seeds=known_seed_names, - table_functions=known_table_function_names, - macros=loaded_macros, - ) - error: str | None = catalog.unknown_test_target( - str(test_file.relative_path), - ( - [*model_payload.mock_model_names], - [*model_payload.mock_source_names], - [*model_payload.mock_seed_names], - [*model_payload.mock_table_function_names], - [*model_payload.macro_mocks], - [*model_payload.expected_model_names], - [*assertion_target_model_names], - ), - ) - if error is not None: - raise CompileInputError(error) - return - - mock_model_name: str - for mock_model_name in model_payload.mock_model_names: - if mock_model_name not in known_model_names: - raise CompileInputError( - f"SQL test file {test_file.relative_path} mocks unknown model '{mock_model_name}'" - ) - mock_source_name: str - for mock_source_name in model_payload.mock_source_names: - if mock_source_name not in known_source_names: - raise CompileInputError( - f"SQL test file {test_file.relative_path} mocks unknown source '{mock_source_name}'" - ) - mock_seed_name: str - for mock_seed_name in model_payload.mock_seed_names: - if mock_seed_name not in known_seed_names: - raise CompileInputError( - f"SQL test file {test_file.relative_path} mocks unknown seed '{mock_seed_name}'" - ) - mock_table_function_name: str - for mock_table_function_name in model_payload.mock_table_function_names: - if mock_table_function_name not in known_table_function_names: - raise CompileInputError( - f"SQL test file {test_file.relative_path} mocks unknown table function " - f"'{mock_table_function_name}'" - ) - macro_mock_name: str - for macro_mock_name in model_payload.macro_mocks: - if macro_mock_name not in loaded_macros: - raise CompileInputError( - f"SQL test file {test_file.relative_path} mocks unknown macro '{macro_mock_name}'" - ) - expected_model_name: str - for expected_model_name in model_payload.expected_model_names: - if expected_model_name not in known_model_names: - raise CompileInputError( - f"SQL test file {test_file.relative_path} expects unknown model " - f"'{expected_model_name}'" - ) - - assertion_target_name: str - for assertion_target_name in assertion_target_model_names: - if assertion_target_name not in known_model_names: - raise CompileInputError( - f"SQL test file {test_file.relative_path} assertion references unknown model " - f"'{assertion_target_name}'" - ) + catalog: _native.SqlTestTargetCatalog = target_catalog or native_test_target_catalog( + models=known_model_names, + sources=known_source_names, + seeds=known_seed_names, + table_functions=known_table_function_names, + macros=loaded_macros, + ) + error: str | None = catalog.unknown_test_target( + str(test_file.relative_path), + ( + [*model_payload.mock_model_names], + [*model_payload.mock_source_names], + [*model_payload.mock_seed_names], + [*model_payload.mock_table_function_names], + [*model_payload.macro_mocks], + [*model_payload.expected_model_names], + [*assertion_target_model_names], + ), + ) + if error is not None: + raise CompileInputError(error) + return diff --git a/src/sqlbuild/compiler/compile/_helpers/attachment/target.py b/src/sqlbuild/compiler/compile/_helpers/attachment/target.py index 384a535141..4bbb400d85 100644 --- a/src/sqlbuild/compiler/compile/_helpers/attachment/target.py +++ b/src/sqlbuild/compiler/compile/_helpers/attachment/target.py @@ -19,7 +19,7 @@ from sqlbuild.compiler.discovery.models import DiscoveredProjectInputs from sqlbuild.compiler.frontier.constants import ( COMPILER_CACHE_DIRECTORY_NAME, - ENGINE_CACHE_NAMESPACE_SUFFIXES, + RETIRED_CACHE_NAMESPACE_SUFFIXES, ) from sqlbuild.compiler.frontier.main.compiler_cache_directory import compiler_cache_directory from sqlbuild.spec.contracts.main.resolve_target_config import resolve_target_config @@ -77,7 +77,7 @@ def compile_cache_root( def _remove_retired_fact_caches(*, root: Path) -> None: """Delete the per-file fact caches older releases kept under every engine's compiler root.""" - for suffix in ENGINE_CACHE_NAMESPACE_SUFFIXES.values(): + for suffix in RETIRED_CACHE_NAMESPACE_SUFFIXES: retired: Path = ( root.parent / f"{COMPILER_CACHE_DIRECTORY_NAME}{suffix}" diff --git a/src/sqlbuild/compiler/compile/_helpers/deps/dependencies.py b/src/sqlbuild/compiler/compile/_helpers/deps/dependencies.py deleted file mode 100644 index ab9bafd3d6..0000000000 --- a/src/sqlbuild/compiler/compile/_helpers/deps/dependencies.py +++ /dev/null @@ -1,133 +0,0 @@ -"""Dependency key derivation helpers for compiled resources.""" - -from __future__ import annotations - -from collections.abc import Iterable - -from sqlbuild.compiler.compile.models import ( - CompiledObjectKey, - CompileSqlReference, -) -from sqlbuild.compiler.compile.types import ( - AttachedAuditTargetKind, - CompiledResourceType, -) -from sqlbuild.compiler.references.types import SqlReferenceKind - - -def model_build_deps( - *, - references: tuple[CompileSqlReference, ...], - seed_names: frozenset[str] = frozenset(), -) -> tuple[CompiledObjectKey, ...]: - """Return build graph dependencies implied by model SQL references.""" - - if not references: - return () - if len(references) == 1: - return (_reference_dep(reference=references[0], seed_names=seed_names),) - return _dedupe_object_keys( - _reference_dep(reference=reference, seed_names=seed_names) for reference in references - ) - - -def function_build_deps( - *, - references: tuple[CompileSqlReference, ...], - seed_names: frozenset[str] = frozenset(), -) -> tuple[CompiledObjectKey, ...]: - """Return build graph dependencies implied by function SQL references.""" - - if not references: - return () - if len(references) == 1: - return (_reference_dep(reference=references[0], seed_names=seed_names),) - return _dedupe_object_keys( - _reference_dep(reference=reference, seed_names=seed_names) for reference in references - ) - - -def audit_scope_deps( - *, - references: tuple[CompileSqlReference, ...], - attached_target_kind: AttachedAuditTargetKind | str | None, - attached_target_name: str | None, -) -> tuple[CompiledObjectKey, ...]: - """Return resources that select or gate an audit.""" - - deps: list[CompiledObjectKey] = list(model_build_deps(references=references)) - if attached_target_kind is not None and attached_target_name is not None: - deps.append( - CompiledObjectKey( - resource_type=AttachedAuditTargetKind(attached_target_kind).resource_type, - name=attached_target_name, - ) - ) - return _dedupe_object_keys(deps) - - -def sql_test_scope_deps(*, expected_model_names: tuple[str, ...]) -> tuple[CompiledObjectKey, ...]: - """Return model names that select a SQL-native unit test.""" - - if not expected_model_names: - return () - if len(expected_model_names) == 1: - return ( - CompiledObjectKey( - resource_type=CompiledResourceType.MODEL, name=expected_model_names[0] - ), - ) - return _dedupe_object_keys( - CompiledObjectKey(resource_type=CompiledResourceType.MODEL, name=model_name) - for model_name in expected_model_names - ) - - -def _reference_dep( - *, reference: CompileSqlReference, seed_names: frozenset[str] = frozenset() -) -> CompiledObjectKey: - if reference.ref_kind == SqlReferenceKind.SOURCE: - return CompiledObjectKey( - resource_type=CompiledResourceType.SOURCE, - name=reference.ref_name, - ) - if reference.ref_kind == SqlReferenceKind.SEED: - return CompiledObjectKey( - resource_type=CompiledResourceType.SEED, - name=reference.ref_name, - ) - if reference.ref_kind == SqlReferenceKind.DBT_REF: - return CompiledObjectKey( - resource_type=CompiledResourceType.DBT_REF, - name=( - f"{reference.ref_package}.{reference.ref_name}" - if reference.ref_package is not None - else reference.ref_name - ), - ) - if reference.ref_kind == SqlReferenceKind.UDF: - return CompiledObjectKey( - resource_type=CompiledResourceType.UDF, - name=reference.ref_name, - ) - if reference.ref_kind == SqlReferenceKind.TABLE_FUNCTION: - return CompiledObjectKey( - resource_type=CompiledResourceType.TABLE_FN, - name=reference.ref_name, - ) - return CompiledObjectKey( - resource_type=CompiledResourceType.MODEL, - name=reference.ref_name, - ) - - -def _dedupe_object_keys(keys: Iterable[CompiledObjectKey]) -> tuple[CompiledObjectKey, ...]: - deduped_keys: list[CompiledObjectKey] = [] - seen_keys: set[CompiledObjectKey] = set() - key: CompiledObjectKey - for key in keys: - if key in seen_keys: - continue - seen_keys.add(key) - deduped_keys.append(key) - return tuple(deduped_keys) diff --git a/src/sqlbuild/compiler/compile/_helpers/diagnostics/details.py b/src/sqlbuild/compiler/compile/_helpers/diagnostics/details.py index 20fd94da22..86257468d3 100644 --- a/src/sqlbuild/compiler/compile/_helpers/diagnostics/details.py +++ b/src/sqlbuild/compiler/compile/_helpers/diagnostics/details.py @@ -1,57 +1,13 @@ -"""Explain semantic diagnostics using the query's actual input schemas.""" +"""Column suggestions and unknown-column parsing for resource SQL diagnostics.""" from __future__ import annotations import re -from bisect import bisect_right -from dataclasses import replace from typing import Any -from sqlbuild.compiler.compile._helpers.analysis.compact import get_complete_schema_binding_request -from sqlbuild.compiler.compile._helpers.assembly.semantic_shapes import semantic_shapes -from sqlbuild.compiler.compile._helpers.diagnostics.help import ( - comparison_help, - semantic_help, -) -from sqlbuild.compiler.compile.models import CompiledModel, CompiledProject, CompilerDiagnostic -from sqlbuild.compiler.compile.types import CompiledResourceType -from sqlbuild.compiler.sql_analysis.main.import_polyglot_sql import import_polyglot_sql -from sqlbuild.compiler.sql_analysis.models import SqlSchemaValidationRequest -from sqlbuild.spec.contracts.models import SourceLocation - -_UNKNOWN_COLUMN: str = "B002" -_COMPARISON: str = "B217" _MIN_ABBREVIATION_LENGTH: int = 3 _MAX_EDIT_DISTANCE: int = 2 -_DISPLAY_LIMIT: int = 10 -_QUALIFIER_SEPARATOR: str = "." -_COLUMN_KIND: str = "column" -_TYPE_CODES: frozenset[str] = frozenset(f"B21{i}" for i in range(10)) -_TYPE_WORDS: str = ( - r"\b(timestamp|integer|varchar|boolean|date|interval|double|float|decimal|numeric|" - r"bigint|smallint|text|time|string|binary|array|struct)\b" -) -type _LineIndex = tuple[tuple[str, ...], tuple[int, ...]] -type _BinaryIndex = tuple[tuple[int, ...], tuple[re.Match[str], ...]] _MISSING: re.Pattern[str] = re.compile(r"Unknown column '([^']+)'(?: in table '([^']+)')?") -_OPERAND: str = ( - r"(?:TIMESTAMP\s+'[^']*'|DATE\s+'[^']*'|'(?:[^']|'')*'|-?\d+(?:\.\d+)?|" - r"[A-Za-z_]\w*(?:\.[A-Za-z_]\w*)?)" -) -_BINARY: re.Pattern[str] = re.compile( - rf"(?P{_OPERAND})\s*(?:>=|<=|<>|!=|=|>|<|\+|\*|/|-)\s*(?P{_OPERAND})", - re.IGNORECASE, -) - - -def sentence_message(message: str) -> str: - text: str = re.sub(r" \(context: [^)]*\)$", "", message) - pieces: list[str] = re.split(r"('[^']*')", text) - for index in range(0, len(pieces), 2): - pieces[index] = re.sub( - _TYPE_WORDS, lambda match: match.group().upper(), pieces[index], flags=re.IGNORECASE - ) - return "".join(pieces) def column_distance(*, left: str, right: str) -> int: @@ -95,253 +51,3 @@ def closest_column(*, name: str, columns: dict[str, str]) -> str | None: def missing_column(message: str) -> tuple[str, str | None] | None: match: re.Match[str] | None = _MISSING.search(message) return (match.group(1), match.group(2)) if match else None - - -def input_aliases(*, model: CompiledModel, dialect: str | None) -> dict[str, str]: - parsed: Any = _parsed_model(model=model, dialect=dialect) - if parsed is None: - return {} - aliases: dict[str, set[str]] = {} - for table in parsed.find_all("table"): - value: dict[str, Any] = table.to_dict().get("table", {}) - name: str = str(value.get("name", {}).get("name", "")) - aliases.setdefault(name, set()).add(name) - alias: dict[str, Any] = value.get("alias") or {} - if alias: - aliases.setdefault(str(alias["name"]), set()).add(name) - return {alias: next(iter(names)) for alias, names in aliases.items() if len(names) == 1} - - -def unaliased_output_columns(*, model: CompiledModel, dialect: str | None) -> set[str]: - """Only an unaliased missing projection can lose its corrected output name.""" - parsed: Any = _parsed_model(model=model, dialect=dialect) - if parsed is None: - return set() - projections: list[dict[str, Any]] = parsed.to_dict().get("select", {}).get("expressions", []) - return { - str(expression["column"]["name"]["name"]) - for expression in projections - if _COLUMN_KIND in expression - } - - -def _parsed_model(*, model: CompiledModel, dialect: str | None) -> Any: - request: SqlSchemaValidationRequest = get_complete_schema_binding_request( - query_sql=model.query_sql, placeholders=None, dialect=dialect, binding_schema={} - ) - module: Any = import_polyglot_sql() - try: - return module.parse_one(request.sql, dialect=dialect) - except module.PolyglotError: - return None - - -def explain_diagnostics(project: CompiledProject) -> CompiledProject: - """Enrich errors only; successful models require no extra SQL parsing.""" - if not project.diagnostics: - return project - shapes: dict[str, dict[str, str]] = semantic_shapes(project=project) - models: dict[str, CompiledModel] = {model.name: model for model in project.models} - aliases: dict[str, dict[str, str]] = {} - line_indexes: dict[str, _LineIndex] = {} - binary_indexes: dict[str, _BinaryIndex] = {} - diagnostics: list[CompilerDiagnostic] = [] - diagnostic: CompilerDiagnostic - for diagnostic in project.diagnostics: - model: CompiledModel | None = models.get(diagnostic.resource_name or "") - if model is not None and diagnostic.code in {_UNKNOWN_COLUMN, *_TYPE_CODES}: - if model.name not in aliases: - aliases[model.name] = input_aliases( - model=model, dialect=project.sql_analysis_dialect - ) - line_indexes[model.name] = _line_index(model.authored_sql) - if diagnostic.code in _TYPE_CODES and model.name not in binary_indexes: - binary_indexes[model.name] = _binary_index(model.authored_sql) - diagnostic = _explain_model( - diagnostic=diagnostic, - model=model, - aliases=aliases[model.name], - shapes=shapes, - dialect=project.sql_analysis_dialect, - lines=line_indexes[model.name], - binaries=binary_indexes.get(model.name, ((), ())), - ) - elif semantic_help(diagnostic.code) is not None: - diagnostic = replace( - diagnostic, - message=sentence_message(diagnostic.message), - help=diagnostic.help or semantic_help(diagnostic.code), - ) - diagnostics.append(diagnostic) - return replace( - project, - diagnostics=tuple(diagnostics), - models=update_binding_models(models=project.models, diagnostics=tuple(diagnostics)), - ) - - -def update_binding_models( - *, models: tuple[CompiledModel, ...], diagnostics: tuple[CompilerDiagnostic, ...] -) -> tuple[CompiledModel, ...]: - """Keep model binding facts distinct from metadata and SQL-test diagnostics.""" - by_model: dict[str, list[CompilerDiagnostic]] = {} - for diagnostic in diagnostics: - if diagnostic.resource_type == CompiledResourceType.MODEL: - by_model.setdefault(diagnostic.resource_name or "", []).append(diagnostic) - updated: list[CompiledModel] = [] - for model in models: - codes: set[str] = {item.code for item in model.binding_diagnostics} - bindings: tuple[CompilerDiagnostic, ...] = tuple( - item for item in by_model.get(model.name, ()) if item.code in codes - ) - updated.append(replace(model, binding_diagnostics=bindings)) - return tuple(updated) - - -def _line_index(sql: str) -> _LineIndex: - """Index authored lines once per model so each diagnostic maps positions in O(log n).""" - starts: list[int] = [0] - for line in sql.splitlines(keepends=True): - starts.append(starts[-1] + len(line)) - return tuple(sql.splitlines()), tuple(starts) - - -def _binary_index(sql: str) -> _BinaryIndex: - matches: tuple[re.Match[str], ...] = tuple(_BINARY.finditer(sql)) - return tuple(match.start() for match in matches), matches - - -def _line_offset(*, lines: _LineIndex, line: int, column: int) -> int: - starts: tuple[int, ...] = lines[1] - return starts[min(max(line - 1, 0), len(starts) - 1)] + column - 1 - - -def _binary_at(*, binaries: _BinaryIndex, offset: int) -> re.Match[str] | None: - """Matches are ordered and disjoint, so only the last one starting at or before can match.""" - position: int = bisect_right(binaries[0], offset) - 1 - if position < 0: - return None - match: re.Match[str] = binaries[1][position] - return match if offset < match.end() else None - - -def _explain_model( - *, - diagnostic: CompilerDiagnostic, - model: CompiledModel, - aliases: dict[str, str], - shapes: dict[str, dict[str, str]], - dialect: str | None, - lines: _LineIndex, - binaries: _BinaryIndex, -) -> CompilerDiagnostic: - message: str = sentence_message(diagnostic.message) - help_text: str | None = semantic_help(diagnostic.code) - if diagnostic.code == _COMPARISON: - help_text = comparison_help( - types=tuple( - value.upper() - for value in re.findall(_TYPE_WORDS, diagnostic.message, re.IGNORECASE) - ), - dialect=dialect, - ) - notes: list[str] = list(diagnostic.notes) - location: SourceLocation | None = diagnostic.location - missing: tuple[str, str | None] | None = missing_column(diagnostic.message) - if missing is not None: - name, table = missing - columns: dict[str, str] = shapes.get(table or "", {}) - suggestion: str | None = closest_column(name=name, columns=columns) - help_text = f"did you mean '{suggestion}'?" if suggestion else None - message = f"Unknown column '{name}'" + (f" in {table}" if table else "") - if location is not None: - prefix: str = lines[0][location.line - 1][: location.column - 1] - qualifier: re.Match[str] | None = re.search( - r'(?:"((?:[^"]|"")+)"|([A-Za-z_]\w*))\.$', prefix - ) - alias: str | None = ( - (qualifier.group(1) or qualifier.group(2)).replace('""', '"') if qualifier else None - ) - if alias and aliases.get(alias) == table: - message += f" (as {alias})" - available: list[str] = ordered_columns(name=name, columns=columns) - if available: - suffix: str = ( - f", and {len(available) - _DISPLAY_LIMIT} more" - if len(available) > _DISPLAY_LIMIT - else "" - ) - notes.insert(0, f"{table} has: {', '.join(available[:10])}{suffix}") - if diagnostic.code in _TYPE_CODES and location is not None: - offset: int = _line_offset(lines=lines, line=location.line, column=location.column) - binary: re.Match[str] | None = _binary_at(binaries=binaries, offset=offset) - if binary: - left: str = binary.group("left") - right: str = binary.group("right") - types: tuple[str | None, str | None] = ( - _operand_type(text=left, aliases=aliases, shapes=shapes), - _operand_type(text=right, aliases=aliases, shapes=shapes), - ) - if all(types): - notes.append(f"{left} is {types[0]}, {right} is {types[1]}") - if diagnostic.code == _COMPARISON: - help_text = comparison_help( - types=tuple(value for value in types if value), dialect=dialect - ) - end: int = binary.end() - if location.end_line is not None and location.end_column is not None: - native_end: int = _line_offset( - lines=lines, line=location.end_line, column=location.end_column - ) - end = max(end, native_end) - begin: int = min(binary.start(), offset) - location = replace( - location, - line=model.authored_sql.count("\n", 0, begin) + 1, - column=begin - model.authored_sql.rfind("\n", 0, begin), - end_line=model.authored_sql.count("\n", 0, end) + 1, - end_column=end - model.authored_sql.rfind("\n", 0, end), - ) - else: - operand: re.Match[str] | None = re.compile(_OPERAND, re.IGNORECASE).match( - model.authored_sql, offset - ) - if operand: - operand_type: str | None = _operand_type( - text=operand.group(), aliases=aliases, shapes=shapes - ) - if operand_type: - notes.append(f"{operand.group()} is {operand_type}") - return replace( - diagnostic, - message=message, - help=help_text, - notes=tuple(notes), - location=location, - line=location.line if location is not None else diagnostic.line, - column=location.column if location is not None else diagnostic.column, - ) - - -def _operand_type( - *, text: str, aliases: dict[str, str], shapes: dict[str, dict[str, str]] -) -> str | None: - temporal: re.Match[str] | None = re.match(r"(TIMESTAMP|DATE)\s*'", text, re.IGNORECASE) - if temporal: - return temporal.group(1).upper() - if re.fullmatch(r"-?\d+", text): - return "INTEGER" - if re.fullmatch(r"-?\d+\.\d+", text): - return "DECIMAL" - if text.startswith("'"): - return "VARCHAR" - if _QUALIFIER_SEPARATOR in text: - alias, column = text.split(".", 1) - value: str | None = shapes.get(aliases.get(alias, alias), {}).get(column) - return value.upper() if value else None - candidates: set[str] = { - shapes[table][text].upper() - for table in set(aliases.values()) - if table in shapes and text in shapes[table] - } - return next(iter(candidates)) if len(candidates) == 1 else None diff --git a/src/sqlbuild/compiler/compile/_helpers/diagnostics/help.py b/src/sqlbuild/compiler/compile/_helpers/diagnostics/help.py index 904fa0380c..1ccfd4bf25 100644 --- a/src/sqlbuild/compiler/compile/_helpers/diagnostics/help.py +++ b/src/sqlbuild/compiler/compile/_helpers/diagnostics/help.py @@ -1,8 +1,5 @@ """Code-owned semantic remediation; no catch-all help for unrelated diagnostics.""" -_TIMESTAMP: str = "TIMESTAMP" -_DATE: str = "DATE" -_BIGQUERY: str = "bigquery" _SEMANTIC_HELP: dict[str, str] = { "B003": "qualify this column with the intended input alias", "B004": "give each referenced relation a visible alias in this scope", @@ -33,20 +30,3 @@ def semantic_help_catalogue() -> dict[str, str]: """Return the code-owned remediation catalogue.""" return dict(_SEMANTIC_HELP) - - -def semantic_help(code: str) -> str | None: - """Return help only for a code with its own remediation.""" - return _SEMANTIC_HELP.get(code) - - -def comparison_help(*, types: tuple[str, ...], dialect: str | None) -> str: - """Offer a concrete literal for a proven temporal comparison mismatch.""" - if any(_TIMESTAMP in value for value in types): - literal: str = "TIMESTAMP '2026-04-01'" - if dialect == _BIGQUERY: - literal = "TIMESTAMP '2026-04-01 00:00:00+00'" - return f"compare with a timestamp, for example {literal}" - if _DATE in types: - return "compare with a date, for example DATE '2026-04-01'" - return _SEMANTIC_HELP["B217"] diff --git a/src/sqlbuild/compiler/compile/_helpers/diagnostics/recovery.py b/src/sqlbuild/compiler/compile/_helpers/diagnostics/recovery.py index 6f5c027477..212d9a5dd2 100644 --- a/src/sqlbuild/compiler/compile/_helpers/diagnostics/recovery.py +++ b/src/sqlbuild/compiler/compile/_helpers/diagnostics/recovery.py @@ -1,44 +1,16 @@ -"""Recover poisoned output names without suppressing unrelated downstream errors.""" +"""Complete semantic diagnostics: type recovery, metadata checks, recovery and explanations.""" from __future__ import annotations -import re -from collections import Counter -from dataclasses import replace from typing import Any from sqlbuild.adapter.contract.models import ExpressionInferenceProfile -from sqlbuild.compiler.compile._helpers.assembly.metadata_validation import ( - get_semantic_metadata_diagnostics, -) -from sqlbuild.compiler.compile._helpers.assembly.semantic_shapes import semantic_shapes -from sqlbuild.compiler.compile._helpers.diagnostics.details import ( - closest_column, - explain_diagnostics, - missing_column, - unaliased_output_columns, - update_binding_models, -) -from sqlbuild.compiler.compile._helpers.diagnostics.sql_analysis_opt_outs import ( - reject_unneeded_sql_analysis_opt_outs, -) -from sqlbuild.compiler.compile._helpers.diagnostics.type_recovery import recover_output_types -from sqlbuild.compiler.compile.models import ( - CompiledModel, - CompiledProject, - CompilerDiagnostic, -) -from sqlbuild.compiler.frontier.main.native_stage_enabled import native_stage_enabled -from sqlbuild.compiler.frontier.main.report_native_answer import report_native_answer -from sqlbuild.compiler.frontier.types import NativeStage +from sqlbuild.compiler.compile.models import CompiledProject from sqlbuild.compiler.semantic_checks.main._complete_native_semantic_diagnostics import ( complete_native_semantic_diagnostics, ) from sqlbuild.compiler.sql_analysis.models import SqlBindingDiagnostic -_MISSING_CODE: str = "B002" -_TEST_CODE: str = "B302" - def complete_semantic_diagnostics( *, @@ -49,118 +21,11 @@ def complete_semantic_diagnostics( native_session: Any | None = None, ) -> CompiledProject: """Recover type facts before metadata checks, then explain retained root diagnostics.""" - if native_stage_enabled(NativeStage.SEMANTIC_CHECKS): - native_project: CompiledProject | None = complete_native_semantic_diagnostics( - project=project, - profile=profile, - binding_results=binding_results, - resource_sql_analysis=resource_sql_analysis, - session=native_session, - ) - if native_project is not None: - report_native_answer(stage=NativeStage.SEMANTIC_CHECKS, kind="semantic_completions") - return native_project - project = recover_output_types(project=project, binding_results=binding_results) - project = replace( - project, - diagnostics=( - *project.diagnostics, - *get_semantic_metadata_diagnostics( - project=project, profile=profile, resource_sql_analysis=resource_sql_analysis - ), - ), - ) - return reject_unneeded_sql_analysis_opt_outs(explain_diagnostics(recover_diagnostics(project))) - -def recover_diagnostics(project: CompiledProject) -> CompiledProject: - """Recover poisoned uses while retaining independent errors on unaffected outputs.""" - roots: list[CompilerDiagnostic] = [ - item for item in project.diagnostics if item.code == _MISSING_CODE - ] - if not roots: - return project - shapes: dict[str, dict[str, str]] = semantic_shapes(project=project) - models: dict[str, CompiledModel] = {model.name: model for model in project.models} - poisoned: dict[tuple[str, str], CompilerDiagnostic] = {} - origins: dict[CompilerDiagnostic, tuple[str, str]] = {} - projections: dict[str, set[str]] = {} - inferred_names: dict[str, set[str]] = {} - upstream_sources: dict[str, dict[str, set[tuple[str, str]]]] = {} - for diagnostic in roots: - model: CompiledModel | None = models.get(diagnostic.resource_name or "") - missing: tuple[str, str | None] | None = missing_column(diagnostic.message) - if model is None or missing is None: - continue - column, table = missing - if model.name not in inferred_names: - inferred_names[model.name] = {item.name for item in model.inferred_columns or ()} - if column not in inferred_names[model.name]: - continue - if model.name not in projections: - projections[model.name] = unaliased_output_columns( - model=model, dialect=project.sql_analysis_dialect - ) - if column not in projections[model.name]: - continue - if model.name not in upstream_sources: - upstream_sources[model.name] = _upstream_sources_by_output(model=model) - if table is None or (table, column) not in upstream_sources[model.name].get(column, set()): - continue - suggestion: str | None = closest_column(name=column, columns=shapes.get(table or "", {})) - if suggestion is not None: - poisoned[(model.name, suggestion)] = diagnostic - origins[diagnostic] = model.name, suggestion - for _ in project.models: - previous: int = len(poisoned) - for model in project.models: - for column in model.fast_lineage_columns or (): - for source in column.upstream_columns: - root: CompilerDiagnostic | None = poisoned.get( - (source.resource_name, source.column_name) - ) - if root is not None: - poisoned.setdefault((model.name, column.output_column), root) - if len(poisoned) == previous: - break - skipped: Counter[tuple[CompilerDiagnostic, str, str]] = Counter() - kept: list[CompilerDiagnostic] = [] - for diagnostic in project.diagnostics: - missing = missing_column(diagnostic.message) if diagnostic.code == _MISSING_CODE else None - target: tuple[str, str] | None = ( - (missing[1], missing[0]) if missing and missing[1] else None - ) - if diagnostic.code == _TEST_CODE: - match: re.Match[str] | None = re.search( - r"'__(?:expected|ref)__(.+)' names unknown column '([^']+)'", diagnostic.message - ) - if match: - target = match.group(1), match.group(2) - root = poisoned.get(target) if target is not None else None - if root is not None and root != diagnostic and target is not None: - skipped[(root, *origins[root])] += 1 - else: - kept.append(diagnostic) - notes: dict[CompilerDiagnostic, list[str]] = {} - for (root, model_name, column_name), count in skipped.items(): - notes.setdefault(root, []).append( - f"{count} downstream uses of {model_name}.{column_name} " - "were not checked because of this error" - ) - diagnostics: tuple[CompilerDiagnostic, ...] = tuple( - replace(item, notes=(*item.notes, *notes.get(item, ()))) for item in kept - ) - return replace( - project, - diagnostics=diagnostics, - models=update_binding_models(models=project.models, diagnostics=diagnostics), + return complete_native_semantic_diagnostics( + project=project, + profile=profile, + binding_results=binding_results, + resource_sql_analysis=resource_sql_analysis, + session=native_session, ) - - -def _upstream_sources_by_output(*, model: CompiledModel) -> dict[str, set[tuple[str, str]]]: - sources: dict[str, set[tuple[str, str]]] = {} - for output in model.fast_lineage_columns or (): - sources.setdefault(output.output_column, set()).update( - (source.resource_name, source.column_name) for source in output.upstream_columns - ) - return sources diff --git a/src/sqlbuild/compiler/compile/_helpers/diagnostics/sql_analysis_opt_outs.py b/src/sqlbuild/compiler/compile/_helpers/diagnostics/sql_analysis_opt_outs.py index 6db1cd78b5..e328348fd4 100644 --- a/src/sqlbuild/compiler/compile/_helpers/diagnostics/sql_analysis_opt_outs.py +++ b/src/sqlbuild/compiler/compile/_helpers/diagnostics/sql_analysis_opt_outs.py @@ -4,19 +4,13 @@ import re from collections import Counter -from dataclasses import replace from pathlib import Path from sqlbuild.compiler.compile._helpers.analysis.validation import ( hook_sql_statements, - validate_hook_sql_syntax, - validate_sql_syntax, ) from sqlbuild.compiler.compile.constants import UNNEEDED_SQL_ANALYSIS_OPT_OUT_CODE -from sqlbuild.compiler.compile.exceptions import CompileInputError from sqlbuild.compiler.compile.models import ( - CompiledModel, - CompiledProject, CompilerDiagnostic, SqlAnalysisOptOutRequest, ) @@ -32,8 +26,6 @@ SQL_ANALYSIS_CONFIG_KEY, ) from sqlbuild.compiler.discovery.models import DiscoveredSqlModelFile -from sqlbuild.compiler.frontier.main.native_stage_enabled import native_stage_enabled -from sqlbuild.compiler.frontier.types import NativeStage from sqlbuild.compiler.project_assembly.main._check_native_sql_syntax import ( check_native_sql_syntax, ) @@ -44,7 +36,6 @@ from sqlbuild.spec.contracts.models import SettingsConfig, SourceLocation _LEGACY_KEY: str = "sql_validation" -_SEMANTIC_CODE_PREFIX: str = "B" _OPT_OUT_KEYS: tuple[str, ...] = (SQL_ANALYSIS_CONFIG_KEY, _LEGACY_KEY) _HOOK_KEYS: tuple[str, ...] = ("pre_hooks", "post_hooks") _OPT_OUT_KEY_PATTERN: re.Pattern[str] = re.compile(r"\b(?:sql_analysis|sql_validation)\b") @@ -80,76 +71,12 @@ def rejected_sql_analysis_opt_out(request: SqlAnalysisOptOutRequest) -> SourceLo def _parses(request: SqlAnalysisOptOutRequest) -> bool: """Whether the model query and every hook pass Python's syntax validation.""" - if native_stage_enabled(NativeStage.PROJECT_ASSEMBLY): - statements: list[str] = [request.query_sql] - for hook_name in _HOOK_KEYS: - statements.extend(hook_sql_statements(request.config.values.get(hook_name))) - native: bool | None = check_native_sql_syntax( - checks=tuple((statement, request.placeholders) for statement in statements), - dialect=None, - ) - if native is not None: - return native - model_name: str = request.model_file.file_path.stem - try: - validate_sql_syntax( - query_sql=request.query_sql, - model_name=model_name, - file_path=request.model_file.file_path, - placeholders=request.placeholders, - ) - for hook_name in _HOOK_KEYS: - validate_hook_sql_syntax( - value=request.config.values.get(hook_name), - hook_name=hook_name, - model_name=model_name, - file_path=request.model_file.file_path, - placeholders=request.placeholders, - ) - except CompileInputError: - return False - return True - - -def reject_unneeded_sql_analysis_opt_outs(project: CompiledProject) -> CompiledProject: - """Replace each rejected opt-out model's findings with one error that counts them.""" - - rejected: dict[str, CompiledModel] = { - model.name: model - for model in project.models - if model.rejected_sql_analysis_opt_out is not None - } - if not rejected: - return project - hidden: dict[str, list[CompilerDiagnostic]] = {name: [] for name in rejected} - kept: list[CompilerDiagnostic] = [] - for diagnostic in project.diagnostics: - if ( - diagnostic.resource_name in hidden - and diagnostic.resource_type in (None, CompiledResourceType.MODEL) - and diagnostic.code.startswith(_SEMANTIC_CODE_PREFIX) - ): - hidden[diagnostic.resource_name].append(diagnostic) - else: - kept.append(diagnostic) - kept.extend( - _opt_out_diagnostic(model=model, hidden=tuple(hidden[name])) - for name, model in sorted(rejected.items()) - ) - return replace(project, diagnostics=tuple(kept)) - - -def _opt_out_diagnostic( - *, model: CompiledModel, hidden: tuple[CompilerDiagnostic, ...] -) -> CompilerDiagnostic: - location: SourceLocation | None = model.rejected_sql_analysis_opt_out - return unneeded_opt_out_diagnostic( - resource_type=CompiledResourceType.MODEL, - kind="model", - name=model.name, - location=location, - hidden=hidden, - path_default=location is not None and location.path.name == PROJECT_CONFIG_FILENAME, + statements: list[str] = [request.query_sql] + for hook_name in _HOOK_KEYS: + statements.extend(hook_sql_statements(request.config.values.get(hook_name))) + return check_native_sql_syntax( + checks=tuple((statement, request.placeholders) for statement in statements), + dialect=None, ) diff --git a/src/sqlbuild/compiler/compile/_helpers/diagnostics/type_recovery.py b/src/sqlbuild/compiler/compile/_helpers/diagnostics/type_recovery.py deleted file mode 100644 index b0e3b165a2..0000000000 --- a/src/sqlbuild/compiler/compile/_helpers/diagnostics/type_recovery.py +++ /dev/null @@ -1,299 +0,0 @@ -"""Propagate unknown output types from located root errors without opening other columns.""" - -from bisect import bisect_right -from collections import Counter, deque -from dataclasses import replace -from typing import Any - -from sqlbuild.compiler.compile._helpers.analysis.compact import get_complete_schema_binding_request -from sqlbuild.compiler.compile._helpers.assembly.native_declarations import ( - known_declared_types, - known_function_names, -) -from sqlbuild.compiler.compile._helpers.assembly.semantic_shapes import semantic_shapes -from sqlbuild.compiler.compile._helpers.diagnostics.details import update_binding_models -from sqlbuild.compiler.compile.models import ( - CompiledModel, - CompiledProject, - CompilerDiagnostic, - InferredColumn, -) -from sqlbuild.compiler.sql_analysis.main._identifier_case import ignores_quoted_case -from sqlbuild.compiler.sql_analysis.main._schema_validation import get_schema_validations -from sqlbuild.compiler.sql_analysis.main.import_polyglot_sql import import_polyglot_sql -from sqlbuild.compiler.sql_analysis.models import ( - SqlBindingDiagnostic, - SqlBindingResult, - SqlSchemaValidationRequest, -) - -_SELECT: str = "SELECT" -_PROJECTION_END: frozenset[str] = frozenset( - { - "FROM", - "WHERE", - "GROUP_BY", - "HAVING", - "QUALIFY", - "ORDER_BY", - "LIMIT", - "UNION", - "INTERSECT", - "EXCEPT", - } -) -_OPEN: str = "(" -_CLOSE: str = ")" -_COMMA: str = "," - - -def recover_output_types( - *, project: CompiledProject, binding_results: dict[str, tuple[SqlBindingDiagnostic, ...]] -) -> CompiledProject: - """Recheck only failed dependants using unknown types for poisoned lineage outputs.""" - failed: list[CompiledModel] = [model for model in project.models if model.binding_diagnostics] - blocking: list[CompilerDiagnostic] = [] - for model in failed: - blocking.extend(item for item in model.binding_diagnostics if item.is_error) - if not blocking: - return project - shapes: dict[str, dict[str, str]] = semantic_shapes(project=project) - requests: tuple[SqlSchemaValidationRequest, ...] = tuple( - _request(project=project, model=model, shapes=shapes) for model in failed - ) - results: tuple[SqlBindingResult, ...] = tuple( - SqlBindingResult(diagnostics=binding_results.get(model.name, ())) for model in failed - ) - poisoned: dict[tuple[str, str], CompilerDiagnostic] = {} - roots_by_model: dict[str, dict[SqlBindingDiagnostic, CompilerDiagnostic]] = {} - outputs_by_diagnostic: dict[CompilerDiagnostic, set[str]] = {} - for model, request, result in zip(failed, requests, results, strict=True): - roots_by_model[model.name] = _root_bindings(model=model, diagnostics=result.diagnostics) - spans: list[tuple[int, int]] = _projection_spans(sql=request.sql, dialect=request.dialect) - columns: tuple[InferredColumn, ...] = model.inferred_columns or () - if len(spans) != len(columns): - continue - span_starts: list[int] = [start for start, _ in spans] - for raw in result.diagnostics: - if raw.start is None: - continue - root: CompilerDiagnostic | None = roots_by_model[model.name].get(raw) - column: InferredColumn | None = _column_at( - columns=columns, spans=spans, span_starts=span_starts, offset=raw.start - ) - if root is not None and root.is_error and column is not None: - poisoned[(model.name, column.name)] = root - outputs_by_diagnostic.setdefault(root, set()).add(column.name) - if not poisoned: - return project - for _ in project.models: - previous: int = len(poisoned) - for model in project.models: - for output in model.fast_lineage_columns or (): - for source in output.upstream_columns: - root = poisoned.get((source.resource_name, source.column_name)) - if root is not None: - poisoned.setdefault((model.name, output.output_column), root) - if len(poisoned) == previous: - break - unknown_shapes: dict[str, dict[str, str]] = { - name: dict(columns) for name, columns in shapes.items() - } - for name, column_name in poisoned: - if name in unknown_shapes and column_name in unknown_shapes[name]: - unknown_shapes[name][column_name] = "UNKNOWN" - skipped: set[CompilerDiagnostic] = set() - redirected: dict[CompilerDiagnostic, set[CompilerDiagnostic]] = {} - for model, original in zip(failed, results, strict=True): - causes: set[CompilerDiagnostic] = set() - for reference in model.references: - causes.update( - root for (name, _), root in poisoned.items() if name == reference.ref_name - ) - if not causes: - continue - revised: SqlBindingResult = get_schema_validations( - requests=(_request(project=project, model=model, shapes=unknown_shapes),) - )[0] - remaining: set[tuple[str, int | None, int | None]] = { - (item.code, item.start, item.end) for item in revised.diagnostics - } - for raw in original.diagnostics: - diagnostic: CompilerDiagnostic | None = roots_by_model[model.name].get(raw) - if ( - diagnostic is None - or diagnostic in causes - or (raw.code, raw.start, raw.end) in remaining - ): - continue - skipped.add(diagnostic) - redirected[diagnostic] = ( - _output_causes( - model=model, - outputs=outputs_by_diagnostic.get(diagnostic, set()), - poisoned=poisoned, - ) - or causes - ) - counts: Counter[CompilerDiagnostic] = _unchecked_uses( - project=project, poisoned=poisoned, redirected=redirected - ) - diagnostics: tuple[CompilerDiagnostic, ...] = tuple( - replace( - item, - notes=( - *item.notes, - *( - ( - f"{counts[item]} downstream output uses were not type-checked " - "because of this error", - ) - if counts[item] - else () - ), - ), - ) - for item in project.diagnostics - if item not in skipped - ) - models: list[CompiledModel] = [] - for model in update_binding_models(models=project.models, diagnostics=diagnostics): - updated: tuple[InferredColumn, ...] | None = None - if model.inferred_columns is not None: - updated = tuple( - replace(column, type=None) if (model.name, column.name) in poisoned else column - for column in model.inferred_columns - ) - models.append( - replace( - model, - inferred_columns=updated, - unchecked_output_columns=frozenset( - column for name, column in poisoned if name == model.name - ), - ) - ) - return replace(project, models=tuple(models), diagnostics=diagnostics) - - -def _unchecked_uses( - *, - project: CompiledProject, - poisoned: dict[tuple[str, str], CompilerDiagnostic], - redirected: dict[CompilerDiagnostic, set[CompilerDiagnostic]], -) -> Counter[CompilerDiagnostic]: - """Attribute transitive unchecked output uses to retained root errors.""" - counts: Counter[CompilerDiagnostic] = Counter() - for model in project.models: - for output in model.fast_lineage_columns or (): - pending: list[CompilerDiagnostic] = [] - for source in output.upstream_columns: - root: CompilerDiagnostic | None = poisoned.get( - (source.resource_name, source.column_name) - ) - if root is not None: - pending.append(root) - visited: set[CompilerDiagnostic] = set() - while pending: - root = pending.pop() - if root in visited: - continue - visited.add(root) - if root in redirected: - pending.extend(redirected[root]) - else: - counts[root] += 1 - return counts - - -def _root_bindings( - *, model: CompiledModel, diagnostics: tuple[SqlBindingDiagnostic, ...] -) -> dict[SqlBindingDiagnostic, CompilerDiagnostic]: - """Pair repeated messages by occurrence, preserving distinct native spans.""" - pending: dict[tuple[str, str], deque[CompilerDiagnostic]] = {} - for diagnostic in model.binding_diagnostics: - pending.setdefault((diagnostic.code, diagnostic.message), deque()).append(diagnostic) - result: dict[SqlBindingDiagnostic, CompilerDiagnostic] = {} - for raw in diagnostics: - matches: deque[CompilerDiagnostic] | None = pending.get((raw.code, raw.message)) - if matches: - result[raw] = matches.popleft() - return result - - -def _output_causes( - *, model: CompiledModel, outputs: set[str], poisoned: dict[tuple[str, str], CompilerDiagnostic] -) -> set[CompilerDiagnostic]: - """Redirect only the failing projection's lineage instead of every poisoned input.""" - result: set[CompilerDiagnostic] = set() - for output in model.fast_lineage_columns or (): - if output.output_column in outputs: - for source in output.upstream_columns: - root: CompilerDiagnostic | None = poisoned.get( - (source.resource_name, source.column_name) - ) - if root is not None: - result.add(root) - return result - - -def _request( - *, project: CompiledProject, model: CompiledModel, shapes: dict[str, dict[str, str]] -) -> SqlSchemaValidationRequest: - return replace( - get_complete_schema_binding_request( - query_sql=model.query_sql, - placeholders=None, - dialect=project.sql_analysis_dialect, - known_functions=known_function_names(project.functions), - known_types=known_declared_types(functions=project.functions, column_types=shapes), - binding_schema={ - reference.ref_name: shapes.get(reference.ref_name, {}) - for reference in model.references - }, - ), - catalog=project.binding_catalog, - quoted_identifiers_ignore_case=ignores_quoted_case( - connection=project.effective_connection, dialect=project.sql_analysis_dialect - ), - ) - - -def _column_at( - *, - columns: tuple[InferredColumn, ...], - spans: list[tuple[int, int]], - span_starts: list[int], - offset: int, -) -> InferredColumn | None: - """Projection spans are ordered and disjoint, so bisect finds the only candidate.""" - position: int = bisect_right(span_starts, offset) - 1 - if position < 0 or offset >= spans[position][1]: - return None - return columns[position] - - -def _projection_spans(*, sql: str, dialect: str | None) -> list[tuple[int, int]]: - module: Any = import_polyglot_sql() - tokens: list[dict[str, Any]] = module.tokenize(sql, dialect=dialect) - depth: int = 0 - start: int | None = None - spans: list[tuple[int, int]] = [] - for token in tokens: - text: str = token["text"] - if text == _OPEN: - depth += 1 - elif text == _CLOSE: - depth -= 1 - elif depth == 0: - if start is None and token["token_type"] == _SELECT: - start = token["span"]["end"] - elif start is not None and token["token_type"] in _PROJECTION_END: - spans.append((start, token["span"]["start"])) - return spans - elif start is not None and text == _COMMA: - spans.append((start, token["span"]["start"])) - start = token["span"]["end"] - if start is not None: - spans.append((start, len(sql))) - return spans diff --git a/src/sqlbuild/compiler/compile/_helpers/explicit_references/checks.py b/src/sqlbuild/compiler/compile/_helpers/explicit_references/checks.py new file mode 100644 index 0000000000..e86357b808 --- /dev/null +++ b/src/sqlbuild/compiler/compile/_helpers/explicit_references/checks.py @@ -0,0 +1,422 @@ +"""Compile's explicit-reference checks: Python collects the facts, native decides.""" + +from __future__ import annotations + +import ast +import inspect +import textwrap +from collections.abc import Callable, Iterator, Mapping +from dataclasses import dataclass, field +from itertools import chain +from pathlib import Path +from typing import Any + +import orjson + +import sqlbuild._native as _native +from sqlbuild.compiler.compile.constants import MIGRATE_FROM_CONFIG_KEY +from sqlbuild.compiler.compile.exceptions import CompileInputError +from sqlbuild.compiler.compile.models import ( + CompiledAudit, + CompiledModel, + CompiledObjectKey, + CompiledProject, + CompiledRelationLocation, + CompiledSource, + CompilerDiagnostic, + PythonSqlReferenceReport, +) +from sqlbuild.compiler.compile.types import ( + AttachedAuditTargetKind, + DiagnosticPhase, + DiagnosticSeverity, +) +from sqlbuild.compiler.discovery.main.explicit_references_help import explicit_references_help +from sqlbuild.compiler.discovery.models import DiscoveredProjectInputs, SqlHookEntry +from sqlbuild.compiler.graph.main._model_python_hook_names import model_python_hook_names +from sqlbuild.compiler.migrations.main._resolve_old_name_view_retention import ( + resolve_old_name_view_retention, +) +from sqlbuild.compiler.references.models import LiteralSqlRelation, RelationName +from sqlbuild.compiler.references.types import HardCodedRelationOwnerKind +from sqlbuild.python_nodes.main.read_loader_definition import read_loader_definition +from sqlbuild.python_nodes.models import LoaderDefinition, SqlResourceRef +from sqlbuild.python_nodes.types import SqlResourceRefKind +from sqlbuild.spec.contracts.models import SourceEntry, SourceLocation + +_MODEL_HOOK_KEYS: tuple[str, ...] = ("pre_hooks", "post_hooks") +_RAISE_KEY: str = "raise" +_REPORT_KEY: str = "report" +_SQL_METHOD_NAMES: frozenset[str] = frozenset({"query", "execute_sql"}) +_SQL_PARAMETER_NAME: str = "sql" +_CONTEXT_PARAMETER_NAMES: frozenset[str] = frozenset({"ctx", "context", "_ctx", "hook_context"}) +_VALUE_PLACEHOLDER: str = "__sqlbuild_python_value_" + + +@dataclass(frozen=True) +class _PythonSqlOwner: + label: str + kind: HardCodedRelationOwnerKind + function: Callable[..., object] + relative_path: Path + own_refs: frozenset[SqlResourceRef] = frozenset() + upstream_loader_by_source: Mapping[str, str] = field(default_factory=dict) + + +@dataclass(frozen=True) +class _LiteralSql: + method: str + sql: str + line: int + + +def explicit_reference_report( + *, project: CompiledProject, discovered_inputs: DiscoveredProjectInputs, enforce_explicit: bool +) -> PythonSqlReferenceReport: + """Return P005, P007 and P008 errors and unmatched Python-SQL relations; raise P001.""" + + owners: tuple[_PythonSqlOwner, ...] = ( + _owners(project=project, discovered_inputs=discovered_inputs) if enforce_explicit else () + ) + literals: tuple[tuple[_LiteralSql, ...], ...] = tuple( + tuple(_literal_sql_calls(owner.function)) for owner in owners + ) + paths: list[Path] = sorted({owner.relative_path for owner in owners}) + path_order: dict[Path, int] = {path: index for index, path in enumerate(paths)} + outcome: dict[str, Any] = orjson.loads( + _native.check_native_explicit_references( + orjson.dumps( + { + "enforce_explicit": enforce_explicit, + "dialect": project.sql_analysis_dialect, + "explicit_help": ( + explicit_references_help(allowed="hard-coded relation names") + if enforce_explicit + else "" + ), + "placeholder": _VALUE_PLACEHOLDER, + "resources": _resource_rows(project), + "models": [ + _model_row( + model=model, + old_name_retention=( + discovered_inputs.project_config.migrations.old_name_views + ), + ) + for model in project.models + ], + "sources": [_source_row(source) for source in project.sources], + "seeds": [ + {"name": seed.name, "relation": _location_row(seed.destination)} + for seed in project.seeds + ], + "audits": [_audit_row(audit) for audit in project.audits], + "hooks": [ + { + "name": hook.name, + "path": hook.relative_path.as_posix(), + "reads": _ref_rows(hook.reads), + } + for hook in project.hook_functions + ], + "owners": [ + _owner_row( + owner=owner, + literals=owner_literals, + path_order=path_order[owner.relative_path], + ) + for owner, owner_literals in zip(owners, literals, strict=True) + ], + } + ).decode() + ) + ) + if _RAISE_KEY in outcome: + raise CompileInputError(outcome[_RAISE_KEY]) + report: dict[str, Any] = outcome[_REPORT_KEY] + return PythonSqlReferenceReport( + diagnostics=tuple(_diagnostic(row=row, owners=owners) for row in report["diagnostics"]), + unmatched=tuple( + LiteralSqlRelation( + owner_label=owners[row["owner"]].label, + owner_kind=owners[row["owner"]].kind, + relative_path=owners[row["owner"]].relative_path, + line=row["line"], + method=row["method"], + relation=RelationName( + name=row["relation"]["name"], + schema=row["relation"]["schema"], + database=row["relation"]["database"], + ), + ) + for row in report["unmatched"] + ), + ) + + +def _diagnostic(*, row: dict[str, Any], owners: tuple[_PythonSqlOwner, ...]) -> CompilerDiagnostic: + owner: int | None = row["owner"] + resource: list[str] | None = row["resource"] + return CompilerDiagnostic( + phase=DiagnosticPhase.COMPILE, + severity=DiagnosticSeverity.ERROR, + code=row["code"], + message=row["message"], + resource_type=None if resource is None else resource[0], + resource_name=None if resource is None else resource[1], + path=None if row["path"] is None else Path(row["path"]), + location=( + None + if owner is None + else SourceLocation(path=owners[owner].relative_path, line=row["line"], column=1) + ), + help=row["help"], + ) + + +def _owner_row( + *, owner: _PythonSqlOwner, literals: tuple[_LiteralSql, ...], path_order: int +) -> dict[str, object]: + return { + "label": owner.label, + "kind": str(owner.kind), + "path_order": path_order, + "own_refs": _ref_rows(tuple(owner.own_refs)), + "upstream_loaders": list(owner.upstream_loader_by_source.items()), + "literals": [ + {"method": literal.method, "sql": literal.sql, "line": literal.line} + for literal in literals + ], + } + + +def _resource_rows(project: CompiledProject) -> list[dict[str, object]]: + return [ + {"key": _key_row(resource.key), "deps": _key_rows(resource.deps)} + for resource in (*project.models, *project.sources, *project.seeds, *project.functions) + ] + + +def _key_row(key: CompiledObjectKey) -> tuple[str, str]: + return (str(key.resource_type), key.name) + + +def _key_rows(keys: tuple[CompiledObjectKey, ...]) -> list[tuple[str, str]]: + return [_key_row(key) for key in keys] + + +def _model_row(*, model: CompiledModel, old_name_retention: str | None) -> dict[str, object]: + raw: object = model.config.values.get(MIGRATE_FROM_CONFIG_KEY) + retained: bool = isinstance(raw, str) and ( + resolve_old_name_view_retention( + config_values=model.config.values, project_retention=old_name_retention + ) + is not None + ) + return { + "name": model.name, + "path": str(model.relative_path), + "destination": _location_row(model.destination), + "python_hooks": list(model_python_hook_names(model=model)), + "sql_hooks": list( + chain.from_iterable( + _sql_hook_rows(hook_key=hook_key, entries=model.config.values.get(hook_key)) + for hook_key in _MODEL_HOOK_KEYS + ) + ), + "migrate_from": raw if retained else None, + } + + +def _sql_hook_rows(*, hook_key: str, entries: object) -> list[dict[str, object]]: + """SQL hook entries with declared reads, at their position among the key's entries.""" + + items: tuple[object, ...] = tuple(entries) if isinstance(entries, list | tuple) else (entries,) + return [ + { + "hook_key": hook_key, + "index": index, + "name": entry.name, + "path": None if entry.relative_path is None else str(entry.relative_path), + "reads": _ref_rows(entry.reads), + } + for index, entry in enumerate(items) + if isinstance(entry, SqlHookEntry) and entry.reads + ] + + +def _source_row(source: CompiledSource) -> dict[str, object]: + entry: SourceEntry = source.source_entry + return { + "name": source.name, + "table": entry.table, + "schema": entry.schema, + "database": entry.database, + "expression": entry.expression is not None, + } + + +def _audit_row(audit: CompiledAudit) -> dict[str, object]: + target: tuple[str, str] | None = ( + ( + str(AttachedAuditTargetKind(audit.attached_target_kind).resource_type), + audit.attached_target_name, + ) + if audit.attached_target_kind is not None and audit.attached_target_name is not None + else None + ) + return { + "name": audit.name, + "path": str(audit.audit_file.relative_path), + "target": target, + "scope_deps": _key_rows(audit.scope_deps), + } + + +def _location_row(location: CompiledRelationLocation) -> dict[str, str | None]: + return {"name": location.name, "schema": location.schema, "database": location.database} + + +def _ref_rows(refs: tuple[SqlResourceRef, ...]) -> list[tuple[str, str]]: + return [(str(ref.kind), ref.name) for ref in refs] + + +def _owners( + *, project: CompiledProject, discovered_inputs: DiscoveredProjectInputs +) -> tuple[_PythonSqlOwner, ...]: + owners: list[_PythonSqlOwner] = [] + for label, nodes in ( + ("task", discovered_inputs.task_functions), + ("asset", discovered_inputs.asset_functions), + ("check", discovered_inputs.check_functions), + ): + owners.extend( + _PythonSqlOwner( + label=f"{label}:{node.name}", + kind=HardCodedRelationOwnerKind.NODE, + function=node.function, + relative_path=node.relative_path, + ) + for node in nodes + ) + owners.extend(_loader_owners(project=project, discovered_inputs=discovered_inputs)) + attached_models: dict[str, set[SqlResourceRef]] = {} + for model in project.models: + for hook_name in model_python_hook_names(model=model): + attached_models.setdefault(hook_name, set()).add( + SqlResourceRef(kind=SqlResourceRefKind.MODEL, name=model.name) + ) + owners.extend( + _PythonSqlOwner( + label=f"hook:{hook.name}", + kind=HardCodedRelationOwnerKind.HOOK, + function=hook.function, + relative_path=hook.relative_path, + own_refs=frozenset(attached_models.get(hook.name, ())), + ) + for hook in project.hook_functions + ) + return tuple(owners) + + +def _loader_owners( + *, project: CompiledProject, discovered_inputs: DiscoveredProjectInputs +) -> tuple[_PythonSqlOwner, ...]: + sources_by_loader: dict[str, set[str]] = {} + for source in project.sources: + if source.source_entry.loader is not None: + sources_by_loader.setdefault(source.source_entry.loader, set()).add(source.name) + owners: list[_PythonSqlOwner] = [] + for loader in discovered_inputs.loader_functions: + upstream_loader_by_source: dict[str, str] = {} + for dependency in loader.depends_on: + definition: LoaderDefinition | None = ( + read_loader_definition(dependency) if callable(dependency) else None + ) + if definition is None: + continue + for source_name in sources_by_loader.get(definition.name, ()): + upstream_loader_by_source[source_name] = getattr( + dependency, "__name__", definition.name + ) + owners.append( + _PythonSqlOwner( + label=f"loader:{loader.name}", + kind=HardCodedRelationOwnerKind.LOADER, + function=loader.function, + relative_path=loader.relative_path, + own_refs=frozenset( + SqlResourceRef(kind=SqlResourceRefKind.SOURCE, name=source_name) + for source_name in sources_by_loader.get(loader.name, ()) + ), + upstream_loader_by_source=upstream_loader_by_source, + ) + ) + return tuple(owners) + + +def _literal_sql_calls(function: Callable[..., object]) -> Iterator[_LiteralSql]: + try: + lines: list[str] + start_line: int + lines, start_line = inspect.getsourcelines(function) + tree: ast.Module = ast.parse(textwrap.dedent("".join(lines))) + except (OSError, TypeError, SyntaxError): + return + definition: ast.stmt | None = tree.body[0] if tree.body else None + if not isinstance(definition, ast.FunctionDef | ast.AsyncFunctionDef): + return + parameters: list[str] = [ + argument.arg + for argument in ( + *definition.args.posonlyargs, + *definition.args.args, + *definition.args.kwonlyargs, + ) + ] + context_name: str | None = next( + (name for name in parameters if name in _CONTEXT_PARAMETER_NAMES), + parameters[0] if parameters else None, + ) + if context_name is None: + return + for node in ast.walk(definition): + if not ( + isinstance(node, ast.Call) + and isinstance(node.func, ast.Attribute) + and node.func.attr in _SQL_METHOD_NAMES + and isinstance(node.func.value, ast.Name) + and node.func.value.id == context_name + ): + continue + argument: ast.expr | None = _sql_argument(node) + sql: str | None = _literal_text(argument) if argument is not None else None + if sql is not None: + yield _LiteralSql(method=node.func.attr, sql=sql, line=start_line + node.lineno - 1) + + +def _sql_argument(call: ast.Call) -> ast.expr | None: + if call.args: + return call.args[0] + for keyword in call.keywords: + if keyword.arg == _SQL_PARAMETER_NAME: + return keyword.value + if keyword.arg is None and isinstance(keyword.value, ast.Dict): + for key, value in zip(keyword.value.keys, keyword.value.values, strict=True): + if isinstance(key, ast.Constant) and key.value == _SQL_PARAMETER_NAME: + return value + return None + + +def _literal_text(node: ast.expr) -> str | None: + if isinstance(node, ast.Constant) and isinstance(node.value, str): + return node.value + if not isinstance(node, ast.JoinedStr): + return None + parts: list[str] = [] + for index, value in enumerate(node.values): + if isinstance(value, ast.Constant) and isinstance(value.value, str): + parts.append(value.value) + else: + parts.append(f"{_VALUE_PLACEHOLDER}{index}") + return "".join(parts) diff --git a/src/sqlbuild/compiler/compile/_helpers/explicit_references/hook_reads.py b/src/sqlbuild/compiler/compile/_helpers/explicit_references/hook_reads.py deleted file mode 100644 index 3b4ffa6384..0000000000 --- a/src/sqlbuild/compiler/compile/_helpers/explicit_references/hook_reads.py +++ /dev/null @@ -1,69 +0,0 @@ -"""Compile validation for resources model hooks read.""" - -from __future__ import annotations - -from sqlbuild.compiler.compile.constants import HOOK_READS_OWN_DEPENDANT_CODE -from sqlbuild.compiler.compile.exceptions import CompileInputError -from sqlbuild.compiler.compile.models import ( - CompiledObjectKey, - CompiledProject, - CompilerDiagnostic, -) -from sqlbuild.compiler.compile.types import ( - CompiledResourceType, - DiagnosticPhase, - DiagnosticSeverity, -) -from sqlbuild.compiler.graph.main._hook_read_cycles import hook_read_cycles -from sqlbuild.compiler.graph.models import HookReadEdge -from sqlbuild.compiler.graph.types import HookReadType -from sqlbuild.python_nodes.models import SqlResourceRef -from sqlbuild.python_nodes.types import SqlResourceRefKind - - -def hook_read_diagnostics(*, project: CompiledProject) -> tuple[CompilerDiagnostic, ...]: - """Reject unknown hook reads; return a P007 error for each read of a hook's own dependant.""" - - known: dict[SqlResourceRefKind, frozenset[str]] = { - SqlResourceRefKind.MODEL: frozenset(model.name for model in project.models), - SqlResourceRefKind.SOURCE: frozenset(source.name for source in project.sources), - SqlResourceRefKind.SEED: frozenset(seed.name for seed in project.seeds), - } - for hook in sorted(project.hook_functions, key=lambda item: item.name): - ref: SqlResourceRef - for ref in hook.reads: - if ref.name not in known[ref.kind]: - raise CompileInputError( - f"Python hook '{hook.name}' in '{hook.relative_path.as_posix()}' reads unknown " - f"{ref.kind.value} '{ref.name}'" - ) - return tuple(_cycle_diagnostic(cycle) for cycle in hook_read_cycles(project=project)) - - -def _cycle_diagnostic(cycle: HookReadEdge) -> CompilerDiagnostic: - destination: str = ( - "ctx.destination" - if cycle.hook_type is HookReadType.PYTHON - else "@@CTX:destination.qualified" - ) - return CompilerDiagnostic( - phase=DiagnosticPhase.COMPILE, - severity=DiagnosticSeverity.ERROR, - code=HOOK_READS_OWN_DEPENDANT_CODE, - message=( - f"{cycle.label} on {_describe(cycle.gated)} reads " - f"{_describe(cycle.read)}, which depends on '{cycle.gated.name}'; a hook runs as " - "part of its model, so it cannot wait for a resource built from that model" - ), - resource_type=CompiledResourceType.MODEL, - resource_name=cycle.gated.name, - path=cycle.hook_path, - help=( - f"attach the hook to a model built after '{cycle.read.name}', or drop the read and " - f"use {destination} for '{cycle.gated.name}' itself" - ), - ) - - -def _describe(key: CompiledObjectKey) -> str: - return f"{key.resource_type} '{key.name}'" diff --git a/src/sqlbuild/compiler/compile/_helpers/explicit_references/python_sql.py b/src/sqlbuild/compiler/compile/_helpers/explicit_references/python_sql.py deleted file mode 100644 index bcafdfbbaa..0000000000 --- a/src/sqlbuild/compiler/compile/_helpers/explicit_references/python_sql.py +++ /dev/null @@ -1,351 +0,0 @@ -"""Compile-time rejection of project relation names hard-coded in Python SQL.""" - -from __future__ import annotations - -import ast -import inspect -import textwrap -from collections.abc import Callable, Iterator, Mapping -from dataclasses import dataclass, field -from pathlib import Path - -from sqlbuild.compiler.compile.constants import HARD_CODED_PROJECT_RELATION_CODE -from sqlbuild.compiler.compile.models import ( - CompiledProject, - CompilerDiagnostic, - PythonSqlReferenceReport, -) -from sqlbuild.compiler.compile.types import DiagnosticPhase, DiagnosticSeverity -from sqlbuild.compiler.discovery.main.explicit_references_help import explicit_references_help -from sqlbuild.compiler.discovery.models import DiscoveredProjectInputs -from sqlbuild.compiler.graph.main._model_python_hook_names import model_python_hook_names -from sqlbuild.compiler.references.main._compiled_project_relations import ( - compiled_project_relations, -) -from sqlbuild.compiler.references.main._old_name_reference_message import ( - old_name_reference_message, -) -from sqlbuild.compiler.references.main.extract_relation_names import extract_relation_names -from sqlbuild.compiler.references.main.hard_coded_relation_remedy import ( - hard_coded_relation_remedy, -) -from sqlbuild.compiler.references.main.match_project_relation import match_project_relation -from sqlbuild.compiler.references.models import ( - LiteralSqlRelation, - ProjectRelation, - ProjectRelationIndex, - RelationName, -) -from sqlbuild.compiler.references.types import HardCodedRelationOwnerKind -from sqlbuild.python_nodes.main.read_loader_definition import read_loader_definition -from sqlbuild.python_nodes.models import LoaderDefinition, SqlResourceRef -from sqlbuild.python_nodes.types import SqlResourceRefKind -from sqlbuild.spec.contracts.models import SourceLocation - -_SQL_METHOD_NAMES: frozenset[str] = frozenset({"query", "execute_sql"}) -_SQL_PARAMETER_NAME: str = "sql" -_CONTEXT_PARAMETER_NAMES: frozenset[str] = frozenset({"ctx", "context", "_ctx", "hook_context"}) -_VALUE_PLACEHOLDER: str = "__sqlbuild_python_value_" - - -@dataclass(frozen=True) -class _PythonSqlOwner: - label: str - kind: HardCodedRelationOwnerKind - function: Callable[..., object] - relative_path: Path - own_refs: frozenset[SqlResourceRef] = frozenset() - upstream_loader_by_source: Mapping[str, str] = field(default_factory=dict) - - -@dataclass(frozen=True) -class _LiteralSql: - method: str - sql: str - line: int - - -def python_sql_reference_diagnostics( - *, project: CompiledProject, discovered_inputs: DiscoveredProjectInputs -) -> PythonSqlReferenceReport: - """Return P008 errors for project relations literal SQL in Python code names.""" - - owners: tuple[_PythonSqlOwner, ...] = _owners( - project=project, discovered_inputs=discovered_inputs - ) - if not owners: - return PythonSqlReferenceReport() - index: ProjectRelationIndex = compiled_project_relations( - project=project, - old_name_retention=discovered_inputs.project_config.migrations.old_name_views, - ) - diagnostics: dict[tuple[str, int, str, str], CompilerDiagnostic] = {} - unmatched: list[LiteralSqlRelation] = [] - for owner in owners: - temporary: frozenset[str] = frozenset() - for literal in sorted(_literal_sql_calls(owner.function), key=lambda item: item.line): - found: dict[tuple[str, int, str, str], CompilerDiagnostic] - unnamed: tuple[LiteralSqlRelation, ...] - temporary, found, unnamed = _hard_coded_relations( - owner=owner, - literal=literal, - index=index, - dialect=project.sql_analysis_dialect, - temporary=temporary, - ) - unmatched.extend(unnamed) - for key, diagnostic in found.items(): - diagnostics.setdefault(key, diagnostic) - return PythonSqlReferenceReport( - diagnostics=tuple( - diagnostics[key] - for key in sorted( - diagnostics, - key=lambda key: (diagnostics[key].path or Path(), key[1], key[0], key[2], key[3]), - ) - ), - unmatched=tuple(dict.fromkeys(unmatched)), - ) - - -def _owners( - *, project: CompiledProject, discovered_inputs: DiscoveredProjectInputs -) -> tuple[_PythonSqlOwner, ...]: - owners: list[_PythonSqlOwner] = [] - for label, nodes in ( - ("task", discovered_inputs.task_functions), - ("asset", discovered_inputs.asset_functions), - ("check", discovered_inputs.check_functions), - ): - owners.extend( - _PythonSqlOwner( - label=f"{label}:{node.name}", - kind=HardCodedRelationOwnerKind.NODE, - function=node.function, - relative_path=node.relative_path, - ) - for node in nodes - ) - owners.extend(_loader_owners(project=project, discovered_inputs=discovered_inputs)) - attached_models: dict[str, set[SqlResourceRef]] = {} - for model in project.models: - for hook_name in model_python_hook_names(model=model): - attached_models.setdefault(hook_name, set()).add( - SqlResourceRef(kind=SqlResourceRefKind.MODEL, name=model.name) - ) - owners.extend( - _PythonSqlOwner( - label=f"hook:{hook.name}", - kind=HardCodedRelationOwnerKind.HOOK, - function=hook.function, - relative_path=hook.relative_path, - own_refs=frozenset(attached_models.get(hook.name, ())), - ) - for hook in project.hook_functions - ) - return tuple(owners) - - -def _loader_owners( - *, project: CompiledProject, discovered_inputs: DiscoveredProjectInputs -) -> tuple[_PythonSqlOwner, ...]: - sources_by_loader: dict[str, set[str]] = {} - for source in project.sources: - if source.source_entry.loader is not None: - sources_by_loader.setdefault(source.source_entry.loader, set()).add(source.name) - owners: list[_PythonSqlOwner] = [] - for loader in discovered_inputs.loader_functions: - upstream_loader_by_source: dict[str, str] = {} - for dependency in loader.depends_on: - definition: LoaderDefinition | None = ( - read_loader_definition(dependency) if callable(dependency) else None - ) - if definition is None: - continue - for source_name in sources_by_loader.get(definition.name, ()): - upstream_loader_by_source[source_name] = getattr( - dependency, "__name__", definition.name - ) - owners.append( - _PythonSqlOwner( - label=f"loader:{loader.name}", - kind=HardCodedRelationOwnerKind.LOADER, - function=loader.function, - relative_path=loader.relative_path, - own_refs=frozenset( - SqlResourceRef(kind=SqlResourceRefKind.SOURCE, name=source_name) - for source_name in sources_by_loader.get(loader.name, ()) - ), - upstream_loader_by_source=upstream_loader_by_source, - ) - ) - return tuple(owners) - - -def _literal_sql_calls(function: Callable[..., object]) -> Iterator[_LiteralSql]: - try: - lines: list[str] - start_line: int - lines, start_line = inspect.getsourcelines(function) - tree: ast.Module = ast.parse(textwrap.dedent("".join(lines))) - except (OSError, TypeError, SyntaxError): - return - definition: ast.stmt | None = tree.body[0] if tree.body else None - if not isinstance(definition, ast.FunctionDef | ast.AsyncFunctionDef): - return - parameters: list[str] = [ - argument.arg - for argument in ( - *definition.args.posonlyargs, - *definition.args.args, - *definition.args.kwonlyargs, - ) - ] - context_name: str | None = next( - (name for name in parameters if name in _CONTEXT_PARAMETER_NAMES), - parameters[0] if parameters else None, - ) - if context_name is None: - return - for node in ast.walk(definition): - if not ( - isinstance(node, ast.Call) - and isinstance(node.func, ast.Attribute) - and node.func.attr in _SQL_METHOD_NAMES - and isinstance(node.func.value, ast.Name) - and node.func.value.id == context_name - ): - continue - argument: ast.expr | None = _sql_argument(node) - sql: str | None = _literal_text(argument) if argument is not None else None - if sql is not None: - yield _LiteralSql(method=node.func.attr, sql=sql, line=start_line + node.lineno - 1) - - -def _sql_argument(call: ast.Call) -> ast.expr | None: - if call.args: - return call.args[0] - for keyword in call.keywords: - if keyword.arg == _SQL_PARAMETER_NAME: - return keyword.value - if keyword.arg is None and isinstance(keyword.value, ast.Dict): - for key, value in zip(keyword.value.keys, keyword.value.values, strict=True): - if isinstance(key, ast.Constant) and key.value == _SQL_PARAMETER_NAME: - return value - return None - - -def _literal_text(node: ast.expr) -> str | None: - if isinstance(node, ast.Constant) and isinstance(node.value, str): - return node.value - if not isinstance(node, ast.JoinedStr): - return None - parts: list[str] = [] - for index, value in enumerate(node.values): - if isinstance(value, ast.Constant) and isinstance(value.value, str): - parts.append(value.value) - else: - parts.append(f"{_VALUE_PLACEHOLDER}{index}") - return "".join(parts) - - -def _hard_coded_relations( - *, - owner: _PythonSqlOwner, - literal: _LiteralSql, - index: ProjectRelationIndex, - dialect: str | None, - temporary: frozenset[str], -) -> tuple[ - frozenset[str], - dict[tuple[str, int, str, str], CompilerDiagnostic], - tuple[LiteralSqlRelation, ...], -]: - extracted: tuple[tuple[RelationName, ...], frozenset[str]] | None = extract_relation_names( - sql=literal.sql, dialect=dialect - ) - found: dict[tuple[str, int, str, str], CompilerDiagnostic] = {} - unmatched: list[LiteralSqlRelation] = [] - if extracted is None: - return temporary, found, () - relations, created = extracted - temporary = temporary | created - for relation in relations: - if _VALUE_PLACEHOLDER in "".join( - part for part in (relation.database, relation.schema, relation.name) if part - ): - continue - if relation.schema is None and relation.name.casefold() in temporary: - continue - match: ProjectRelation | None = match_project_relation(index=index, relation=relation) - if match is None: - unmatched.append( - LiteralSqlRelation( - owner_label=owner.label, - owner_kind=owner.kind, - relative_path=owner.relative_path, - line=literal.line, - method=literal.method, - relation=relation, - ) - ) - continue - if match.ref in owner.own_refs and match.compatibility_for is None: - continue - key: tuple[str, int, str, str] = ( - owner.label, - literal.line, - match.ref.kind.value, - match.ref.name, - ) - found.setdefault( - key, - _hard_coded_relation_diagnostic( - owner=owner, literal=literal, relation=relation, match=match - ), - ) - return temporary, found, tuple(unmatched) - - -def _hard_coded_relation_diagnostic( - *, - owner: _PythonSqlOwner, - literal: _LiteralSql, - relation: RelationName, - match: ProjectRelation, -) -> CompilerDiagnostic: - written: str = ".".join( - part for part in (relation.database, relation.schema, relation.name) if part - ) - remedy: str = hard_coded_relation_remedy( - owner_kind=owner.kind, - ref=match.ref, - upstream_loader_by_source=owner.upstream_loader_by_source, - ) - qualify_help: str = ( - f"\n = help: if '{written}' is an external table that shares the name, qualify it " - "with its schema" - if relation.schema is None - else "" - ) - return CompilerDiagnostic( - phase=DiagnosticPhase.COMPILE, - severity=DiagnosticSeverity.ERROR, - code=HARD_CODED_PROJECT_RELATION_CODE, - message=( - old_name_reference_message( - owner_label=owner.label, - written=written, - method=literal.method, - model_name=match.compatibility_for, - ) - if match.compatibility_for is not None - else f"{owner.label} names {match.ref.kind.value}:{match.ref.name} as '{written}' " - f"in SQL passed to ctx.{literal.method}()" - ), - location=SourceLocation(path=owner.relative_path, line=literal.line, column=1), - help=( - f"{remedy}{qualify_help}\n" - " = help: " + explicit_references_help(allowed="hard-coded relation names") - ), - ) diff --git a/src/sqlbuild/compiler/compile/_helpers/macro_bridge/call_store.py b/src/sqlbuild/compiler/compile/_helpers/macro_bridge/call_store.py index 8e8c3238f2..1901cba38e 100644 --- a/src/sqlbuild/compiler/compile/_helpers/macro_bridge/call_store.py +++ b/src/sqlbuild/compiler/compile/_helpers/macro_bridge/call_store.py @@ -6,8 +6,6 @@ from sqlbuild.compiler.compile._helpers.attachment.target import build_compile_target_context from sqlbuild.compiler.discovery.models import DiscoveredProjectInputs -from sqlbuild.compiler.frontier.main.native_stage_enabled import native_stage_enabled -from sqlbuild.compiler.frontier.types import NativeStage from sqlbuild.compiler.macro_bridge.classes.macro_bridge import MacroBridge from sqlbuild.compiler.macro_bridge.main._claim_first_compile import claim_first_compile from sqlbuild.compiler.macro_bridge.main.active_macro_bridge import active_macro_bridge @@ -38,7 +36,6 @@ def target_context_with_macro_call_store( and bridge is not None and compile_cache_dir is not None and project_dir is not None - and native_stage_enabled(NativeStage.MACRO_CALL_STORE) ): bridge.attach_store( cache_dir=compile_cache_dir, diff --git a/src/sqlbuild/compiler/compile/_helpers/macro_bridge/expansion.py b/src/sqlbuild/compiler/compile/_helpers/macro_bridge/expansion.py index dce51b5f95..783a795e89 100644 --- a/src/sqlbuild/compiler/compile/_helpers/macro_bridge/expansion.py +++ b/src/sqlbuild/compiler/compile/_helpers/macro_bridge/expansion.py @@ -3,27 +3,26 @@ from __future__ import annotations from pathlib import Path +from typing import cast from sqlbuild.compiler.compile._helpers.render.macros import ( - _evaluate_macro_call, - _expand_resolved_sql_macros, _expansion_declarations, _record_macro_declaration_usage, _record_macro_use, _report_generated_references, + evaluate_macro_call, + raise_failed_macro_call, ) from sqlbuild.compiler.compile.classes.macro_expansion_facts import MacroExpansionFacts from sqlbuild.compiler.compile.constants import MACRO_TOKEN -from sqlbuild.compiler.compile.exceptions import CompileInputError from sqlbuild.compiler.compile.models import ( DeclarationResolutionContext, ExpansionSpan, MacroExpansionState, ) from sqlbuild.compiler.frontier.exceptions import NativeStageMismatchError -from sqlbuild.compiler.frontier.main.report_native_answer import report_native_answer -from sqlbuild.compiler.frontier.main.report_native_fallback import report_native_fallback -from sqlbuild.compiler.frontier.types import NativeFallbackSite, NativeStage +from sqlbuild.compiler.frontier.main._report_native_fallback import report_native_fallback +from sqlbuild.compiler.frontier.types import NativeFallbackSite from sqlbuild.compiler.macro_bridge.classes.macro_bridge import MacroBridge from sqlbuild.compiler.macro_bridge.constants import ( ARGUMENT_REFERENCE_EVENT, @@ -31,7 +30,13 @@ GENERATED_SQL_EVENT, MACRO_USE_EVENT, ) -from sqlbuild.compiler.macro_bridge.models import MacroCallClass, MacroCallSite +from sqlbuild.compiler.macro_bridge.main._scan_macro_calls import scan_macro_calls +from sqlbuild.compiler.macro_bridge.main._splice_macro_calls import splice_macro_calls +from sqlbuild.compiler.macro_bridge.models import ( + MacroCallClass, + MacroCallScan, + MacroCallSite, +) from sqlbuild.compiler.macro_bridge.types import MacroCallEvent, MacroCallRecord from sqlbuild.compiler.scopes.models import DeclarationIdentity from sqlbuild.compiler.scopes.types import DeclarationKind @@ -46,34 +51,31 @@ def expand_bridged_sql_macros( state: MacroExpansionState, bridge: MacroBridge, ) -> tuple[str, tuple[ExpansionSpan, ...]]: - """Expand one string, replaying memoized calls and running the rest in Python in order.""" + """Expand one string, replaying memoized calls; unresolved trees evaluate calls in order.""" if MACRO_TOKEN not in sql: return sql, () declarations: DeclarationResolutionContext | None = _expansion_declarations( state=state, consumer_path=consumer_path ) - sites: tuple[MacroCallSite, ...] | None = bridge.scan(sql) - call_classes: list[MacroCallClass] = [] - for site in sites or (): - call_class: MacroCallClass | None = bridge.call_class( - site=site, - declarations=declarations, - loaded_macros=state.loaded_macros, - macro_context=state.macro_context, - ) - if call_class is None: - report_native_fallback(site=NativeFallbackSite.MACRO_CALL_RESOLUTION) - sites = None - break - call_classes.append(call_class) - if sites is None: - return _expand_resolved_sql_macros( - sql=sql, - consumer_path=consumer_path, - state=state, - declarations=declarations, - stack=(), + scan: MacroCallScan = bridge.scan(sql) + sites: tuple[MacroCallSite, ...] = scan.sites + call_classes: list[MacroCallClass | None] = ( + [] + if scan.failure is not None + else [ + bridge.call_class( + site=site, + declarations=declarations, + loaded_macros=state.loaded_macros, + macro_context=state.macro_context, + ) + for site in sites + ] + ) + if scan.failure is not None or None in call_classes: + return _unmemoised_sql_macros( + sql=sql, consumer_path=consumer_path, state=state, declarations=declarations, scan=scan ) outputs: list[str] = [ _bridged_call_output( @@ -86,11 +88,8 @@ def expand_bridged_sql_macros( call_class=call_class, ) for site, call_class in zip(sites, call_classes, strict=True) + if call_class is not None ] - mocked: int = sum(bool(state.macro_overrides.keys() & set(site.tree_names)) for site in sites) - report_native_answer( - stage=NativeStage.MACRO_CALLS, kind="bridged_calls", units=len(sites) - mocked - ) return bridge.splice(sql=sql, sites=sites, outputs=outputs) @@ -105,7 +104,7 @@ def _bridged_call_output( # noqa: PLR0913 call_class: MacroCallClass, ) -> str: facts: MacroExpansionFacts = state.facts - if state.macro_overrides.keys() & set(site.tree_names): + if state.macro_overrides.keys() & set(site.tree_names or ()): return _mocked_call_output(sql=sql, consumer_path=consumer_path, state=state, site=site) call_text: str = sql[site.start : site.end] prior_relations: tuple[SqlResourceRef, ...] | None = ( @@ -131,29 +130,15 @@ def _bridged_call_output( # noqa: PLR0913 known_relations: int = len(facts.relations) _ = facts.begin_event_log() try: - macro_result: object - next_index: int - macro_result, next_index = _evaluate_macro_call( + macro_result: str = _top_level_output( sql=sql, - call_start_index=site.start, - file_path=consumer_path, + consumer_path=consumer_path, state=state, declarations=declarations, - stack=(), - top_level=True, + site=site, ) finally: events, replayable = facts.end_event_log() - if not isinstance(macro_result, str): - raise CompileInputError( - f"Macro '@{site.name}' in '{consumer_path}' must return a SQL string when used " - "directly in SQL" - ) - if next_index != site.end: - raise NativeStageMismatchError( - f"Native macro call scan of '{consumer_path}' ended at {site.end}, Python at " - f"{next_index}" - ) added_relations: tuple[SqlResourceRef, ...] = tuple(facts.relations)[known_relations:] if replayable and (prior_relations is not None or not added_relations): bridge.record( @@ -166,35 +151,107 @@ def _bridged_call_output( # noqa: PLR0913 return facts.render_relation_placeholders(macro_result) +def expand_unbridged_sql_macros( + *, sql: str, consumer_path: Path, state: MacroExpansionState +) -> tuple[str, tuple[ExpansionSpan, ...]]: + """Expand one string outside compile inputs: native call sites, each evaluated in order.""" + + if MACRO_TOKEN not in sql: + return sql, () + return _unmemoised_sql_macros( + sql=sql, + consumer_path=consumer_path, + state=state, + declarations=_expansion_declarations(state=state, consumer_path=consumer_path), + scan=scan_macro_calls(sql=sql), + ) + + +def _unmemoised_sql_macros( + *, + sql: str, + consumer_path: Path, + state: MacroExpansionState, + declarations: DeclarationResolutionContext | None, + scan: MacroCallScan, +) -> tuple[str, tuple[ExpansionSpan, ...]]: + """Evaluate every call in order without the memo, raising where Python's scan raises.""" + + outputs: list[str] = [ + _evaluated_call_output( + sql=sql, + consumer_path=consumer_path, + state=state, + declarations=declarations, + site=site, + ) + for site in scan.sites + ] + if scan.failure is not None: + raise_failed_macro_call( + failure=scan.failure, + file_path=consumer_path, + state=state, + declarations=declarations, + ) + return splice_macro_calls(sql=sql, sites=scan.sites, outputs=outputs) + + def _mocked_call_output( *, sql: str, consumer_path: Path, state: MacroExpansionState, site: MacroCallSite ) -> str: """Run a call whose tree a test mocks; its output differs from the shared memo's, so skip it.""" report_native_fallback(site=NativeFallbackSite.MACRO_CALL_MOCKED, kind="test_mock") + return _evaluated_call_output( + sql=sql, + consumer_path=consumer_path, + state=state, + declarations=_expansion_declarations(state=state, consumer_path=consumer_path), + site=site, + ) + + +def _evaluated_call_output( + *, + sql: str, + consumer_path: Path, + state: MacroExpansionState, + declarations: DeclarationResolutionContext | None, + site: MacroCallSite, +) -> str: + """Evaluate one natively scanned call in Python without the memo.""" + + macro_result: str = _top_level_output( + sql=sql, + consumer_path=consumer_path, + state=state, + declarations=declarations, + site=site, + ) + return state.facts.render_relation_placeholders(macro_result) + + +def _top_level_output( + *, + sql: str, + consumer_path: Path, + state: MacroExpansionState, + declarations: DeclarationResolutionContext | None, + site: MacroCallSite, +) -> str: + """One top-level call's SQL; a non-string result raises as Python's top-level check does.""" - macro_result: object - next_index: int - macro_result, next_index = _evaluate_macro_call( + macro_result: object = evaluate_macro_call( sql=sql, - call_start_index=site.start, + site=site, file_path=consumer_path, state=state, - declarations=_expansion_declarations(state=state, consumer_path=consumer_path), + declarations=declarations, stack=(), top_level=True, ) - if not isinstance(macro_result, str): - raise CompileInputError( - f"Macro '@{site.name}' in '{consumer_path}' must return a SQL string when used " - "directly in SQL" - ) - if next_index != site.end: - raise NativeStageMismatchError( - f"Native macro call scan of '{consumer_path}' ended at {site.end}, Python at " - f"{next_index}" - ) - return state.facts.render_relation_placeholders(macro_result) + return cast(str, macro_result) def _replay_macro_call_event( diff --git a/src/sqlbuild/compiler/compile/_helpers/native_stages/assembly.py b/src/sqlbuild/compiler/compile/_helpers/native_stages/assembly.py index 8d44c731cb..cef32f45df 100644 --- a/src/sqlbuild/compiler/compile/_helpers/native_stages/assembly.py +++ b/src/sqlbuild/compiler/compile/_helpers/native_stages/assembly.py @@ -2,7 +2,6 @@ from __future__ import annotations -from functools import partial from typing import Any from sqlbuild.adapter.contract.models import ExpressionInferenceProfile @@ -22,18 +21,11 @@ ) from sqlbuild.compiler.compile._helpers.analysis.pivot_requests import standalone_pivot_models from sqlbuild.compiler.compile._helpers.analysis.syntax_checks import model_syntax_checks -from sqlbuild.compiler.compile._helpers.assembly.semantic_shapes import ( - get_expression_source_shapes, -) from sqlbuild.compiler.compile.models import ( CompileProjectInputs, DynamicColumnContractProof, ModelSqlAnalysis, ) -from sqlbuild.compiler.frontier.main.native_stage_enabled import native_stage_enabled -from sqlbuild.compiler.frontier.main.report_native_answer import report_native_answer -from sqlbuild.compiler.frontier.main.report_native_fallback import report_native_fallback -from sqlbuild.compiler.frontier.types import NativeFallbackSite, NativeStage from sqlbuild.compiler.lineage.types import InferredNullability from sqlbuild.compiler.project_assembly.main._assemble_native_project_resources import ( assemble_native_project_resources, @@ -57,12 +49,10 @@ def project_facts_by_engine( authoritative_column_types_by_table: dict[str, dict[str, str]], column_nullability_by_table: dict[str, dict[str, InferredNullability]], dynamic_families_by_table: dict[str, tuple[SchemaDynamicColumnFamily, ...]], -) -> NativeProjectFacts | None: - """Return the native project facts, or None where Python must derive all of them.""" +) -> NativeProjectFacts: + """Return the native project facts.""" - if not native_stage_enabled(NativeStage.PROJECT_ASSEMBLY): - return None - resources: NativeProjectResources | None = assemble_native_project_resources( + resources: NativeProjectResources = assemble_native_project_resources( inputs=inputs, dialect=dialect, syntax_checks=model_syntax_checks( @@ -75,14 +65,8 @@ def project_facts_by_engine( ), ), ) - if resources is not None: - report_native_answer(stage=NativeStage.PROJECT_ASSEMBLY, kind="project_assemblies") - else: - report_native_fallback(site=NativeFallbackSite.PROJECT_ASSEMBLY) - pivots: dict[int, tuple[str, tuple[SchemaDynamicColumnFamily, ...]]] = ( - standalone_pivot_models(model_inputs=inputs.model_inputs, analyses=analyses) - if native_stage_enabled(NativeStage.MODEL_ANALYSIS) - else {} + pivots: dict[int, tuple[str, tuple[SchemaDynamicColumnFamily, ...]]] = standalone_pivot_models( + model_inputs=inputs.model_inputs, analyses=analyses ) proofs: dict[int, DynamicColumnContractProof | None] = dict( zip( @@ -101,15 +85,12 @@ def project_facts_by_engine( strict=True, ) ) - proven: int = len([proof for proof in proofs.values() if proof is not None]) - report_native_answer( - stage=NativeStage.MODEL_ANALYSIS, kind="dynamic_contract_proofs", units=proven - ) return NativeProjectFacts( models=tuple( NativeModelFacts( - deps=resources.model_deps[index] if resources is not None else None, + deps=resources.model_deps[index], dynamic_contract=proofs.get(index), + syntax_valid=resources.model_syntax_valid[index], ) for index in range(len(inputs.model_inputs)) ), @@ -120,51 +101,15 @@ def project_facts_by_engine( def expression_source_shapes_by_engine( *, expressions: tuple[str, ...], profile: ExpressionInferenceProfile ) -> tuple[dict[str, str] | None, ...]: - """Infer one shape per expression source natively, or with Python where native defers.""" + """Infer one shape per expression source natively.""" - if native_stage_enabled(NativeStage.MODEL_ANALYSIS): - native_shapes: tuple[dict[str, str] | None, ...] | None = ( - infer_native_expression_source_shapes(expressions=expressions, profile=profile) - ) - if native_shapes is not None: - report_native_answer( - stage=NativeStage.MODEL_ANALYSIS, kind="expression_shapes", units=len(native_shapes) - ) - return native_shapes - return get_expression_source_shapes(expressions=expressions, profile=profile) + return infer_native_expression_source_shapes(expressions=expressions, profile=profile) -def analyze_model_sql_by_engine( - *, - python_analysis: partial[dict[str, ModelSqlAnalysis]], - dynamic_families_by_table: dict[str, tuple[SchemaDynamicColumnFamily, ...]], +def analyze_model_sql( + request: NativeModelAnalysisRequest, ) -> tuple[dict[str, ModelSqlAnalysis], Any | None]: - """Analyze models natively, or with Python; also return the finished native session.""" - - if native_stage_enabled(NativeStage.MODEL_ANALYSIS): - native: NativeModelAnalyses | None = analyze_native_model_sql( - request=NativeModelAnalysisRequest( - **python_analysis.keywords, dynamic_families_by_table=dynamic_families_by_table - ) - ) - if native is not None: - report_native_answer( - stage=NativeStage.MODEL_ANALYSIS, kind="model_analyses", units=len(native.analyses) - ) - return native.analyses, native.session - return python_analysis(), None - - -def dynamic_column_contract_by_engine( - *, - sql_analysis: ModelSqlAnalysis | None, - native_proof: DynamicColumnContractProof | None, - python_proof: partial[DynamicColumnContractProof | None], -) -> DynamicColumnContractProof | None: - """Return the proof native analysis carries or proved alone, or prove it in Python.""" + """Analyze models natively; also return the finished session.""" - if sql_analysis is not None and sql_analysis.dynamic_column_contract is not None: - return sql_analysis.dynamic_column_contract - if native_proof is not None: - return native_proof - return python_proof() + native: NativeModelAnalyses = analyze_native_model_sql(request=request) + return native.analyses, native.session diff --git a/src/sqlbuild/compiler/compile/_helpers/native_stages/sql_tests.py b/src/sqlbuild/compiler/compile/_helpers/native_stages/sql_tests.py index 06f93455d9..0f257e5a5f 100644 --- a/src/sqlbuild/compiler/compile/_helpers/native_stages/sql_tests.py +++ b/src/sqlbuild/compiler/compile/_helpers/native_stages/sql_tests.py @@ -1,19 +1,28 @@ -"""Hand compiled SQL test assembly to its native stage when enabled.""" +"""Assemble every SQL test natively; macro-mocked tests' model queries run the user's macros.""" from __future__ import annotations +import decimal from collections.abc import Callable +from dataclasses import replace +import sqlbuild._native as _native from sqlbuild.compiler.compile._helpers.diagnostics.collector import report_compile_diagnostic +from sqlbuild.compiler.compile.exceptions import CompileInputError from sqlbuild.compiler.compile.models import ( + CompiledModelSqlTestPayload, CompiledSqlTest, + CompileModelSqlTestInputPayload, CompileProjectInputs, CompileSqlTestInput, ) -from sqlbuild.compiler.frontier.main.native_stage_enabled import native_stage_enabled -from sqlbuild.compiler.frontier.main.report_native_answer import report_native_answer -from sqlbuild.compiler.frontier.main.report_native_fallback import report_native_fallback -from sqlbuild.compiler.frontier.types import NativeFallbackSite, NativeStage +from sqlbuild.compiler.frontier.main._report_native_fallback import report_native_fallback +from sqlbuild.compiler.frontier.types import NativeFallbackSite +from sqlbuild.compiler.sql_test_glue.constants import ( + SQL_TEST_DECIMAL_OVERFLOW, + SQL_TEST_EXTENSION_CALLBACK, + SQL_TEST_INPUT_FAILURE, +) from sqlbuild.compiler.sql_test_glue.main._assemble_native_sql_tests import ( assemble_native_sql_tests, ) @@ -23,21 +32,36 @@ def assemble_sql_tests_by_engine( *, inputs: CompileProjectInputs, - assemble_python_test: Callable[[CompileSqlTestInput], CompiledSqlTest], + macro_mock_queries: Callable[[CompileSqlTestInput], dict[str, str]], ) -> tuple[CompiledSqlTest, ...]: - """Assemble every SQL test natively, or each test in Python where native defers.""" + """Assemble every SQL test natively, raising errors in Python's assembly order.""" - if not native_stage_enabled(NativeStage.SQL_TEST_GLUE): - return tuple(assemble_python_test(test_input) for test_input in inputs.test_inputs) - native: tuple[NativeSqlTestAssembly | None, ...] = assemble_native_sql_tests(inputs=inputs) + native: tuple[NativeSqlTestAssembly, ...] = assemble_native_sql_tests(inputs=inputs) tests: list[CompiledSqlTest] = [] for test_input, assembly in zip(inputs.test_inputs, native, strict=True): - if assembly is None: - report_native_fallback(site=NativeFallbackSite.SQL_TEST_ASSEMBLY) - tests.append(assemble_python_test(test_input)) - continue + if assembly.test is None: + message: str = assembly.failure.message if assembly.failure is not None else "" + if assembly.failure is not None and assembly.failure.kind == SQL_TEST_INPUT_FAILURE: + raise CompileInputError(message) + raise _native.NativeCompilerError(message) for key, diagnostic in assembly.diagnostics: report_compile_diagnostic(key=key, diagnostic=diagnostic) - report_native_answer(stage=NativeStage.SQL_TEST_GLUE, kind="sql_test_assemblies") - tests.append(assembly.test) + test: CompiledSqlTest = assembly.test + payload: object = test_input.payload + if isinstance(payload, CompileModelSqlTestInputPayload) and payload.macro_mocks: + report_native_fallback( + site=NativeFallbackSite.SQL_TEST_MACRO_MOCK_QUERIES, + kind=SQL_TEST_EXTENSION_CALLBACK, + ) + test = _with_model_queries(test=test, queries=macro_mock_queries(test_input)) + if assembly.failure is not None and assembly.failure.kind == SQL_TEST_DECIMAL_OVERFLOW: + raise decimal.Overflow([decimal.Overflow]) + tests.append(test) return tuple(tests) + + +def _with_model_queries(*, test: CompiledSqlTest, queries: dict[str, str]) -> CompiledSqlTest: + payload: object = test.payload + if not isinstance(payload, CompiledModelSqlTestPayload): + return test + return replace(test, payload=replace(payload, model_query_overrides=queries)) diff --git a/src/sqlbuild/compiler/compile/_helpers/refs/references.py b/src/sqlbuild/compiler/compile/_helpers/refs/references.py index 31da788a7e..ce170e1ba8 100644 --- a/src/sqlbuild/compiler/compile/_helpers/refs/references.py +++ b/src/sqlbuild/compiler/compile/_helpers/refs/references.py @@ -26,8 +26,6 @@ DiagnosticSeverity, SqlReferenceScanFailure, ) -from sqlbuild.compiler.frontier.main.report_native_answer import report_native_answer -from sqlbuild.compiler.frontier.types import NativeStage from sqlbuild.compiler.sql_analysis.models import SqlLexicalSyntax from sqlbuild.spec.contracts.models import SourceLocation @@ -61,7 +59,6 @@ def _reference_scan_outcome( outcome: SqlReferenceScan | SqlReferenceScanFailure = extract_native_sql_references( sql=sql, syntax=syntax ) - report_native_answer(stage=NativeStage.REFERENCE_EXTRACTION, kind="reference_scans") return outcome diff --git a/src/sqlbuild/compiler/compile/_helpers/render/cursor_intrinsics.py b/src/sqlbuild/compiler/compile/_helpers/render/cursor_intrinsics.py index efa9c139fd..dcfc1b6832 100644 --- a/src/sqlbuild/compiler/compile/_helpers/render/cursor_intrinsics.py +++ b/src/sqlbuild/compiler/compile/_helpers/render/cursor_intrinsics.py @@ -7,8 +7,6 @@ import sqlbuild._native as _native from sqlbuild.compiler.compile.exceptions import CompileInputError -from sqlbuild.compiler.frontier.main.report_native_answer import report_native_answer -from sqlbuild.compiler.frontier.types import NativeStage from sqlbuild.compiler.planner.constants import ( MICROBATCH_END_SENTINEL, MICROBATCH_START_SENTINEL, @@ -35,7 +33,6 @@ def get_validated_model_cursor_intrinsics( (model_name, config_values.get("materialized"), config_values.get("cursor")), _PYTHON, ) - report_native_answer(stage=NativeStage.MODEL_LOOP, kind="cursor_intrinsic_validations") if error is not None: raise CompileInputError(error) return str(canonical_sql) @@ -47,7 +44,6 @@ def reject_cursor_intrinsics(*, sql: str, context: str) -> None: error: str | None = _native.cursor_intrinsics_rejection( sql, _RESERVED_MARKERS, context, _PYTHON ) - report_native_answer(stage=NativeStage.ATTACHMENTS, kind="cursor_intrinsic_rejections") if error is not None: raise CompileInputError(error) diff --git a/src/sqlbuild/compiler/compile/_helpers/render/declarations.py b/src/sqlbuild/compiler/compile/_helpers/render/declarations.py index 075bfd2a9c..25c57555fe 100644 --- a/src/sqlbuild/compiler/compile/_helpers/render/declarations.py +++ b/src/sqlbuild/compiler/compile/_helpers/render/declarations.py @@ -2,14 +2,12 @@ from __future__ import annotations -import re from collections.abc import Mapping from dataclasses import replace from pathlib import Path from types import MappingProxyType from typing import cast -from sqlbuild.compiler.compile.constants import MACRO_TOKEN, SQL_QUOTE_TOKENS from sqlbuild.compiler.compile.exceptions import CompileInputError from sqlbuild.compiler.compile.models import ( DeclarationExpansionContext, @@ -32,10 +30,8 @@ EnumMember, ModelSchemaDeclaration, ) -from sqlbuild.compiler.frontier.main.native_stage_enabled import native_stage_enabled -from sqlbuild.compiler.frontier.main.report_native_answer import report_native_answer -from sqlbuild.compiler.frontier.main.report_native_fallback import report_native_fallback -from sqlbuild.compiler.frontier.types import NativeFallbackSite, NativeStage +from sqlbuild.compiler.frontier.main._report_native_fallback import report_native_fallback +from sqlbuild.compiler.frontier.types import NativeFallbackSite from sqlbuild.compiler.model_loop.constants import ( ENUM_REFERENCE_KIND_CODE, INVALID_CONSTANT_REFERENCE_STOP_CODE, @@ -45,6 +41,9 @@ from sqlbuild.compiler.model_loop.main._build_native_declaration_contexts import ( build_native_declaration_contexts, ) +from sqlbuild.compiler.model_loop.main._scan_native_declaration_references import ( + scan_native_declaration_references, +) from sqlbuild.compiler.model_loop.types import NativeDeclarationScan from sqlbuild.compiler.planner.types import ContractPolicy from sqlbuild.compiler.scopes.constants import CURRENT_PATH_COMPONENT, QUALIFIED_IDENTITY_SEPARATOR @@ -71,24 +70,11 @@ ScopeKind, UsageKind, ) -from sqlbuild.compiler.sql_analysis.main._skip_block_comment import skip_block_comment -from sqlbuild.compiler.sql_analysis.main._skip_line_comment import skip_line_comment -from sqlbuild.compiler.sql_analysis.main._skip_quoted_text import skip_quoted_text from sqlbuild.spec.contracts.models import SchemaAuditInstance, SchemaColumn, SchemaModelEntry from sqlbuild.sql_values.exceptions import SqlValueRenderingError, SqlValueValidationError from sqlbuild.sql_values.main.validate_rendered_size import validate_rendered_sql_value_size from sqlbuild.sql_values.types import CollectionRendering, SqlValueKind -_ENUM_REFERENCE_PATTERN: re.Pattern[str] = re.compile( - r"@enum\s*\(\s*(?P['\"])(?P[A-Za-z_][A-Za-z0-9_]*)" - r"(?P=quote)\s*\)\s*\.\s*(?P[A-Za-z_][A-Za-z0-9_]*)" -) -_CONSTANT_REFERENCE_PATTERN: re.Pattern[str] = re.compile( - r"@const\s*\(\s*(?P['\"])(?P[A-Za-z_][A-Za-z0-9_]*)" - r"(?P=quote)\s*\)" -) -_DECLARATION_REFERENCE_START_PATTERN: re.Pattern[str] = re.compile(r"@(?Penum|const)\b") -_DECLARATION_SCAN_SPECIAL: re.Pattern[str] = re.compile(r"['\"`$@/-]") _CONTEXT: str = "Enum and constant expansion" _ACCEPTED_VALUES_AUDIT: str = "accepted_values" _ENUM_REFERENCE_KIND: str = "enum" @@ -165,7 +151,7 @@ def build_declaration_scope_resolver( if loaded_macros is not None: for macro in loaded_macros.values(): declarations[DeclarationIdentity(DeclarationKind.MACRO, macro.name)] = macro - if lookup is None and native_stage_enabled(NativeStage.DECLARATION_SCOPES): + if lookup is None: report_native_fallback(site=NativeFallbackSite.SCOPE_REBIND_LOOKUP) scope_lookup: ScopeLookup = build_scope_lookup(index=scope_index) if lookup is None else lookup return DeclarationScopeResolver( @@ -229,7 +215,6 @@ def resolve_declaration_context( context: DeclarationResolutionContext = resolver.native_contexts.context( list(matches), consumer ) - report_native_answer(stage=NativeStage.MODEL_LOOP, kind="declaration_contexts") if cache_key is not None: resolver.cache_context(key=cache_key, context=context) return context @@ -315,39 +300,25 @@ def declaration_usage_records( ) -> tuple[UsageRecord, ...]: """Collect declaration usages with path or expected-model provenance.""" + scanned, stop = scan_native_declaration_references(sqls=(sql,), skip_malformed=True)[0] + if stop is not None: + raise CompileInputError(_unclosed_text_message(stop)) usages: list[UsageRecord] = [] - cursor: int = 0 - while (reference_start := _find_next_reference_start(sql=sql, start=cursor)) is not None: - start_match: re.Match[str] | None = _DECLARATION_REFERENCE_START_PATTERN.match( - sql, reference_start - ) - if start_match is None: - break - is_enum: bool = start_match.group("kind") == _ENUM_REFERENCE_KIND - match: re.Match[str] | None = ( - _ENUM_REFERENCE_PATTERN.match(sql, reference_start) - if is_enum - else _CONSTANT_REFERENCE_PATTERN.match(sql, reference_start) - ) - if match is None: - cursor = start_match.end() - continue - name: str = match.group("name") + for kind, name, _member, _start, _end in scanned: visibility: tuple[VisibilityRecord, ...] = ( declarations.enum_visibility.get(name, ()) - if is_enum + if kind == ENUM_REFERENCE_KIND_CODE else declarations.constant_visibility.get(name, ()) ) - for record in usage_visibility(visibility=visibility, consumer=resource): - usages.append( - UsageRecord( - consumer=resource, - declaration=record.declaration, - kind=UsageKind.RUNTIME, - through=record.through, - ) + usages.extend( + UsageRecord( + consumer=resource, + declaration=record.declaration, + kind=UsageKind.RUNTIME, + through=record.through, ) - cursor = match.end() + for record in usage_visibility(visibility=visibility, consumer=resource) + ) return tuple(dict.fromkeys(usages)) @@ -573,6 +544,10 @@ def _stop_message(*, stop: int, file_path: Path) -> str: return _invalid_reference_message(kind=_ENUM_REFERENCE_KIND, file_path=file_path) if stop == INVALID_CONSTANT_REFERENCE_STOP_CODE: return _invalid_reference_message(kind=_CONSTANT_REFERENCE_KIND, file_path=file_path) + return _unclosed_text_message(stop) + + +def _unclosed_text_message(stop: int) -> str: if stop == UNCLOSED_BLOCK_COMMENT_STOP_CODE: return f"{_CONTEXT} contains an unclosed block comment" return f"{_CONTEXT} contains an unclosed quoted string" @@ -773,28 +748,3 @@ def render_enum_member_value(*, value: str | int) -> str: return str(value) escaped_value: str = value.replace("'", "''") return f"'{escaped_value}'" - - -def _find_next_reference_start(*, sql: str, start: int) -> int | None: - if sql.find("@enum", start) < 0 and sql.find("@const", start) < 0: - return None - index: int = start - while index < len(sql): - special: re.Match[str] | None = _DECLARATION_SCAN_SPECIAL.search(sql, index) - if special is None: - return None - index = special.start() - character: str = sql[index] - if character in SQL_QUOTE_TOKENS: - index = skip_quoted_text(sql=sql, start=index, context=_CONTEXT) - continue - if sql.startswith("--", index): - index = skip_line_comment(sql=sql, start=index) - continue - if sql.startswith("/*", index): - index = skip_block_comment(sql=sql, start=index, context=_CONTEXT) - continue - if character == MACRO_TOKEN and _DECLARATION_REFERENCE_START_PATTERN.match(sql, index): - return index - index += 1 - return None diff --git a/src/sqlbuild/compiler/compile/_helpers/render/macro_argument_values.py b/src/sqlbuild/compiler/compile/_helpers/render/macro_argument_values.py index f6fd2b75ca..856cda760a 100644 --- a/src/sqlbuild/compiler/compile/_helpers/render/macro_argument_values.py +++ b/src/sqlbuild/compiler/compile/_helpers/render/macro_argument_values.py @@ -16,8 +16,6 @@ ) from sqlbuild.compiler.compile.exceptions import MacroArgumentError from sqlbuild.compiler.compile.models import ParsedMacroArguments -from sqlbuild.compiler.frontier.main.report_native_answer import report_native_answer -from sqlbuild.compiler.frontier.types import NativeStage type _ValueRow = tuple[object, ...] type _BuildContext = tuple[Sequence[object], Callable[..., MacroArgumentError]] @@ -74,7 +72,6 @@ def argument_error(*, offset: int, detail: str, help_text: str) -> MacroArgument help_text=cast(str, help_text), ) _, positional, keywords, references = parsed - report_native_answer(stage=NativeStage.MACRO_CALLS, kind="parsed_arguments") def unary_error(*, call: int, sign: str) -> MacroArgumentError: value: object = nested_values[call] diff --git a/src/sqlbuild/compiler/compile/_helpers/render/macros.py b/src/sqlbuild/compiler/compile/_helpers/render/macros.py index c2475554b7..b039839358 100644 --- a/src/sqlbuild/compiler/compile/_helpers/render/macros.py +++ b/src/sqlbuild/compiler/compile/_helpers/render/macros.py @@ -6,7 +6,6 @@ import hashlib import heapq import inspect -import re import sys import threading from collections.abc import Callable, Iterator, Mapping @@ -14,8 +13,9 @@ from dataclasses import dataclass, replace from pathlib import Path from types import MappingProxyType, ModuleType -from typing import cast +from typing import NoReturn, cast +import sqlbuild._native as _native from sqlbuild.compiler.compile._helpers.explicit_references.macro_arguments import ( call_site_sql_references, reject_macro_generated_references, @@ -28,9 +28,6 @@ from sqlbuild.compiler.compile.constants import ( DECLARATION_REFERENCE_NAMES, MACRO_CONTEXT_PARAMETER_NAME, - MACRO_TOKEN, - SQL_OPEN_PAREN_TOKEN, - SQL_QUOTE_TOKENS, ) from sqlbuild.compiler.compile.exceptions import ( CompileInputError, @@ -55,9 +52,6 @@ DiscoveredMacroFile, EnumDeclaration, ) -from sqlbuild.compiler.frontier.main.native_stage_enabled import native_stage_enabled -from sqlbuild.compiler.frontier.main.report_native_fallback import report_native_fallback -from sqlbuild.compiler.frontier.types import NativeFallbackSite, NativeStage from sqlbuild.compiler.macro_bridge.classes.macro_bridge import MacroBridge from sqlbuild.compiler.macro_bridge.constants import ( DECLARATION_READ_EVENT, @@ -65,7 +59,9 @@ GENERATED_SQL_EVENT, MACRO_USE_EVENT, ) +from sqlbuild.compiler.macro_bridge.main._scan_macro_calls import scan_macro_calls from sqlbuild.compiler.macro_bridge.main.active_macro_bridge import active_macro_bridge +from sqlbuild.compiler.macro_bridge.models import MacroCallScan, MacroCallSite, MacroScanFailure from sqlbuild.compiler.resource_names.main._validate_resource_identity import ( validate_resource_identity, ) @@ -77,25 +73,11 @@ VisibilityRecord, ) from sqlbuild.compiler.scopes.types import DeclarationKind, ResourceKind, ScopeKind, UsageKind -from sqlbuild.compiler.sql_analysis.main._find_matching_paren import find_matching_paren -from sqlbuild.compiler.sql_analysis.main._is_identifier_character import ( - is_identifier_character as _is_identifier_continue, -) -from sqlbuild.compiler.sql_analysis.main._is_identifier_start import ( - is_identifier_start as _is_identifier_start, -) -from sqlbuild.compiler.sql_analysis.main._skip_block_comment import skip_block_comment -from sqlbuild.compiler.sql_analysis.main._skip_line_comment import skip_line_comment -from sqlbuild.compiler.sql_analysis.main._skip_quoted_text import skip_quoted_text from sqlbuild.python_nodes.models import RELATION_RENDERER, SqlResourceRef from sqlbuild.sql_values.models import SqlValue from sqlbuild.sql_values.types import SqlValueKind -_CONTEXT: str = "Macro expansion" -_LINE_COMMENT_TOKEN: str = "--" -_BLOCK_COMMENT_TOKEN: str = "/*" _STAR_IMPORT_NAME: str = "*" -_MACRO_SCAN_PATTERN: re.Pattern[str] = re.compile(r"@|--|/\*|'|\"|`|\$") _SYNTHETIC_PACKAGE_PREFIX: str = "_sqlbuild_project_macros_" _OBJECT_ENTRY_LENGTH: int = 2 _MACRO_MODULE_LOAD_LOCK: threading.RLock = threading.RLock() @@ -258,20 +240,6 @@ def load_project_macros(macro_files: tuple[DiscoveredMacroFile, ...]) -> dict[st return loaded_macros -def _inventory_project_macros( - *, macro_files: tuple[DiscoveredMacroFile, ...] -) -> StaticMacroInventory: - """Validate and inventory project macro exports without executing authored code.""" - - try: - analyses: dict[str, _MacroModuleAnalysis] = _analyze_project_macro_modules( - macro_files=macro_files - ) - except CompileInputError: - return _inventory_project_macros_tolerantly(macro_files=macro_files) - return _inventory_from_analyses(macro_files=macro_files, analyses=analyses) - - def _macro_inventory_fault( *, error: CompileInputError, macro_files: tuple[DiscoveredMacroFile, ...] ) -> StaticMacroFault: @@ -1218,24 +1186,8 @@ def expand_sql_macros_result( consumer=consumer, ) bridge: MacroBridge | None = active_macro_bridge() - if bridge is None and MACRO_TOKEN in sql and native_stage_enabled(NativeStage.MACRO_CALLS): - report_native_fallback( - site=NativeFallbackSite.MACRO_UNBRIDGED_EXPANSION, kind="outside_compile_inputs" - ) - expanded_sql, spans = ( - _expand_sql_macros( - sql=sql, - consumer_path=file_path, - state=state, - stack=(), - ) - if bridge is None - else _bridged_sql_macros( - sql=sql, - consumer_path=file_path, - state=state, - bridge=bridge, - ) + expanded_sql, spans = _bridged_sql_macros( + sql=sql, consumer_path=file_path, state=state, bridge=bridge ) return MacroExpansionResult( sql=expanded_sql, @@ -1247,33 +1199,32 @@ def expand_sql_macros_result( def _bridged_sql_macros( - *, sql: str, consumer_path: Path, state: MacroExpansionState, bridge: MacroBridge + *, sql: str, consumer_path: Path, state: MacroExpansionState, bridge: MacroBridge | None ) -> tuple[str, tuple[ExpansionSpan, ...]]: from sqlbuild.compiler.compile._helpers.macro_bridge.expansion import ( expand_bridged_sql_macros, + expand_unbridged_sql_macros, ) + if bridge is None: + return expand_unbridged_sql_macros(sql=sql, consumer_path=consumer_path, state=state) return expand_bridged_sql_macros( sql=sql, consumer_path=consumer_path, state=state, bridge=bridge ) -def _expand_sql_macros( - *, - sql: str, - consumer_path: Path, - state: MacroExpansionState, - stack: tuple[DeclarationIdentity, ...], -) -> tuple[str, tuple[ExpansionSpan, ...]]: - if MACRO_TOKEN not in sql: - return sql, () - return _expand_resolved_sql_macros( - sql=sql, - consumer_path=consumer_path, - state=state, - declarations=_expansion_declarations(state=state, consumer_path=consumer_path), - stack=stack, - ) +def _inventory_project_macros( + *, macro_files: tuple[DiscoveredMacroFile, ...] +) -> StaticMacroInventory: + """Validate and inventory project macro exports without executing authored code.""" + + try: + analyses: dict[str, _MacroModuleAnalysis] = _analyze_project_macro_modules( + macro_files=macro_files + ) + except CompileInputError: + return _inventory_project_macros_tolerantly(macro_files=macro_files) + return _inventory_from_analyses(macro_files=macro_files, analyses=analyses) def _expansion_declarations( @@ -1291,62 +1242,13 @@ def _expansion_declarations( return declarations -def _expand_resolved_sql_macros( - *, - sql: str, - consumer_path: Path, - state: MacroExpansionState, - declarations: DeclarationResolutionContext | None, - stack: tuple[DeclarationIdentity, ...], -) -> tuple[str, tuple[ExpansionSpan, ...]]: - rendered_sql_parts: list[str] = [] - spans: list[ExpansionSpan] = [] - output_length: int = 0 - cursor: int = 0 - while cursor < len(sql): - macro_start_index: int | None = _find_next_macro_start(sql=sql, start_index=cursor) - if macro_start_index is None: - rendered_sql_parts.append(sql[cursor:]) - break - leading_literal: str = sql[cursor:macro_start_index] - rendered_sql_parts.append(leading_literal) - output_length += len(leading_literal) - macro_result: object - next_index: int - macro_result, next_index = _evaluate_macro_call( - sql=sql, - call_start_index=macro_start_index, - file_path=consumer_path, - state=state, - declarations=declarations, - stack=stack, - top_level=True, - ) - if not isinstance(macro_result, str): - raise CompileInputError( - f"Macro '@{_parse_macro_name(sql=sql, call_start_index=macro_start_index)}' in " - f"'{consumer_path}' must return a SQL string when used directly in SQL" - ) - macro_result = state.facts.render_relation_placeholders(macro_result) - rendered_sql_parts.append(macro_result) - spans.append( - ExpansionSpan( - source_start=macro_start_index, - source_end=next_index, - output_start=output_length, - output_end=output_length + len(macro_result), - ) - ) - output_length += len(macro_result) - cursor = next_index - return "".join(rendered_sql_parts), tuple(spans) - - def find_macro_call_names(sql: str) -> tuple[str, ...]: """Return unique authored macro call names in encounter order.""" return tuple( - name for name in _find_sqlbuild_call_names(sql) if name not in DECLARATION_REFERENCE_NAMES + name + for name in _native_macro_call_names(sql=sql, nested=False) + if name not in DECLARATION_REFERENCE_NAMES ) @@ -1355,60 +1257,53 @@ def find_nested_macro_call_names(sql: str) -> tuple[str, ...]: return tuple( name - for name in _scan_sqlbuild_call_names(sql=sql, include_nested=True) + for name in _native_macro_call_names(sql=sql, nested=True) if name not in DECLARATION_REFERENCE_NAMES ) -def _find_sqlbuild_call_names(sql: str) -> tuple[str, ...]: - """Return executable SQLBuild call names, excluding quoted and commented text.""" +def _native_macro_call_names(*, sql: str, nested: bool) -> tuple[str, ...]: + """Every call name Python's scan finds, declaration calls included.""" - return _scan_sqlbuild_call_names(sql=sql, include_nested=False) + names: list[str] | None + message: str | None + names, message = _native.macro_call_names(sql, nested) + if names is None: + raise CompileInputError(message or "") + return tuple(names) -def _scan_sqlbuild_call_names(*, sql: str, include_nested: bool) -> tuple[str, ...]: - if MACRO_TOKEN not in sql: - return () +def raise_failed_macro_call( + *, + failure: MacroScanFailure, + file_path: Path, + state: MacroExpansionState, + declarations: DeclarationResolutionContext | None, +) -> NoReturn: + """Raise where Python's scan raises: the failing call's macro lookup error, else the scan's.""" - names: list[str] = [] - seen: set[str] = set() - cursor: int = 0 - while cursor < len(sql): - macro_start_index: int | None = _find_next_macro_start(sql=sql, start_index=cursor) - if macro_start_index is None: - break - macro_name: str = _parse_macro_name(sql=sql, call_start_index=macro_start_index) - if macro_name not in seen: - seen.add(macro_name) - names.append(macro_name) - opening_paren_index: int = _skip_whitespace( - sql=sql, start_index=macro_start_index + 1 + len(macro_name) - ) - cursor = ( - opening_paren_index + 1 - if include_nested - else _find_matching_paren(sql=sql, opening_paren_index=opening_paren_index) + 1 + if failure.call_name is not None: + _ = _resolved_macro( + macro_name=failure.call_name, + file_path=file_path, + state=state, + declarations=declarations, ) - return tuple(names) + raise CompileInputError(failure.message) -def _evaluate_macro_call( +def _resolved_macro( *, - sql: str, - call_start_index: int, + macro_name: str, file_path: Path, state: MacroExpansionState, declarations: DeclarationResolutionContext | None, - stack: tuple[DeclarationIdentity, ...], - top_level: bool, -) -> tuple[object, int]: - macro_name: str = _parse_macro_name(sql=sql, call_start_index=call_start_index) +) -> LoadedMacro: loaded_macro: LoadedMacro | None = ( declarations.macros.get(macro_name) if declarations is not None else state.loaded_macros.get(macro_name) ) - override_value: str | None = state.macro_overrides.get(macro_name) if declarations is not None and macro_name in declarations.inaccessible_macros: record: DeclarationRecord = declarations.inaccessible_macros[macro_name] suggestions: str = ", ".join(sorted(declarations.macros)) or "none" @@ -1425,17 +1320,31 @@ def _evaluate_macro_call( f"Unknown macro '@{macro_name}' in '{file_path}'. Available macros: " f"{available_macro_names}" ) - opening_paren_index: int = _skip_whitespace( - sql=sql, start_index=call_start_index + 1 + len(macro_name) - ) - closing_paren_index: int = _find_matching_paren( - sql=sql, opening_paren_index=opening_paren_index + return loaded_macro + + +def evaluate_macro_call( + *, + sql: str, + site: MacroCallSite, + file_path: Path, + state: MacroExpansionState, + declarations: DeclarationResolutionContext | None, + stack: tuple[DeclarationIdentity, ...], + top_level: bool, +) -> object: + """Run one natively scanned call: its nested calls, then the macro, in Python's order.""" + + macro_name: str = site.name + loaded_macro: LoadedMacro = _resolved_macro( + macro_name=macro_name, file_path=file_path, state=state, declarations=declarations ) + override_value: str | None = state.macro_overrides.get(macro_name) if override_value is not None: _validate_final_macro_sql( macro_name=macro_name, file_path=file_path, macro_result=override_value ) - return override_value, closing_paren_index + 1 + return override_value identity: DeclarationIdentity = ( declarations.macro_records[macro_name].identity if declarations is not None @@ -1457,7 +1366,7 @@ def _evaluate_macro_call( declarations=declarations, stack=stack, ) - args_source: str = sql[opening_paren_index + 1 : closing_paren_index] + args_source: str = sql[site.args_start : site.end - 1] args: tuple[object, ...] kwargs: dict[str, object] _ = state.facts.open_call_site() @@ -1471,7 +1380,7 @@ def _evaluate_macro_call( stack=stack, ) except MacroArgumentError as error: - raise error.shifted(opening_paren_index + 1) from None + raise error.shifted(site.args_start) from None finally: approved: frozenset[SqlResourceRef] = state.facts.close_call_site() try: @@ -1520,7 +1429,7 @@ def _evaluate_macro_call( file_path=file_path, state=state, ) - return macro_result, closing_paren_index + 1 + return macro_result def _record_macro_use( @@ -1760,7 +1669,7 @@ def _validate_final_macro_sql(*, macro_name: str, file_path: Path, macro_result: "bytes decoded with errors='surrogateescape'" ), ) from None - generated_calls: tuple[str, ...] = _find_sqlbuild_call_names(macro_result) + generated_calls: tuple[str, ...] = _native_macro_call_names(sql=macro_result, nested=False) if not generated_calls: return calls: str = ", ".join(f"@{name}()" for name in generated_calls) @@ -1800,22 +1709,24 @@ def _parse_macro_arguments( ) -> tuple[tuple[object, ...], dict[str, object]]: if not args_source.strip(): return (), {} - nested: list[tuple[int, int]] = [] - nested_values: list[object] = [] - cursor: int = 0 - while (start := _find_next_macro_start(sql=args_source, start_index=cursor)) is not None: - nested_value: object - nested_value, cursor = _evaluate_macro_call( + scan: MacroCallScan = scan_macro_calls(sql=args_source) + nested: list[tuple[int, int]] = [(site.start, site.end) for site in scan.sites] + nested_values: list[object] = [ + evaluate_macro_call( sql=args_source, - call_start_index=start, + site=site, file_path=file_path, state=state, declarations=declarations, stack=stack, top_level=False, ) - nested.append((start, cursor)) - nested_values.append(nested_value) + for site in scan.sites + ] + if scan.failure is not None: + raise_failed_macro_call( + failure=scan.failure, file_path=file_path, state=state, declarations=declarations + ) parsed: ParsedMacroArguments = parse_macro_call_arguments( args_source=args_source, nested=tuple(nested), @@ -1825,55 +1736,3 @@ def _parse_macro_arguments( ) state.facts.record_call_site_refs(parsed.typed_references) return parsed.args, parsed.kwargs - - -def _find_next_macro_start(*, sql: str, start_index: int) -> int | None: - index: int = start_index - while True: - match: re.Match[str] | None = _MACRO_SCAN_PATTERN.search(sql, index) - if match is None: - return None - index = match.start() - token: str = match.group() - if token in SQL_QUOTE_TOKENS: - index = skip_quoted_text(sql=sql, start=index, context=_CONTEXT) - continue - if token == _LINE_COMMENT_TOKEN: - index = skip_line_comment(sql=sql, start=index) - continue - if token == _BLOCK_COMMENT_TOKEN: - index = skip_block_comment(sql=sql, start=index, context=_CONTEXT) - continue - if _is_macro_call_start(sql=sql, at_index=index): - return index - index += 1 - - -def _is_macro_call_start(*, sql: str, at_index: int) -> bool: - if at_index + 1 >= len(sql) or not _is_identifier_start(sql[at_index + 1]): - return False - cursor: int = at_index + 2 - while cursor < len(sql) and _is_identifier_continue(sql[cursor]): - cursor += 1 - cursor = _skip_whitespace(sql=sql, start_index=cursor) - return cursor < len(sql) and sql[cursor] == SQL_OPEN_PAREN_TOKEN - - -def _parse_macro_name(*, sql: str, call_start_index: int) -> str: - cursor: int = call_start_index + 1 - while cursor < len(sql) and _is_identifier_continue(sql[cursor]): - cursor += 1 - return sql[call_start_index + 1 : cursor] - - -def _find_matching_paren(*, sql: str, opening_paren_index: int) -> int: - if opening_paren_index >= len(sql) or sql[opening_paren_index] != SQL_OPEN_PAREN_TOKEN: - raise CompileInputError("expected opening parenthesis") - return find_matching_paren(sql=sql, open_paren_index=opening_paren_index, context=_CONTEXT) - - -def _skip_whitespace(*, sql: str, start_index: int) -> int: - index: int = start_index - while index < len(sql) and sql[index].isspace(): - index += 1 - return index diff --git a/src/sqlbuild/compiler/compile/_helpers/render/parameters.py b/src/sqlbuild/compiler/compile/_helpers/render/parameters.py index 4dbb3e6c65..4aaaa82799 100644 --- a/src/sqlbuild/compiler/compile/_helpers/render/parameters.py +++ b/src/sqlbuild/compiler/compile/_helpers/render/parameters.py @@ -6,14 +6,8 @@ from pathlib import Path import sqlbuild._native as _native -from sqlbuild.compiler.compile.constants import SQL_QUOTE_TOKENS from sqlbuild.compiler.compile.exceptions import CompileInputError from sqlbuild.compiler.compile.types import TypedSqlValueRenderer -from sqlbuild.compiler.frontier.main.native_stage_enabled import native_stage_enabled -from sqlbuild.compiler.frontier.types import NativeStage -from sqlbuild.compiler.sql_analysis.main._skip_block_comment import skip_block_comment -from sqlbuild.compiler.sql_analysis.main._skip_line_comment import skip_line_comment -from sqlbuild.compiler.sql_analysis.main._skip_quoted_text import skip_quoted_text from sqlbuild.sql_values.exceptions import SqlValueRenderingError, SqlValueValidationError from sqlbuild.sql_values.main.validate_rendered_size import validate_rendered_sql_value_size from sqlbuild.sql_values.models import SqlValue @@ -36,71 +30,20 @@ def expand_test_parameters( """Render active parameter references while leaving comments and quoted text unchanged.""" value_lookup: dict[str, SqlValue] = dict(values) - if native_stage_enabled(NativeStage.ATTACHMENTS): - references, error = _native.scan_test_parameter_references( - sql, list(value_lookup), f"SQL test '{test_name}' case '{case_name}' in '{file_path}'" - ) - expanded: tuple[str, frozenset[str]] = _splice_parameter_references( - sql=sql, - references=references, - value_lookup=value_lookup, - value_renderer=value_renderer, - test_name=test_name, - case_name=case_name, - ) - if error is not None: - raise CompileInputError(error) - return expanded - used_names: set[str] = set() - parts: list[str] = [] - cursor: int = 0 - while cursor < len(sql): - character: str = sql[cursor] - if character in SQL_QUOTE_TOKENS: - end: int = skip_quoted_text(sql=sql, start=cursor) - parts.append(sql[cursor:end]) - cursor = end - continue - if sql.startswith("--", cursor): - end = skip_line_comment(sql=sql, start=cursor) - parts.append(sql[cursor:end]) - cursor = end - continue - if sql.startswith("/*", cursor): - end = skip_block_comment(sql=sql, start=cursor) - parts.append(sql[cursor:end]) - cursor = end - continue - if _PARAMETER_TOKEN.match(sql, cursor): - match: re.Match[str] | None = _PARAMETER_REFERENCE.match(sql, cursor) - if match is None: - raise CompileInputError( - f"SQL test '{test_name}' case '{case_name}' in '{file_path}' has malformed " - "@param reference; expected " - '@param("name")' - ) - name: str = match.group("name") - value: SqlValue | None = value_lookup.get(name) - if value is None: - raise CompileInputError( - f"SQL test '{test_name}' case '{case_name}' in '{file_path}' references " - f"undeclared parameter '{name}'" - ) - parts.append( - _render_parameter( - name=name, - value=value, - value_renderer=value_renderer, - test_name=test_name, - case_name=case_name, - ) - ) - used_names.add(name) - cursor = match.end() - continue - parts.append(character) - cursor += 1 - return "".join(parts), frozenset(used_names) + references, error = _native.scan_test_parameter_references( + sql, list(value_lookup), f"SQL test '{test_name}' case '{case_name}' in '{file_path}'" + ) + expanded: tuple[str, frozenset[str]] = _splice_parameter_references( + sql=sql, + references=references, + value_lookup=value_lookup, + value_renderer=value_renderer, + test_name=test_name, + case_name=case_name, + ) + if error is not None: + raise CompileInputError(error) + return expanded def _splice_parameter_references( diff --git a/src/sqlbuild/compiler/compile/_helpers/render/templating.py b/src/sqlbuild/compiler/compile/_helpers/render/templating.py index ebbbe9bf52..e8c9e0eeaa 100644 --- a/src/sqlbuild/compiler/compile/_helpers/render/templating.py +++ b/src/sqlbuild/compiler/compile/_helpers/render/templating.py @@ -8,8 +8,6 @@ from sqlbuild.compiler.compile.classes.unicode_environment import UnicodeEnvironment from sqlbuild.compiler.compile.constants import COMPILE_INPUT_READS, TEMPLATE_OPEN_TOKEN from sqlbuild.compiler.compile.exceptions import CompileInputError -from sqlbuild.compiler.frontier.main.report_native_answer import report_native_answer -from sqlbuild.compiler.frontier.types import NativeStage from sqlbuild.compiler.model_config.constants import ENVIRONMENT_READ from sqlbuild.compiler.model_config.main._expand_native_config_templates import ( expand_native_config_templates, @@ -31,7 +29,6 @@ def expand_effective_vars(raw_values: dict[str, object]) -> dict[str, object]: raw_values, UnicodeEnvironment() ) record_template_reads(tuple(outcome[1])) - report_native_answer(stage=NativeStage.MODEL_CONFIG, kind="effective_vars") if isinstance(outcome[0], _native.NativeConfigError): raise native_config_error(error=outcome[0]) return cast(dict[str, object], outcome[0]) @@ -96,7 +93,6 @@ def expand_template_data( context_label=context_label, ) record_template_reads(outcome.reads) - report_native_answer(stage=NativeStage.MODEL_CONFIG, kind="template_expansions") if isinstance(outcome, NativeTemplateRejection): raise native_config_error(error=outcome.error) return outcome.value diff --git a/src/sqlbuild/compiler/compile/_helpers/scenarios/core.py b/src/sqlbuild/compiler/compile/_helpers/scenarios/core.py index 603a3d8280..fb37e844cc 100644 --- a/src/sqlbuild/compiler/compile/_helpers/scenarios/core.py +++ b/src/sqlbuild/compiler/compile/_helpers/scenarios/core.py @@ -7,30 +7,14 @@ import orjson import sqlbuild._native as _native -from sqlbuild.compiler.compile._helpers.sql_tests.core import ( - _require_prefixed_name, - _skip_ignorable, - _try_consume_keyword, - extract_top_level_ctes_with_scanner, -) -from sqlbuild.compiler.compile.constants import ( - EXPECTED_TEST_CTE_PREFIX, - SQL_WITH_KEYWORD, -) +from sqlbuild.compiler.compile._helpers.sql_tests.core import scanned_expected_model_names from sqlbuild.compiler.compile.exceptions import CompileInputError from sqlbuild.compiler.compile.models import ( CompileSqlScenarioCte, CompileSqlScenarioCtes, ) -from sqlbuild.compiler.frontier.main.report_native_answer import report_native_answer -from sqlbuild.compiler.frontier.types import NativeStage from sqlbuild.compiler.sql_analysis.models import SqlLexicalSyntax -_CONTEXT: str = "SQL scenario" -_WITH_REQUIREMENT: str = ( - "fixture CTEs and at least one __expected__ or __assert__ CTE" -) - def extract_sql_scenario_ctes( *, sql: str, file_label: str, syntax: SqlLexicalSyntax @@ -40,7 +24,6 @@ def extract_sql_scenario_ctes( outcome: dict[str, Any] = orjson.loads( _native.extract_sql_scenario_json(sql, file_label, syntax.native_mapping) ) - report_native_answer(stage=NativeStage.ATTACHMENTS, kind="scenario_ctes") error: str | None = outcome.get("error") if error is not None: raise CompileInputError(error) @@ -67,25 +50,6 @@ def extract_sql_scenario_expected_model_names( ) -> tuple[str, ...]: """Extract explicit expected-model relationships without inspecting CTE bodies.""" - start: int = _skip_ignorable(sql=sql, start=0, context_label=_CONTEXT, syntax=syntax) - if _try_consume_keyword(sql=sql, start=start, keyword=SQL_WITH_KEYWORD) is None: - return () - ctes: tuple[CompileSqlScenarioCte, ...] = extract_top_level_ctes_with_scanner( - sql=sql, - file_label=file_label, - context_label=_CONTEXT, - with_requirement=_WITH_REQUIREMENT, - cte_type=CompileSqlScenarioCte, - syntax=syntax, - ) - return tuple( - _require_prefixed_name( - cte_name=cte.name, - prefix=EXPECTED_TEST_CTE_PREFIX, - label="__expected__", - file_label=file_label, - context_label=_CONTEXT, - ) - for cte in ctes - if cte.name.startswith(EXPECTED_TEST_CTE_PREFIX) + return scanned_expected_model_names( + sql=sql, file_label=file_label, scenario=True, syntax=syntax ) diff --git a/src/sqlbuild/compiler/compile/_helpers/sharing/binding.py b/src/sqlbuild/compiler/compile/_helpers/sharing/binding.py index 709e95c39a..d337b2e6fd 100644 --- a/src/sqlbuild/compiler/compile/_helpers/sharing/binding.py +++ b/src/sqlbuild/compiler/compile/_helpers/sharing/binding.py @@ -2,38 +2,14 @@ from __future__ import annotations -import re -from collections import Counter -from collections.abc import Iterable, Mapping, Sequence -from dataclasses import replace -from typing import Any, cast - -from sqlbuild.compiler.compile._helpers.analysis.columns import ( +from sqlbuild.compiler.compile._helpers.analysis.reference_names import ( _analysis_reference_name, _lineage_resource_type, - _qualified_reference_names, -) -from sqlbuild.compiler.compile.constants import ( - COMPACT_REFERENCE_MARKER_PATTERN, - COMPACT_RELATION_STUB_PREFIX, - COMPACT_UNSTUBBED_REFERENCE_KIND, - MIN_SHARED_BINDING_QUERY_MEMBERS, ) from sqlbuild.compiler.compile.models import ( - CompactBatchContext, - CompactBatchInputs, CompileSqlReference, - ModelSqlAnalysisRequest, - NativeCompactAnalysis, - PreparedBindingQuery, - SharedBindingQuery, ) from sqlbuild.compiler.compile.types import CompiledResourceType -from sqlbuild.compiler.sql_analysis.constants import SQL_QUOTED_IDENTIFIER_DELIMITER -from sqlbuild.compiler.sql_analysis.main._normalize_analysis_batch import ( - normalize_analysis_sql_results, -) -from sqlbuild.compiler.sql_analysis.models import SqlSchemaValidationRequest def lineage_reference_map( @@ -50,353 +26,3 @@ def lineage_reference_map( reference.ref_name, ) return reference_map - - -def binding_share_prekey(*, query_sql: str, references: tuple[CompileSqlReference, ...]) -> str: - """Return authored SQL with lineage relation markers replaced by their stub positions.""" - - positions: dict[str, int] = { - name: index for index, name in enumerate(lineage_reference_map(references)) - } - - def marker(match: re.Match[str]) -> str: - position: int | None = positions.get(match.group(2)) - if position is None or match.group(1) == COMPACT_UNSTUBBED_REFERENCE_KIND: - return match.group(0) - return f"{COMPACT_RELATION_STUB_PREFIX}{position}" - - return COMPACT_REFERENCE_MARKER_PATTERN.sub(marker, query_sql) - - -def shareable_binding_prekeys(*, requests: Sequence[ModelSqlAnalysisRequest]) -> frozenset[str]: - """Return binding pre-keys shared by at least two binding requests of a compile.""" - - counts: Counter[str] = Counter( - binding_share_prekey(query_sql=request.query_sql, references=request.model_input.references) - for request in requests - if request.binding_schema is not None - ) - return frozenset( - prekey for prekey, count in counts.items() if count >= MIN_SHARED_BINDING_QUERY_MEMBERS - ) - - -def prepare_binding_queries( - *, - binding_catalog: Any, - inputs: CompactBatchInputs, - cleaned_sqls: list[str], - share: bool, - shareable_prekeys: frozenset[str] | None, -) -> tuple[PreparedBindingQuery | None, ...]: - """Prepare binding references in catalog order, with shared forms where keys can match.""" - - binding_schemas: tuple[dict[str, dict[str, str]] | None, ...] = inputs.binding_schemas or () - dialect: str | None = inputs.inference_profile.sql_analysis_dialect - prekeys: list[str | None] = [ - binding_share_prekey(query_sql=query_sql, references=query_references) - if share and binding_schema is not None - else None - for query_sql, query_references, binding_schema in zip( - inputs.query_sqls, inputs.references, binding_schemas, strict=True - ) - ] - candidates: frozenset[str] = ( - shareable_prekeys - if shareable_prekeys is not None - else frozenset( - prekey - for prekey, count in Counter(prekeys).items() - if prekey is not None and count >= MIN_SHARED_BINDING_QUERY_MEMBERS - ) - ) - shared_stubs: dict[int, dict[str, str]] = {} - for index, binding_schema in enumerate(binding_schemas): - prekey: str | None = prekeys[index] - if binding_schema is None or prekey is None or prekey not in candidates: - continue - names: list[str] | None = _shared_reference_names( - cleaned_sql=cleaned_sqls[index], - references=inputs.references[index], - binding_schema=binding_schema, - ) - if names is not None: - shared_stubs[index] = { - name: f"{COMPACT_RELATION_STUB_PREFIX}{position}" - for position, name in enumerate(names) - } - shared_sqls: dict[int, str | Exception] = dict( - zip( - shared_stubs, - normalize_analysis_sql_results( - dialect=dialect, - requests=[ - (inputs.query_sqls[index], stubs, inputs.placeholders[index]) - for index, stubs in shared_stubs.items() - ], - catalog=binding_catalog.native, - ), - strict=True, - ) - ) - prepared: list[PreparedBindingQuery | None] = [] - for index, binding_schema in enumerate(binding_schemas): - if binding_schema is None: - prepared.append(None) - continue - _, binding_references, overrides = binding_catalog.prepare( - [ - SqlSchemaValidationRequest( - sql=cleaned_sqls[index], dialect=dialect, schema=binding_schema - ) - ] - )[0] - shared: SharedBindingQuery | None = ( - _shared_binding_query( - binding_catalog=binding_catalog, - sql=normalized_analysis_sql(shared_sqls[index]), - dialect=dialect, - schema=binding_schema, - stubs=shared_stubs[index], - overrides=overrides, - ) - if index in shared_stubs - else None - ) - prepared.append( - PreparedBindingQuery(references=binding_references, overrides=overrides, shared=shared) - ) - if shareable_prekeys is not None: - return tuple(prepared) - counts: Counter[tuple[object, ...]] = Counter( - query.shared.key for query in prepared if query is not None and query.shared is not None - ) - return tuple( - ( - PreparedBindingQuery(references=query.references, overrides=query.overrides) - if query is not None - and query.shared is not None - and counts[query.shared.key] < MIN_SHARED_BINDING_QUERY_MEMBERS - else query - ) - for query in prepared - ) - - -def binding_query_fields( - *, - binding_query: PreparedBindingQuery, - binding_catalog: Any, -) -> tuple[dict[str, object], dict[str, object]]: - """Return native binding query fields and their identity payload.""" - - binding_references: list[tuple[str, bool]] = binding_query.references - fields: dict[str, object] = {} - shared: SharedBindingQuery | None = binding_query.shared - if shared is not None: - stubs: dict[str, str] = shared.stubs - binding_references = sorted( - binding_references, key=lambda reference: stubs.get(reference[0], reference[0]) - ) - fields["binding_aliases"] = { - name: stubs[name] for name, _ in binding_references if name in stubs - } - binding_payload: dict[str, object] = {"references": binding_references} - fields["binding_references"] = binding_references - if binding_query.overrides: - override_id: int = binding_catalog.native.register_override(binding_query.overrides) - fields["binding_override"] = override_id - binding_payload["override"] = override_id - return fields, binding_payload - - -def shared_result_is_exact(*, validation: object, template: object) -> bool: - """Only a successful analysis without diagnostics is independent of relation names.""" - - if isinstance(template, str): - return False - if validation is None: - return True - return isinstance(validation, dict) and cast(dict[str, object], validation).get("errors") == [] - - -def normalized_analysis_sql(result: str | Exception) -> str: - """Return one normalized batch member, raising the error its own normalization raised.""" - - if isinstance(result, Exception): - raise result - return result - - -def relation_stubs_collide(*, cleaned_sql: str, names: Iterable[str]) -> bool: - """Return whether authored SQL or relation names already use the relation stub prefix.""" - - return ( - any(name.startswith(COMPACT_RELATION_STUB_PREFIX) for name in names) - or COMPACT_RELATION_STUB_PREFIX.casefold() in cleaned_sql.casefold() - ) - - -def _shared_reference_names( - *, - cleaned_sql: str, - references: tuple[CompileSqlReference, ...], - binding_schema: Mapping[str, Mapping[str, str]], -) -> list[str] | None: - names: list[str] = list(lineage_reference_map(references)) - if not names or len({name.casefold() for name in names}) != len(names): - return None - if relation_stubs_collide(cleaned_sql=cleaned_sql, names=names): - return None - if SQL_QUOTED_IDENTIFIER_DELIMITER in cleaned_sql: - return None - for relation, columns in binding_schema.items(): - if ( - SQL_QUOTED_IDENTIFIER_DELIMITER in relation - or SQL_QUOTED_IDENTIFIER_DELIMITER in "".join(columns) - ): - return None - if _qualified_reference_names(query_sql=cleaned_sql, reference_names=names): - return None - return names - - -def _shared_binding_query( - *, - binding_catalog: Any, - sql: str, - dialect: str | None, - schema: Mapping[str, Mapping[str, str]], - stubs: dict[str, str], - overrides: Mapping[str, Mapping[str, str]], -) -> SharedBindingQuery: - """Identify one query from its SQL normalized with relation `stubs`.""" - - analysis_shapes: list[tuple[object, ...]] = [] - for name in stubs: - types, nullability = binding_catalog.analysis_shapes.get(name, ({}, {})) - analysis_shapes.append((stubs[name], tuple(types.items()), tuple(nullability.items()))) - binding_shapes: list[tuple[object, ...]] = [] - for relation, columns in schema.items(): - effective: Mapping[str, str] = ( - overrides[relation] - if relation in overrides - else binding_catalog.schemas[relation] - if columns - else {} - ) - binding_shapes.append( - (stubs.get(relation, relation), bool(columns), tuple(effective.items())) - ) - return SharedBindingQuery( - sql=sql, - stubs=stubs, - key=( - sql, - dialect or "generic", - tuple(analysis_shapes), - tuple(sorted(binding_shapes)), - ), - ) - - -def shared_result_keys( - *, inputs: CompactBatchInputs, context: CompactBatchContext -) -> tuple[tuple[object, ...] | None, ...]: - """Identify each shared member's complete native input, including its template.""" - - function_return_types: tuple[tuple[str, str], ...] = tuple( - inputs.inference_profile.function_return_types.items() - ) - keys: list[tuple[object, ...] | None] = [] - for index, binding_query in enumerate(context.binding_queries): - shared: SharedBindingQuery | None = ( - binding_query.shared if binding_query is not None else None - ) - if shared is None: - keys.append(None) - continue - query_references: tuple[CompileSqlReference, ...] = inputs.references[index] - declared_column_order: tuple[str, ...] = ( - tuple( - inputs.column_nullability_by_table.get( - _analysis_reference_name(query_references[0]), {} - ) - ) - if len(query_references) == 1 - else () - ) - reference_types: tuple[tuple[str, str], ...] = tuple( - (shared.stubs[name], resource_type.value) - for name, (resource_type, _) in lineage_reference_map(query_references).items() - ) - keys.append( - ( - shared.key, - inputs.recover_cte_facts[index], - inputs.rich_type_inference, - function_return_types, - declared_column_order, - reference_types, - ) - ) - return tuple(keys) - - -def reused_shared_results( - *, - inputs: CompactBatchInputs, - context: CompactBatchContext, - keys: tuple[tuple[object, ...] | None, ...], - memo: dict[object, object], -) -> dict[int, NativeCompactAnalysis]: - """Project remembered exact shared results onto members with the same key.""" - - reused: dict[int, NativeCompactAnalysis] = {} - for index, key in enumerate(keys): - representative: object = memo.get(key) if key is not None else None - binding_query: PreparedBindingQuery | None = context.binding_queries[index] - if not isinstance(representative, NativeCompactAnalysis) or binding_query is None: - continue - shared: SharedBindingQuery | None = binding_query.shared - if shared is None: - continue - resource_names_by_stub: dict[str, str] = { - shared.stubs[name]: resource_name - for name, (_, resource_name) in lineage_reference_map(inputs.references[index]).items() - } - resource_names: dict[int, str] = {} - for canonical_index in representative.resource_name_indexes: - resource_name: str | None = resource_names_by_stub.get( - representative.string_pool[canonical_index] - ) - if resource_name is None: - break - resource_names[canonical_index] = resource_name - else: - reused[index] = replace( - representative, - cleaned_sql=context.normalized_sqls[index], - resource_names=resource_names, - ) - return reused - - -def remembered_shared_results( - *, - keys: tuple[tuple[object, ...] | None, ...], - results: tuple[NativeCompactAnalysis, ...], -) -> dict[object, NativeCompactAnalysis]: - """Select exact, fully projected shared results to remember for later batches.""" - - remembered: dict[object, NativeCompactAnalysis] = {} - for key, result in zip(keys, results, strict=True): - if ( - key is not None - and key not in remembered - and result.projected - and result.analysis is not None - and result.compact_rows is not None - ): - remembered[key] = result - return remembered diff --git a/src/sqlbuild/compiler/compile/_helpers/sql_tests/core.py b/src/sqlbuild/compiler/compile/_helpers/sql_tests/core.py index 41933e4fe5..f9e2f06b19 100644 --- a/src/sqlbuild/compiler/compile/_helpers/sql_tests/core.py +++ b/src/sqlbuild/compiler/compile/_helpers/sql_tests/core.py @@ -2,21 +2,13 @@ from __future__ import annotations -from collections.abc import Callable from functools import lru_cache import sqlbuild._native as _native from sqlbuild.compiler.compile._helpers.refs.references import extract_sql_references from sqlbuild.compiler.compile.constants import ( DEFAULT_SQL_TEST_MODE, - EXPECTED_TEST_CTE_PREFIX, OMITTED_CEREMONIAL_SELECT_SQL, - SQL_ARGUMENT_SEPARATOR_TOKEN, - SQL_CEREMONIAL_SELECT_VALUE, - SQL_OPEN_PAREN_TOKEN, - SQL_QUOTE_TOKENS, - SQL_STATEMENT_TERMINATOR_TOKEN, - SQL_WITH_KEYWORD, ) from sqlbuild.compiler.compile.exceptions import CompileInputError from sqlbuild.compiler.compile.models import ( @@ -24,36 +16,22 @@ SqlReferenceOrigin, ) from sqlbuild.compiler.compile.types import SqlTestMode -from sqlbuild.compiler.frontier.main.report_native_answer import report_native_answer -from sqlbuild.compiler.frontier.types import NativeStage from sqlbuild.compiler.references.types import SqlReferenceKind -from sqlbuild.compiler.sql_analysis.main._find_matching_paren import find_matching_paren -from sqlbuild.compiler.sql_analysis.main._is_identifier_character import ( - is_identifier_character, -) -from sqlbuild.compiler.sql_analysis.main._is_identifier_start import is_identifier_start -from sqlbuild.compiler.sql_analysis.main._skip_dialect_non_code import dialect_non_code_end from sqlbuild.compiler.sql_analysis.models import SqlLexicalSyntax -_CONTEXT: str = "SQL test" -_SQL_TEST_WITH_REQUIREMENT: str = "mock CTEs and one __expected__ CTE" -_MATERIALIZED_KEYWORD: str = "MATERIALIZED" -_NOT_KEYWORD: str = "NOT" - +@lru_cache(maxsize=4096) def extract_unclassified_sql_test_ctes( *, sql: str, file_label: str, syntax: SqlLexicalSyntax ) -> tuple[CompileSqlTestCte, ...]: """Extract raw top-level CTEs before mode-specific classification.""" - return extract_top_level_ctes_with_scanner( - sql=sql, - file_label=file_label, - context_label=_CONTEXT, - with_requirement=_SQL_TEST_WITH_REQUIREMENT, - cte_type=CompileSqlTestCte, - syntax=syntax, - ) + error: str | None + ctes: list[tuple[str, str]] + error, ctes = _native.scope_test_ctes([(sql, file_label)], syntax.native_mapping)[0] + if error is not None: + raise CompileInputError(error) + return tuple(CompileSqlTestCte(name=name, sql_body=body) for name, body in ctes) def extract_sql_test_expected_model_names( @@ -67,29 +45,26 @@ def extract_sql_test_expected_model_names( if mode is not SqlTestMode.MODEL: return () - start: int = _skip_ignorable(sql=sql, start=0, syntax=syntax) - if _try_consume_keyword(sql=sql, start=start, keyword=SQL_WITH_KEYWORD) is None: - return () - ctes: tuple[CompileSqlTestCte, ...] = extract_top_level_ctes_with_scanner( - sql=sql, - file_label=file_label, - context_label=_CONTEXT, - with_requirement=_SQL_TEST_WITH_REQUIREMENT, - cte_type=CompileSqlTestCte, - syntax=syntax, - ) - return tuple( - _require_prefixed_name( - cte_name=cte.name, - prefix=EXPECTED_TEST_CTE_PREFIX, - label="__expected__", - file_label=file_label, - ) - for cte in ctes - if cte.name.startswith(EXPECTED_TEST_CTE_PREFIX) + return scanned_expected_model_names( + sql=sql, file_label=file_label, scenario=False, syntax=syntax ) +def scanned_expected_model_names( + *, sql: str, file_label: str, scenario: bool, syntax: SqlLexicalSyntax +) -> tuple[str, ...]: + """A SQL test's or scenario's `__expected__` names, raising the scan's error.""" + + error: str | None + names: list[str] + error, names = _native.scope_expected_model_names( + [(sql, file_label)], scenario, syntax.native_mapping + )[0] + if error is not None: + raise CompileInputError(error) + return tuple(names) + + def extract_assertion_target_model_names( *, assertion_sql: tuple[str, ...], @@ -108,248 +83,10 @@ def extract_assertion_target_model_names( return tuple(dict.fromkeys(targets)) -@lru_cache(maxsize=4096) -def extract_top_level_ctes_with_scanner[CteT]( - *, - sql: str, - file_label: str, - context_label: str, - with_requirement: str, - cte_type: Callable[..., CteT], - syntax: SqlLexicalSyntax, -) -> tuple[CteT, ...]: - """Scan top-level `WITH` CTEs, optionally followed by the ceremonial `SELECT 1`.""" - - ctes: tuple[tuple[str, str], ...] - index: int - ctes, index = _scan_top_level_ctes( - sql=sql, - file_label=file_label, - context_label=context_label, - with_requirement=with_requirement, - syntax=syntax, - ) - _validate_ceremonial_select( - sql=sql, - start=index, - file_label=file_label, - context_label=context_label, - syntax=syntax, - ) - return tuple(cte_type(name=name, sql_body=body) for name, body in ctes) - - def complete_omitted_ceremonial_select(*, sql: str, syntax: SqlLexicalSyntax) -> str: """Return test or scenario SQL as one statement, adding an omitted trailing `SELECT 1`.""" offset: int | None = _native.omitted_ceremonial_select(sql, syntax.native_mapping) - report_native_answer(stage=NativeStage.ATTACHMENTS, kind="omitted_select_scans") if offset is None: return sql return f"{sql[:offset]}{OMITTED_CEREMONIAL_SELECT_SQL}{sql[offset:]}" - - -def _scan_top_level_ctes( - *, - sql: str, - file_label: str, - context_label: str, - with_requirement: str, - syntax: SqlLexicalSyntax, -) -> tuple[tuple[tuple[str, str], ...], int]: - """Return top-level CTEs and the first code position after them.""" - - with_end: int | None = _try_consume_keyword( - sql=sql, - start=_skip_ignorable(sql=sql, start=0, context_label=context_label, syntax=syntax), - keyword=SQL_WITH_KEYWORD, - ) - if with_end is None: - raise CompileInputError( - f"{context_label} '{file_label}' must declare {with_requirement} in a top-level " - "WITH clause" - ) - index: int = _skip_ignorable( - sql=sql, start=with_end, context_label=context_label, syntax=syntax - ) - recursive_end: int | None = _try_consume_keyword(sql=sql, start=index, keyword="RECURSIVE") - if recursive_end is not None: - index = _skip_ignorable( - sql=sql, start=recursive_end, context_label=context_label, syntax=syntax - ) - - ctes: list[tuple[str, str]] = [] - seen_cte_names: set[str] = set() - while True: - cte_name, index = _read_identifier( - sql=sql, start=index, file_label=file_label, context_label=context_label - ) - if cte_name in seen_cte_names: - raise CompileInputError( - f"{context_label} '{file_label}' defines duplicate CTE '{cte_name}'" - ) - seen_cte_names.add(cte_name) - - index = _skip_ignorable(sql=sql, start=index, context_label=context_label, syntax=syntax) - if index < len(sql) and sql[index] == SQL_OPEN_PAREN_TOKEN: - index = ( - find_matching_paren( - sql=sql, open_paren_index=index, context=context_label, syntax=syntax - ) - + 1 - ) - index = _skip_ignorable( - sql=sql, start=index, context_label=context_label, syntax=syntax - ) - index = _consume_keyword( - sql=sql, - start=index, - keyword="AS", - file_label=file_label, - context_label=context_label, - ) - index = _skip_ignorable(sql=sql, start=index, context_label=context_label, syntax=syntax) - hint: str | None = _materialization_hint( - sql=sql, start=index, context_label=context_label, syntax=syntax - ) - if hint is not None: - raise CompileInputError( - f"{context_label} '{file_label}' CTE '{cte_name}' must not use AS {hint}; " - f"materialization hints are not supported in {context_label} CTEs" - ) - if index >= len(sql) or sql[index] != SQL_OPEN_PAREN_TOKEN: - raise CompileInputError( - f"{context_label} '{file_label}' CTE '{cte_name}' must use AS (...)" - ) - cte_body_start: int = index + 1 - cte_body_end: int = find_matching_paren( - sql=sql, open_paren_index=index, context=context_label, syntax=syntax - ) - ctes.append((cte_name, sql[cte_body_start:cte_body_end].strip())) - index = _skip_ignorable( - sql=sql, start=cte_body_end + 1, context_label=context_label, syntax=syntax - ) - if index < len(sql) and sql[index] == SQL_ARGUMENT_SEPARATOR_TOKEN: - index = _skip_ignorable( - sql=sql, start=index + 1, context_label=context_label, syntax=syntax - ) - continue - return tuple(ctes), index - - -def _materialization_hint( - *, sql: str, start: int, context_label: str, syntax: SqlLexicalSyntax -) -> str | None: - if _try_consume_keyword(sql=sql, start=start, keyword=_MATERIALIZED_KEYWORD) is not None: - return _MATERIALIZED_KEYWORD - not_end: int | None = _try_consume_keyword(sql=sql, start=start, keyword=_NOT_KEYWORD) - if not_end is None: - return None - index: int = _skip_ignorable(sql=sql, start=not_end, context_label=context_label, syntax=syntax) - if _try_consume_keyword(sql=sql, start=index, keyword=_MATERIALIZED_KEYWORD) is None: - return None - return f"{_NOT_KEYWORD} {_MATERIALIZED_KEYWORD}" - - -def _require_prefixed_name( - *, cte_name: str, prefix: str, label: str, file_label: str, context_label: str = _CONTEXT -) -> str: - extracted_name: str = cte_name.removeprefix(prefix) - if extracted_name: - return extracted_name - raise CompileInputError(f"{context_label} '{file_label}' must use {label} to identify a target") - - -def _validate_ceremonial_select( - *, - sql: str, - start: int, - file_label: str, - syntax: SqlLexicalSyntax, - context_label: str = _CONTEXT, -) -> None: - if _is_statement_end( - sql=sql, start=start, context_label=context_label, syntax=syntax - ) or _is_ceremonial_select_statement( - sql=sql, start=start, context_label=context_label, syntax=syntax - ): - return - raise CompileInputError( - f"{context_label} '{file_label}' must end after its CTEs; only an optional " - "ceremonial top-level `SELECT 1` may follow them" - ) - - -def _is_ceremonial_select_statement( - *, sql: str, start: int, syntax: SqlLexicalSyntax, context_label: str = _CONTEXT -) -> bool: - index: int = _skip_ignorable(sql=sql, start=start, context_label=context_label, syntax=syntax) - select_end: int | None = _try_consume_keyword(sql=sql, start=index, keyword="SELECT") - if select_end is None: - return False - index = _skip_ignorable(sql=sql, start=select_end, context_label=context_label, syntax=syntax) - if index >= len(sql) or sql[index] != SQL_CEREMONIAL_SELECT_VALUE: - return False - index = _skip_ignorable(sql=sql, start=index + 1, context_label=context_label, syntax=syntax) - return _is_statement_end(sql=sql, start=index, context_label=context_label, syntax=syntax) - - -def _is_statement_end( - *, sql: str, start: int, syntax: SqlLexicalSyntax, context_label: str = _CONTEXT -) -> bool: - index: int = start - if index < len(sql) and sql[index] == SQL_STATEMENT_TERMINATOR_TOKEN: - index = _skip_ignorable( - sql=sql, start=index + 1, context_label=context_label, syntax=syntax - ) - return index == len(sql) - - -def _consume_keyword( - *, sql: str, start: int, keyword: str, file_label: str, context_label: str = _CONTEXT -) -> int: - keyword_end: int | None = _try_consume_keyword(sql=sql, start=start, keyword=keyword) - if keyword_end is not None: - return keyword_end - raise CompileInputError(f"{context_label} '{file_label}' expected keyword {keyword}") - - -def _try_consume_keyword(*, sql: str, start: int, keyword: str) -> int | None: - keyword_end: int = start + len(keyword) - if sql[start:keyword_end].upper() != keyword: - return None - if keyword_end < len(sql) and is_identifier_character(sql[keyword_end]): - return None - if start > 0 and is_identifier_character(sql[start - 1]): - return None - return keyword_end - - -def _read_identifier( - *, sql: str, start: int, file_label: str, context_label: str = _CONTEXT -) -> tuple[str, int]: - if start >= len(sql) or not is_identifier_start(sql[start]): - raise CompileInputError(f"{context_label} '{file_label}' expected a CTE name") - index: int = start + 1 - while index < len(sql) and is_identifier_character(sql[index]): - index += 1 - return sql[start:index], index - - -def _skip_ignorable( - *, sql: str, start: int, syntax: SqlLexicalSyntax, context_label: str = _CONTEXT -) -> int: - index: int = start - while index < len(sql): - if sql[index].isspace(): - index += 1 - continue - if sql[index] not in SQL_QUOTE_TOKENS: - comment_end: int | None = dialect_non_code_end( - sql=sql, start=index, syntax=syntax, context=context_label - ) - if comment_end is not None: - index = comment_end - continue - return index - return index diff --git a/src/sqlbuild/compiler/compile/_helpers/sql_tests/helper_ctes.py b/src/sqlbuild/compiler/compile/_helpers/sql_tests/helper_ctes.py index 69f6f5f7d3..fa806f2e8b 100644 --- a/src/sqlbuild/compiler/compile/_helpers/sql_tests/helper_ctes.py +++ b/src/sqlbuild/compiler/compile/_helpers/sql_tests/helper_ctes.py @@ -4,8 +4,8 @@ import re from collections.abc import Iterable -from typing import Any +import sqlbuild._native as _native from sqlbuild.compiler.compile._helpers.diagnostics.collector import report_compile_diagnostic from sqlbuild.compiler.compile._helpers.refs.references import ( reference_call_location, @@ -20,7 +20,6 @@ TABLE_FN_TEST_CTE_PREFIX, ) from sqlbuild.compiler.compile.models import ( - CompileModelInput, CompileModelSqlTestCtes, CompilerDiagnostic, CompileSqlReference, @@ -35,7 +34,6 @@ ) from sqlbuild.compiler.discovery.models import DiscoveredSqlTestBlock, DiscoveredSqlTestFile from sqlbuild.compiler.references.types import SqlReferenceKind -from sqlbuild.compiler.sql_analysis.main.import_polyglot_sql import import_polyglot_sql from sqlbuild.compiler.sql_analysis.models import SqlLexicalSyntax from sqlbuild.spec.contracts.models import SourceLocation @@ -46,22 +44,6 @@ DBT_REF_TEST_CTE_PREFIX, TABLE_FN_TEST_CTE_PREFIX, ) -_RELATION_REFERENCE_KINDS: frozenset[SqlReferenceKind] = frozenset( - { - SqlReferenceKind.REF, - SqlReferenceKind.SOURCE, - SqlReferenceKind.SEED, - SqlReferenceKind.DBT_REF, - SqlReferenceKind.TABLE_FUNCTION, - } -) -_MOCK_PREFIX_BY_KIND: dict[SqlReferenceKind, str] = { - SqlReferenceKind.REF: REF_TEST_CTE_PREFIX, - SqlReferenceKind.SOURCE: SOURCE_TEST_CTE_PREFIX, - SqlReferenceKind.SEED: SEED_TEST_CTE_PREFIX, - SqlReferenceKind.DBT_REF: DBT_REF_TEST_CTE_PREFIX, - SqlReferenceKind.TABLE_FUNCTION: TABLE_FN_TEST_CTE_PREFIX, -} _IDENTIFIER_PATTERN: re.Pattern[str] = re.compile(r"[A-Za-z_][\w$]*") @@ -323,86 +305,6 @@ def _mock_name_read( return None -def report_mocks_reading_referencing_helpers( - *, - authored_ctes: tuple[CompileSqlTestCte, ...], - reader_ctes: tuple[CompileSqlTestCte, ...], - model_inputs: tuple[CompileModelInput, ...], - target_model_names: tuple[str, ...], - mock_model_names: tuple[str, ...], - test_file: DiscoveredSqlTestFile, - test_block: DiscoveredSqlTestBlock, - syntax: SqlLexicalSyntax, -) -> None: - """Report mocks the test reads that read a helper calling a reference, which cannot resolve.""" - - referencing: dict[str, CompileSqlReference] = {} - for cte in authored_ctes: - if cte.name.startswith(_MOCK_CTE_PREFIXES): - continue - reference: CompileSqlReference | None = next( - ( - reference - for reference in _references(sql=cte.sql_body, syntax=syntax) - if reference.ref_kind in _RELATION_REFERENCE_KINDS - ), - None, - ) - if reference is not None: - referencing[cte.name.casefold()] = reference - if not referencing: - return - graph: SqlTestCteGraph = sql_test_cte_graph( - authored_ctes=authored_ctes, reader_ctes=reader_ctes - ) - called_mocks: list[str] = [] - for sql in ( - *(cte.sql_body for cte in reader_ctes), - *(graph.ctes[key].sql_body for key in _read_helper_keys(graph)), - ): - for reference in _references(sql=sql, syntax=syntax): - called_mocks.extend( - _mock_keys(kind=SqlReferenceKind(reference.ref_kind), reference=reference) - ) - used_mocks: tuple[str, ...] = _used_mock_keys( - graph=graph, - called_mocks=tuple(called_mocks), - model_references={ - model_input.model_file.file_path.stem: model_input.references - for model_input in model_inputs - }, - target_model_names=target_model_names, - mocked=frozenset(mock_model_names), - ) - reporter: _HelperDiagnostics = _HelperDiagnostics(test_file=test_file, test_block=test_block) - for mock_key in used_mocks: - helper_key: str | None = next( - ( - key - for key in reachable_cte_keys(graph=graph, roots=graph.reads.get(mock_key, ())) - if key in referencing - ), - None, - ) - if helper_key is None: - continue - mock_name: str = graph.ctes[mock_key].name - helper_name: str = graph.ctes[helper_key].name - call: str = _reference_call(referencing[helper_key]) - reporter.report( - cte_name=helper_name, - call=call, - message=( - f"SQL test mock '{mock_name}' reads helper CTE '{helper_name}', which calls " - f"{call}; mocks and fixtures are defined before the models the test runs, so " - "the helper cannot be resolved for them" - ), - help=_mock_reference_help( - mock_name=mock_name, call=call, reference=referencing[helper_key] - ), - ) - - def _reader_ctes(payload: CompileModelSqlTestCtes) -> tuple[CompileSqlTestCte, ...]: return (*payload.expected_ctes, *payload.assertion_ctes) @@ -415,63 +317,6 @@ def _read_helper_keys(graph: SqlTestCteGraph) -> tuple[str, ...]: ) -def _used_mock_keys( - *, - graph: SqlTestCteGraph, - called_mocks: tuple[str, ...], - model_references: dict[str, tuple[CompileSqlReference, ...]], - target_model_names: tuple[str, ...], - mocked: frozenset[str], -) -> tuple[str, ...]: - """Return mocks the test's checks and read helpers, or the models it runs, read in order.""" - - used: list[str] = [ - key - for key in reachable_cte_keys(graph=graph, roots=graph.reader_reads) - if graph.ctes[key].name.startswith(_MOCK_CTE_PREFIXES) - ] - used.extend(key for key in dict.fromkeys(called_mocks) if key in graph.ctes and key not in used) - pending: list[str] = [name for name in target_model_names if name not in mocked] - visited: set[str] = set(pending) - while pending: - model_name: str = pending.pop(0) - for reference in model_references.get(model_name, ()): - kind: SqlReferenceKind = SqlReferenceKind(reference.ref_kind) - for mock_key in _mock_keys(kind=kind, reference=reference): - if mock_key in graph.ctes and mock_key not in used: - used.append(mock_key) - if ( - kind is SqlReferenceKind.REF - and reference.ref_name not in mocked - and reference.ref_name not in visited - ): - visited.add(reference.ref_name) - pending.append(reference.ref_name) - return tuple(used) - - -def _mock_keys(*, kind: SqlReferenceKind, reference: CompileSqlReference) -> tuple[str, ...]: - prefix: str | None = _MOCK_PREFIX_BY_KIND.get(kind) - if prefix is None: - return () - names: list[str] = [reference.ref_name] - if reference.ref_package is not None: - names.append(f"{reference.ref_package}__{reference.ref_name}") - return tuple(f"{prefix}{name}".casefold() for name in names) - - -def _mock_reference_help(*, mock_name: str, call: str, reference: CompileSqlReference) -> str: - kind: SqlReferenceKind = SqlReferenceKind(reference.ref_kind) - if kind is not SqlReferenceKind.TABLE_FUNCTION and reference.ref_package is None: - mock_cte: str = f"{kind.fixture_cte_prefix}{reference.ref_name}" - return ( - f"Read a mock by its CTE name instead, for example FROM {mock_cte} rather than " - f"FROM {call}, defining {mock_cte} AS (SELECT ...) if the test does not mock it, " - f"or write the rows of '{mock_name}' directly." - ) - return f"Write the rows of '{mock_name}' directly, for example {mock_name} AS (SELECT ...)." - - def _reference_call(reference: CompileSqlReference) -> str: kind: SqlReferenceKind = SqlReferenceKind(reference.ref_kind) if kind is SqlReferenceKind.DBT_REF and reference.ref_package is not None: @@ -486,45 +331,8 @@ def _references(*, sql: str, syntax: SqlLexicalSyntax) -> tuple[CompileSqlRefere def _parsed_reads(*, sql: str, keys: frozenset[str]) -> tuple[str, ...] | None: """Return unqualified table reads of ``keys`` not shadowed by a nested CTE, or None.""" - folded: str = sql.casefold() - if not any(key in folded for key in keys): - return () - polyglot_module: Any = import_polyglot_sql() - try: - parsed: Any = polyglot_module.parse_one(sql, dialect="generic") - except polyglot_module.PolyglotError: - return None - nested: frozenset[str] = _defined_cte_keys(parsed.to_dict()) - reads: list[str] = [] - for table in parsed.find_all("table"): - if table.arg("schema") is not None or table.arg("catalog") is not None: - continue - key: str = str(getattr(table, "name", "") or "").casefold() - if key in keys and key not in nested and key not in reads: - reads.append(key) - return tuple(reads) - - -def _defined_cte_keys(tree: Any) -> frozenset[str]: - """Return the case-folded names of every CTE a parsed query defines, at any depth.""" - - keys: set[str] = set() - pending: list[Any] = [tree] - while pending: - value: Any = pending.pop() - if isinstance(value, list): - pending.extend(value) - continue - if not isinstance(value, dict): - continue - ctes: Any = value.get("ctes") - for cte in ctes if isinstance(ctes, list) else (): - alias: Any = cte.get("alias") if isinstance(cte, dict) else None - name: Any = alias.get("name") if isinstance(alias, dict) else None - if isinstance(name, str): - keys.add(name.casefold()) - pending.extend(value.values()) - return frozenset(keys) + reads: list[str] | None = _native.sql_test_helper_reads(sql, sorted(keys)) + return None if reads is None else tuple(reads) def _token_reads(*, sql: str, keys: frozenset[str]) -> tuple[str, ...]: diff --git a/src/sqlbuild/compiler/compile/_helpers/sql_tests/identity.py b/src/sqlbuild/compiler/compile/_helpers/sql_tests/identity.py deleted file mode 100644 index 74ca533181..0000000000 --- a/src/sqlbuild/compiler/compile/_helpers/sql_tests/identity.py +++ /dev/null @@ -1,46 +0,0 @@ -"""Version identity for one expanded SQL test case.""" - -from __future__ import annotations - -import hashlib -import json -from pathlib import Path - -from sqlbuild.compiler.compile.models import CompiledObjectKey, CompiledSqlTestResource -from sqlbuild.compiler.discovery.models import SqlTestParameterDeclaration -from sqlbuild.sql_values.main.identity import sql_value_identity -from sqlbuild.sql_values.models import SqlValue - - -def build_sql_test_case_fingerprint( - *, - source_path: Path, - block_index: int, - case_name: str, - parameter_schema: tuple[SqlTestParameterDeclaration, ...], - parameter_values: tuple[tuple[str, SqlValue], ...], - expanded_sql: str, - scope_deps: tuple[CompiledObjectKey, ...], - tested_resources: tuple[CompiledSqlTestResource, ...], -) -> str: - """Hash all compile-resolved inputs that version a stable test case.""" - - payload: dict[str, object] = { - "source_path": source_path.as_posix(), - "block_index": block_index, - "case_name": case_name, - "parameter_schema": [ - (parameter.name, parameter.value_type.value, parameter.nullable) - for parameter in parameter_schema - ], - "parameter_values": [ - (name, sql_value_identity(value=value)) for name, value in parameter_values - ], - "expanded_sql": expanded_sql, - "scope_deps": sorted((str(dep.resource_type), dep.name) for dep in scope_deps), - "tested_resources": sorted( - (resource.kind.value, resource.name) for resource in tested_resources - ), - } - encoded: str = json.dumps(payload, ensure_ascii=True, separators=(",", ":"), sort_keys=True) - return hashlib.sha256(encoded.encode("utf-8")).hexdigest() diff --git a/src/sqlbuild/compiler/compile/_helpers/sql_tests/scope_deps.py b/src/sqlbuild/compiler/compile/_helpers/sql_tests/scope_deps.py deleted file mode 100644 index 38463bfeae..0000000000 --- a/src/sqlbuild/compiler/compile/_helpers/sql_tests/scope_deps.py +++ /dev/null @@ -1,67 +0,0 @@ -"""Scope dependencies of macro, UDF and table-function SQL tests.""" - -from __future__ import annotations - -from sqlbuild.compiler.compile._helpers.render.macros import find_macro_call_names -from sqlbuild.compiler.compile.models import CompiledObjectKey, CompileModelInput -from sqlbuild.compiler.compile.types import CompiledResourceType -from sqlbuild.compiler.references.types import SqlReferenceKind - - -def macro_sql_test_scope_deps( - *, tested_macro_names: tuple[str, ...], model_inputs: tuple[CompileModelInput, ...] -) -> tuple[CompiledObjectKey, ...]: - """Return the models whose macro calls include a tested macro.""" - - tested_names: frozenset[str] = frozenset(tested_macro_names) - scope_deps: list[CompiledObjectKey] = [] - model_input: CompileModelInput - for model_input in model_inputs: - model_macro_deps: frozenset[str] = frozenset( - model_input.macro_deps or find_macro_call_names(model_input.macro_source_sql) - ) - if not tested_names.intersection(model_macro_deps): - continue - scope_deps.append( - CompiledObjectKey( - resource_type=CompiledResourceType.MODEL, - name=model_input.model_file.file_path.stem, - ) - ) - return tuple(scope_deps) - - -def udf_sql_test_scope_deps( - *, tested_udf_names: tuple[str, ...], model_inputs: tuple[CompileModelInput, ...] -) -> tuple[CompiledObjectKey, ...]: - """Return the models that call a tested UDF.""" - - tested_names: frozenset[str] = frozenset(tested_udf_names) - scope_deps: list[CompiledObjectKey] = [] - model_input: CompileModelInput - for model_input in model_inputs: - model_udf_deps: frozenset[str] = frozenset( - reference.ref_name - for reference in model_input.references - if reference.ref_kind == SqlReferenceKind.UDF - ) - if not tested_names.intersection(model_udf_deps): - continue - scope_deps.append( - CompiledObjectKey( - resource_type=CompiledResourceType.MODEL, - name=model_input.model_file.file_path.stem, - ) - ) - return tuple(scope_deps) - - -def function_sql_test_scope_deps( - *, tested_function_names: tuple[str, ...] -) -> tuple[CompiledObjectKey, ...]: - """Return the tested table functions as scope dependencies.""" - - return tuple( - CompiledObjectKey(resource_type=CompiledResourceType.TABLE_FN, name=function_name) - for function_name in tested_function_names - ) diff --git a/src/sqlbuild/compiler/compile/classes/binding_dataflow.py b/src/sqlbuild/compiler/compile/classes/binding_dataflow.py deleted file mode 100644 index 0909ba58c7..0000000000 --- a/src/sqlbuild/compiler/compile/classes/binding_dataflow.py +++ /dev/null @@ -1,314 +0,0 @@ -"""Model analysis state that publishes producer shapes as each analysis completes.""" - -from __future__ import annotations - -import contextvars -import heapq -import sys -import threading -import time -from collections.abc import Callable -from dataclasses import replace -from graphlib import CycleError, TopologicalSorter - -from sqlbuild.adapter.contract.models import ExpressionInferenceProfile -from sqlbuild.compiler.compile._helpers.analysis.cache import model_analysis_output_signature -from sqlbuild.compiler.compile._helpers.analysis.compact import serialized_analysis -from sqlbuild.compiler.compile._helpers.assembly.semantic_shapes import ( - binding_relation_names, - published_model_shape, - referenced_model_names, -) -from sqlbuild.compiler.compile.models import ( - ModelSqlAnalysis, - ModelSqlAnalysisRequest, - PolyglotAnalysisResult, -) -from sqlbuild.compiler.lineage.types import InferredNullability -from sqlbuild.presentation.main.transient_line_coordinator import ( - shared_transient_line_coordinator, -) - -_WORKER_POLL_SECONDS: float = 0.05 -_WORKER_START_GRACE_SECONDS: float = 1.0 -_INTERRUPT_NOTICE: str = "Interrupted; finishing in-flight model analysis...\n" - - -class BindingDataflow: - """Analyze each model with exactly the producer shapes and cache state it depends on.""" - - def __init__( - self, - *, - requests: tuple[ModelSqlAnalysisRequest, ...], - names: tuple[str, ...], - cached: dict[str, PolyglotAnalysisResult], - previous_signatures: dict[str, str], - shapes: dict[str, dict[str, str]], - types: dict[str, dict[str, str]], - nullability: dict[str, dict[str, InferredNullability]], - profile: ExpressionInferenceProfile, - analyze: Callable[..., tuple[ModelSqlAnalysis, ...]], - complete: Callable[..., tuple[ModelSqlAnalysis, ...]], - ) -> None: - self._requests: tuple[ModelSqlAnalysisRequest, ...] = requests - self._names: tuple[str, ...] = names - self._cached: dict[str, PolyglotAnalysisResult] = cached - self._by_name: dict[str, ModelSqlAnalysisRequest] = dict(zip(names, requests, strict=True)) - available_names: frozenset[str] = frozenset(names) - self._dependencies: dict[str, tuple[str, ...]] = { - name: referenced_model_names( - model_input=request.model_input, available_names=available_names - ) - for name, request in self._by_name.items() - } - self._previous_signatures: dict[str, str] = previous_signatures - self._complete_shapes: dict[str, dict[str, str]] = dict(shapes) - self._available_types: dict[str, dict[str, str]] = dict(types) - self._available_nullability: dict[str, dict[str, InferredNullability]] = dict(nullability) - self._reusable: dict[str, PolyglotAnalysisResult] = dict(cached) - self._profile: ExpressionInferenceProfile = profile - self._analyze: Callable[..., tuple[ModelSqlAnalysis, ...]] = analyze - self._complete: Callable[..., tuple[ModelSqlAnalysis, ...]] = complete - self._changed: set[str] = set() - self._results: dict[str, ModelSqlAnalysis] = {} - self._ready: list[tuple[int, int, str]] = [] - self._pending: dict[str, int] = {} - self._dependents: dict[str, list[str]] = {} - self._failure: BaseException | None = None - self._cancelled: bool = False - self._condition: threading.Condition = threading.Condition(threading.Lock()) - - def analyze_waves( - self, - ) -> tuple[tuple[ModelSqlAnalysis, ...], dict[str, PolyglotAnalysisResult]]: - """Analyze one topological level at a time, the reference schedule.""" - - sorter: TopologicalSorter[str] = TopologicalSorter(self._dependencies) - try: - sorter.prepare() - except CycleError: - return self._analyze_cycle(), self._cached - while sorter.is_active(): - ready: tuple[str, ...] = tuple(sorter.get_ready()) - self._analyze_ready(ready) - sorter.done(*ready) - return tuple(self._results[name] for name in self._names), self._reusable - - def analyze_dataflow( - self, *, workers: int, batch_min: int, batch_limit: int - ) -> tuple[tuple[ModelSqlAnalysis, ...], dict[str, PolyglotAnalysisResult]] | None: - """Analyze models as their producers finish; return None after an analysis error.""" - - try: - order: tuple[str, ...] = tuple(TopologicalSorter(self._dependencies).static_order()) - except CycleError: - return self._analyze_cycle(), self._cached - heights: dict[str, int] = {} - self._dependents = {name: [] for name in self._by_name} - for name in self._by_name: - for parent in self._dependencies[name]: - self._dependents[parent].append(name) - for name in reversed(order): - heights[name] = 1 + max((heights[child] for child in self._dependents[name]), default=0) - priorities: dict[str, tuple[int, int]] = { - name: (-heights[name], position) for position, name in enumerate(self._by_name) - } - self._pending = {name: len(self._dependencies[name]) for name in self._by_name} - self._ready = [ - (*priorities[name], name) for name in self._by_name if not self._pending[name] - ] - heapq.heapify(self._ready) - share: tuple[int, int, int] = (workers, batch_min, batch_limit) - with serialized_analysis(self._condition): - context: contextvars.Context = contextvars.copy_context() - threads: list[threading.Thread] = [ - threading.Thread( - target=context.copy().run, - args=(self._run_worker,), - kwargs={"priorities": priorities, "share": share}, - name=f"sqlbuild-model-analysis-{index}", - daemon=True, - ) - for index in range(max(1, workers)) - ] - self._wait_for_workers(threads) - if self._failure is not None and not isinstance(self._failure, Exception): - raise self._failure - if self._failure is not None: - return None - return tuple(self._results[name] for name in self._names), self._reusable - - def _wait_for_workers(self, threads: list[threading.Thread]) -> None: - """Join workers lock-free; a first interrupt cancels them, repeats wait for their exit.""" - - attempted: list[threading.Thread] = [] - interrupt: BaseException | None = None - try: - for thread in threads: - attempted.append(thread) - thread.start() - except BaseException as error: # noqa: BLE001 - re-raised after workers stop - interrupt = self._cancel(interrupt=None, error=error) - pending: list[threading.Thread] = list(attempted) - unstarted_deadline: float = time.monotonic() + _WORKER_START_GRACE_SECONDS - while pending: - try: - pending = [ - thread - for thread in pending - if self._worker_running(thread=thread, unstarted_deadline=unstarted_deadline) - ] - except BaseException as error: # noqa: BLE001 - re-raised after workers stop - interrupt = self._cancel(interrupt=interrupt, error=error) - if interrupt is not None: - raise interrupt - - def _cancel(self, *, interrupt: BaseException | None, error: BaseException) -> BaseException: - if interrupt is not None: - return interrupt - self._cancelled = True - if not isinstance(error, Exception): - shared_transient_line_coordinator().write_persistent( - stream=sys.stderr, text=_INTERRUPT_NOTICE - ) - return error - - @staticmethod - def _worker_running(*, thread: threading.Thread, unstarted_deadline: float) -> bool: - """Join briefly; a thread whose OS thread never started is dropped after a grace period.""" - - if thread.ident is None: - time.sleep(_WORKER_POLL_SECONDS / 10) - return time.monotonic() < unstarted_deadline - try: - thread.join(_WORKER_POLL_SECONDS) - except RuntimeError: - return True - return thread.is_alive() - - def _run_worker( - self, *, priorities: dict[str, tuple[int, int]], share: tuple[int, int, int] - ) -> None: - with self._condition: - try: - self._drain_ready(priorities=priorities, share=share) - except BaseException as error: # noqa: BLE001 - re-raised or replayed in waves - self._record_failure(error) - self._condition.notify_all() - - def _record_failure(self, error: BaseException) -> None: - """Keep the first failure, except that a non-Exception interrupt always wins.""" - - if self._failure is None or ( - isinstance(self._failure, Exception) and not isinstance(error, Exception) - ): - self._failure = error - - def _drain_ready( - self, *, priorities: dict[str, tuple[int, int]], share: tuple[int, int, int] - ) -> None: - workers, batch_min, batch_limit = share - while ( - not self._cancelled - and self._failure is None - and len(self._results) < len(self._by_name) - ): - if not self._ready: - _ = self._condition.wait(_WORKER_POLL_SECONDS) - continue - count: int = min( - len(self._ready), - max(batch_min, -(-len(self._ready) // workers)), - batch_limit, - ) - batch: tuple[str, ...] = tuple(heapq.heappop(self._ready)[2] for _ in range(count)) - self._analyze_ready(batch) - for name in batch: - for child in self._dependents[name]: - self._pending[child] -= 1 - if not self._pending[child]: - heapq.heappush(self._ready, (*priorities[child], child)) - self._condition.notify_all() - - def _analyze_cycle(self) -> tuple[ModelSqlAnalysis, ...]: - return self._complete( - requests=self._requests, - analyses=self._analyze( - requests=self._requests, - cached_analyses=self._cached, - column_types_by_table=self._available_types, - column_nullability_by_table=self._available_nullability, - ), - complete_binding_schemas=self._complete_shapes, - ) - - def _analyze_ready(self, ready: tuple[str, ...]) -> None: - wave: list[ModelSqlAnalysisRequest] = [] - for name in ready: - request: ModelSqlAnalysisRequest = self._by_name[name] - if any(parent in self._changed for parent in self._dependencies[name]): - self._changed.add(name) - if request.cache_key is not None: - self._reusable.pop(request.cache_key, None) - bindings: dict[str, dict[str, str]] | None = ( - None - if request.binding_schema is None - else { - relation: self._complete_shapes.get(relation, {}) - for relation in binding_relation_names(request.model_input.references) - } - ) - wave.append(replace(request, binding_schema=bindings)) - wave_requests: tuple[ModelSqlAnalysisRequest, ...] = tuple(wave) - wave_names: set[str] = set(ready) - for request in wave_requests: - wave_names.update(binding_relation_names(request.model_input.references)) - analyses: tuple[ModelSqlAnalysis, ...] = self._complete( - requests=wave_requests, - analyses=self._analyze( - requests=wave_requests, - cached_analyses=self._reusable, - column_types_by_table=self._available_types, - column_nullability_by_table=self._available_nullability, - ), - complete_binding_schemas={ - name: self._complete_shapes[name] - for name in wave_names - if name in self._complete_shapes - }, - supplied_relations=frozenset( - name - for name in wave_names - if name in self._complete_shapes - and self._available_types.get(name, {}).keys() == self._complete_shapes[name].keys() - ), - ) - for name, request, result in zip(ready, wave_requests, analyses, strict=True): - self._results[name] = result - self._publish(name=name, request=request, result=result) - - def _publish( - self, *, name: str, request: ModelSqlAnalysisRequest, result: ModelSqlAnalysis - ) -> None: - analysis: PolyglotAnalysisResult = result.polyglot_analysis - if model_analysis_output_signature(analysis) != self._previous_signatures.get(name): - self._changed.add(name) - required: frozenset[str] = binding_relation_names(request.model_input.references) - star_known: bool = not analysis.has_star or ( - analysis.star_resolved and required <= self._complete_shapes.keys() - ) - if not analysis.columns or not star_known: - return - shape: dict[str, str] = published_model_shape( - sql=result.cleaned_sql or request.query_sql, - columns={column.name: column.type or "UNKNOWN" for column in analysis.columns}, - inputs={table: self._complete_shapes.get(table, {}) for table in required}, - profile=self._profile, - config_values=request.model_input.config.values, - ) - self._complete_shapes.setdefault(name, shape) - self._available_types.setdefault(name, shape) - self._available_nullability.setdefault( - name, dict.fromkeys(shape, InferredNullability.UNKNOWN) - ) diff --git a/src/sqlbuild/compiler/compile/classes/python_model_analysis.py b/src/sqlbuild/compiler/compile/classes/python_model_analysis.py index 1e5231d406..b3005470bc 100644 --- a/src/sqlbuild/compiler/compile/classes/python_model_analysis.py +++ b/src/sqlbuild/compiler/compile/classes/python_model_analysis.py @@ -1,16 +1,13 @@ -"""Python's half of native model analysis: per-model request rows and deferred analyses.""" +"""Python's half of native model analysis: per-model request rows and cache metrics.""" from __future__ import annotations from sqlbuild.adapter.contract.models import ExpressionInferenceProfile from sqlbuild.compiler.compile._helpers.analysis.cache import record_analysis_cache_metrics -from sqlbuild.compiler.compile._helpers.analysis.columns import ( +from sqlbuild.compiler.compile._helpers.analysis.reference_names import ( substitute_placeholder_defaults, table_function_analysis_name, ) -from sqlbuild.compiler.compile._helpers.analysis.compact import ( - analyze_columns_and_lineage_with_polyglot, -) from sqlbuild.compiler.compile._helpers.analysis.syntax_checks import names_set_operation from sqlbuild.compiler.compile._helpers.assembly.semantic_shapes import ( binding_relation_names, @@ -24,22 +21,18 @@ CompileModelInput, CompileSqlReference, ModelSqlAnalysisRequest, - NativeCompactAnalysis, - PolyglotAnalysisResult, ) -from sqlbuild.compiler.lineage.types import InferredNullability from sqlbuild.compiler.planner.constants import ( SNAPSHOT_DEFAULT_VALID_FROM_COLUMN, SNAPSHOT_DEFAULT_VALID_TO_COLUMN, ) from sqlbuild.compiler.planner.types import ContractPolicy, MaterializationType from sqlbuild.compiler.references.types import SqlReferenceKind -from sqlbuild.compiler.sql_analysis.models import SqlBindingDiagnostic from sqlbuild.spec.contracts.models import SchemaDynamicColumnFamily class PythonModelAnalysis: - """The analysed models' request facts, and today's Python analysis where native defers.""" + """The analysed models' request facts.""" def __init__( self, @@ -70,51 +63,6 @@ def model_rows(self) -> list[tuple[object, ...]]: return [_model_row(request) for request in self.requests] - def analyze_deferred( - self, - *, - model: int, - precomputed: NativeCompactAnalysis, - binding_schema: dict[str, dict[str, str]], - column_types_by_table: dict[str, dict[str, str]], - column_nullability_by_table: dict[str, dict[str, InferredNullability]], - ) -> PolyglotAnalysisResult: - """Python's legacy analysis of a model the native engine handed back.""" - - request: ModelSqlAnalysisRequest = self.requests[model] - return analyze_columns_and_lineage_with_polyglot( - query_sql=request.query_sql, - references=request.model_input.references, - placeholders=request.placeholders, - column_nullability_by_table=column_nullability_by_table, - column_types_by_table=column_types_by_table, - inference_profile=self._profile, - allow_compact_analysis=True, - binding_schema=binding_schema, - recover_cte_facts=_recovers_cte_facts(request.model_input), - precomputed=precomputed, - ) - - def enrich( - self, *, model: int, input_schemas: dict[str, dict[str, str]] - ) -> PolyglotAnalysisResult: - """Python's re-analysis of a model with its known input shapes.""" - - request: ModelSqlAnalysisRequest = self.requests[model] - return analyze_columns_and_lineage_with_polyglot( - query_sql=request.query_sql, - references=request.model_input.references, - placeholders=request.placeholders, - column_types_by_table=input_schemas, - column_nullability_by_table={ - table: dict.fromkeys(columns, InferredNullability.UNKNOWN) - for table, columns in input_schemas.items() - }, - inference_profile=self._profile, - allow_compact_analysis=True, - recover_cte_facts=_recovers_cte_facts(request.model_input), - ) - @staticmethod def family_row(family: SchemaDynamicColumnFamily) -> tuple[str, str, str, str, str, str | None]: """One declared dynamic column family as the native request row.""" @@ -128,44 +76,6 @@ def family_row(family: SchemaDynamicColumnFamily) -> tuple[str, str, str, str, s family.name_pattern, ) - @staticmethod - def legacy_precomputed( - *, - cleaned_sql: str, - binding_diagnostics: tuple[SqlBindingDiagnostic, ...], - lineage: list[tuple[str, int, int, list[tuple[str, str, str]]]] | None, - ) -> NativeCompactAnalysis: - """The native result Python's legacy analysis reads, with lineage rows when kept.""" - - if lineage is None: - return NativeCompactAnalysis( - cleaned_sql=cleaned_sql, - analysis=None, - projected=False, - binding_diagnostics=binding_diagnostics, - ) - pool: dict[str, int] = {} - facts: list[object] = [] - for output_column, transform_code, confidence_code, sources in lineage: - name_index: int = pool.setdefault(output_column, len(pool)) - source_indexes: list[list[int]] = [] - for source in sources: - source_indexes.append([pool.setdefault(value, len(pool)) for value in source]) - facts.append([name_index, None, 0, transform_code, confidence_code, source_indexes]) - return NativeCompactAnalysis( - cleaned_sql=cleaned_sql, - analysis=None, - projected=False, - binding_diagnostics=binding_diagnostics, - compact_rows=list(range(len(facts))), - compact_fact_rows=facts, - string_pool=tuple(pool), - compact_column_cache={}, - compact_template_index=0, - compact_fact_cache={}, - compact_decoded_fact_cache={}, - ) - def record_cached(self, *, hits: int, misses: int) -> None: """Record the analysis cache entries a native session read and missed.""" diff --git a/src/sqlbuild/compiler/compile/classes/semantic_completion_inputs.py b/src/sqlbuild/compiler/compile/classes/semantic_completion_inputs.py index a4cb6fb255..3d0c265b2a 100644 --- a/src/sqlbuild/compiler/compile/classes/semantic_completion_inputs.py +++ b/src/sqlbuild/compiler/compile/classes/semantic_completion_inputs.py @@ -5,12 +5,13 @@ from dataclasses import replace from sqlbuild.adapter.contract.models import ExpressionInferenceProfile -from sqlbuild.compiler.compile._helpers.analysis.compact import get_complete_schema_binding_request +from sqlbuild.compiler.compile._helpers.analysis.binding_requests import ( + get_complete_schema_binding_request, +) from sqlbuild.compiler.compile._helpers.assembly.metadata_validation import ( _audit_errors, _names, _sql_test_columns, - get_semantic_metadata_diagnostics, ) from sqlbuild.compiler.compile._helpers.assembly.native_declarations import ( known_declared_types, @@ -56,19 +57,6 @@ def revalidation_request( ), ) - @staticmethod - def metadata_diagnostics( - *, - project: CompiledProject, - profile: ExpressionInferenceProfile, - resource_sql_analysis: bool, - ) -> tuple[CompilerDiagnostic, ...]: - """The semantic metadata checks after type recovery.""" - - return get_semantic_metadata_diagnostics( - project=project, profile=profile, resource_sql_analysis=resource_sql_analysis - ) - @staticmethod def metadata_shapes( *, project: CompiledProject, profile: ExpressionInferenceProfile diff --git a/src/sqlbuild/compiler/compile/constants.py b/src/sqlbuild/compiler/compile/constants.py index 78f4df17d4..1cd0e085bb 100644 --- a/src/sqlbuild/compiler/compile/constants.py +++ b/src/sqlbuild/compiler/compile/constants.py @@ -78,26 +78,14 @@ } ) -SQL_WILDCARD_TOKEN: str = "*" SQL_OPEN_PAREN_TOKEN: str = "(" SQL_ARGUMENT_SEPARATOR_TOKEN: str = "," SQL_STATEMENT_TERMINATOR_TOKEN: str = ";" -SQL_SINGLE_QUOTE_TOKEN: str = "'" SQL_QUOTE_TOKENS: frozenset[str] = frozenset({"'", '"', "`", "$"}) -SQL_QUALIFIER_SEPARATOR_TOKEN: str = "." SQL_WITH_KEYWORD: str = "WITH" SQL_CEREMONIAL_SELECT_VALUE: str = "1" OMITTED_CEREMONIAL_SELECT_SQL: str = f"\nSELECT {SQL_CEREMONIAL_SELECT_VALUE}" -UNKNOWN_SQL_TYPE_NAME: str = "UNKNOWN" -DECIMAL_SQL_TYPE_NAME: str = "DECIMAL" -RESOLVED_SOURCE_CONFIDENCE: str = "resolved" -POLYGLOT_SET_OPERATION_EXPRESSION_NAMES: frozenset[str] = frozenset( - {"Union", "Intersect", "Except"} -) -POLYGLOT_SELECT_EXPRESSION_NAME: str = "Select" -POLYGLOT_COLUMN_EXPRESSION_NAME: str = "Column" -POLYGLOT_WRAPPER_EXPRESSION_NAMES: frozenset[str] = frozenset({"Annotated", "Subquery", "Paren"}) TABLE_FUNCTION_RETURN_KEYS: frozenset[str] = frozenset({"table"}) @@ -109,10 +97,6 @@ SQL_INTERPOLATION_TOKEN: str = "@@" TEMPLATE_OPEN_TOKEN: str = "${" -POLYGLOT_LITERAL_KIND: str = "literal" -POLYGLOT_ARRAY_KIND: str = "array_func" -POLYGLOT_STRUCTURED_KINDS: frozenset[str] = frozenset({"parse_json", "struct"}) -POLYGLOT_FUNCTION_KIND: str = "function" MACRO_CALL_PATTERN: re.Pattern[str] = re.compile(r"@[A-Za-z_][A-Za-z0-9_]*\s*\(") SQL_ARGUMENT_QUOTED_PARAMETER_PATTERN: re.Pattern[str] = re.compile( @@ -136,28 +120,9 @@ TABLE_FN_ACTUAL_TEST_CTE_NAME: str = "__table_fn_actual__" TABLE_FN_EXPECTED_TEST_CTE_NAME: str = "__table_fn_expected__" DEFAULT_SQL_TEST_MODE: SqlTestMode = SqlTestMode.MODEL -RESERVED_SQL_TEST_CTE_NAMES: frozenset[str] = frozenset( - { - "__actual", - "__expected__typed", - "__actual__projected", - "__missing__", - "__unexpected__", - } -) COMPILE_CACHE_DISABLE_ENV_VAR: str = "SQLBUILD_DISABLE_COMPILE_CACHE" COMPILE_CACHE_DISABLE_VALUE: str = "1" COMPILE_INPUT_READS: CompileInputReadRegistry = CompileInputReadRegistry() -COMPACT_ANALYSIS_RESPONSE_LENGTH: int = 2 -COMPACT_RELATION_STUB_PREFIX: str = "__sqlbuild_project_input_" -COMPACT_REFERENCE_MARKER_PATTERN: re.Pattern[str] = re.compile( - r'__(ref|seed|source|dbt_ref)\((?:"[^"]+"\s*,\s*)?"([^"]+)"\)' -) -COMPACT_UNSTUBBED_REFERENCE_KIND: str = "dbt_ref" -MIN_SHARED_BINDING_QUERY_MEMBERS: int = 2 -COMPACT_ANALYSIS_LEGACY_RESPONSE_LENGTH: int = 3 -COMPACT_ANALYSIS_FACT_LENGTH: int = 6 -COMPACT_ANALYSIS_SOURCE_LENGTH: int = 3 SQL_TEST_SCAN_STORE_FILE_NAME: str = "sql-test-scans.bin" RETIRED_FACT_CACHE_DIRECTORY_NAME: str = "facts-v1" SQL_TEST_SCAN_STORE_VERSION: str = "sql-test-scan-store-v1" diff --git a/src/sqlbuild/compiler/compile/main/_assemble_project.py b/src/sqlbuild/compiler/compile/main/_assemble_project.py index 09b05d4715..a165f9c226 100644 --- a/src/sqlbuild/compiler/compile/main/_assemble_project.py +++ b/src/sqlbuild/compiler/compile/main/_assemble_project.py @@ -8,25 +8,18 @@ from pathlib import Path from sqlbuild.adapter.contract.models import ExpressionInferenceProfile -from sqlbuild.compiler.compile._helpers.assembly.audit_gates import ( - attached_audit_gate_diagnostics, -) from sqlbuild.compiler.compile._helpers.assembly.project import assemble_compiled_project from sqlbuild.compiler.compile._helpers.diagnostics.collector import ( with_collected_compile_diagnostics, ) -from sqlbuild.compiler.compile._helpers.explicit_references.hook_reads import hook_read_diagnostics -from sqlbuild.compiler.compile._helpers.explicit_references.python_sql import ( - python_sql_reference_diagnostics, +from sqlbuild.compiler.compile._helpers.explicit_references.checks import ( + explicit_reference_report, ) from sqlbuild.compiler.compile.models import ( CompiledProject, CompileProjectInputs, - CompilerDiagnostic, PythonSqlReferenceReport, ) -from sqlbuild.compiler.frontier.main.native_stage_enabled import native_stage_enabled -from sqlbuild.compiler.frontier.types import NativeStage from sqlbuild.compiler.lineage.types import ColumnLineageMode from sqlbuild.compiler.macro_bridge.main.active_macro_bridge import active_macro_bridge from sqlbuild.compiler.macro_bridge.main.run_with_macro_bridge import run_with_macro_bridge @@ -54,26 +47,17 @@ def assemble_project( analysis_model_names=analysis_model_names, ) project: CompiledProject = ( - run_with_macro_bridge(stage=assemble) - if native_stage_enabled(NativeStage.MACRO_CALLS) and active_macro_bridge() is None - else assemble() - ) - python_sql: PythonSqlReferenceReport = ( - python_sql_reference_diagnostics( - project=project, discovered_inputs=inputs.discovered_inputs - ) - if inputs.project_config.references.enforce_explicit - else PythonSqlReferenceReport() + run_with_macro_bridge(stage=assemble) if active_macro_bridge() is None else assemble() ) - reference_diagnostics: tuple[CompilerDiagnostic, ...] = ( - *attached_audit_gate_diagnostics(project=project), - *hook_read_diagnostics(project=project), - *python_sql.diagnostics, + references: PythonSqlReferenceReport = explicit_reference_report( + project=project, + discovered_inputs=inputs.discovered_inputs, + enforce_explicit=inputs.project_config.references.enforce_explicit, ) - if not reference_diagnostics and not python_sql.unmatched: + if not references.diagnostics and not references.unmatched: return project return replace( project, - diagnostics=(*project.diagnostics, *reference_diagnostics), - unmatched_literal_sql_relations=python_sql.unmatched, + diagnostics=(*project.diagnostics, *references.diagnostics), + unmatched_literal_sql_relations=references.unmatched, ) diff --git a/src/sqlbuild/compiler/compile/main/expand_sql_with_spans.py b/src/sqlbuild/compiler/compile/main/expand_sql_with_spans.py index 2b1771d007..2f7bd57eca 100644 --- a/src/sqlbuild/compiler/compile/main/expand_sql_with_spans.py +++ b/src/sqlbuild/compiler/compile/main/expand_sql_with_spans.py @@ -11,9 +11,8 @@ ExpansionSpan, SqlExpansionContext, ) -from sqlbuild.compiler.frontier.main.native_stage_enabled import native_stage_enabled -from sqlbuild.compiler.frontier.main.report_native_fallback import report_native_fallback -from sqlbuild.compiler.frontier.types import NativeFallbackSite, NativeStage +from sqlbuild.compiler.frontier.main._report_native_fallback import report_native_fallback +from sqlbuild.compiler.frontier.types import NativeFallbackSite def expand_sql_with_spans( @@ -39,8 +38,7 @@ def expand_sql_with_spans( inaccessible_enums=declarations.inaccessible_enums, inaccessible_constants=declarations.inaccessible_constants, ) - if native_stage_enabled(NativeStage.MODEL_LOOP): - report_native_fallback(site=NativeFallbackSite.LINT_EXPANSION) + report_native_fallback(site=NativeFallbackSite.LINT_EXPANSION) return expand_authored_sql_with_spans( sql=sql, file_path=file_path, diff --git a/src/sqlbuild/compiler/compile/models.py b/src/sqlbuild/compiler/compile/models.py index b350f2d3de..86ecc786ca 100644 --- a/src/sqlbuild/compiler/compile/models.py +++ b/src/sqlbuild/compiler/compile/models.py @@ -1488,34 +1488,6 @@ class PreparedBindingQuery: shared: SharedBindingQuery | None = None -@dataclass(frozen=True) -class CompactAnalysisCacheModel: - """One ordered model identity and its project-model dependencies.""" - - name: str - cache_key: str | None - upstream_names: tuple[str, ...] - - -@dataclass(frozen=True) -class CompactAnalysisCachePlan: - """Current invocation identity for one compact analysis generation.""" - - context: AnalysisCacheContext - batch_key: str - cache_keys: tuple[str, ...] - reuse_keys: tuple[str, ...] - - -@dataclass(frozen=True) -class CompactAnalysisCacheCandidate: - """Validated persisted generation and positions safe for reuse.""" - - matching_indexes: tuple[int, ...] - preparation: CompactBatchPreparation - response: object - - @dataclass(frozen=True) class CompactProjectionCaches: """Shared identity caches used while decoding compact native facts.""" diff --git a/src/sqlbuild/compiler/contracts/_helpers/columns.py b/src/sqlbuild/compiler/contracts/_helpers/columns.py deleted file mode 100644 index d718379e33..0000000000 --- a/src/sqlbuild/compiler/contracts/_helpers/columns.py +++ /dev/null @@ -1,421 +0,0 @@ -"""Model column contract validation.""" - -from __future__ import annotations - -from functools import lru_cache -from pathlib import Path - -from sqlbuild.adapter.contract.types import TypeDialect -from sqlbuild.adapter.type_system.main.types_equal import types_equal -from sqlbuild.compiler.compile.exceptions import CompileInputError -from sqlbuild.compiler.compile.models import ( - CompiledModel, - CompilerDiagnostic, - DynamicColumnContractProof, - DynamicColumnFamilyProof, - InferredColumn, - RelatedLocation, -) -from sqlbuild.compiler.compile.types import ( - CompiledResourceType, - DiagnosticPhase, - DiagnosticSeverity, -) -from sqlbuild.compiler.discovery.main._model_output_column_locations import ( - extract_model_output_column_locations, -) -from sqlbuild.compiler.lineage.types import InferredNullability -from sqlbuild.compiler.planner.types import ContractPolicy -from sqlbuild.spec.contracts.models import ( - SchemaColumn, - SchemaDynamicColumnFamily, - SourceLocation, -) - -_MISSING_COLUMN_CODE: str = "K001" -_TYPE_MISMATCH_CODE: str = "K002" -_UNKNOWN_TYPE_CODE: str = "K003" -_NULLABILITY_MISMATCH_CODE: str = "K004" -_EXTRA_COLUMN_CODE: str = "K005" -_MISSING_DECLARATIONS_CODE: str = "K006" -_DYNAMIC_OUTPUT_NOT_PROVEN_CODE: str = "K011" - - -def collect_model_column_contract_diagnostics( - *, - model: CompiledModel, - validate_declared_shape: bool, - dialect: TypeDialect | str | None = None, -) -> tuple[CompilerDiagnostic, ...]: - """Collect diagnostics for one compiled model's declared column contract.""" - - contract_enforced: bool = model.config.values.get("contract") == ContractPolicy.ENFORCED - if model.schema_entry is None or not ( - model.schema_entry.columns or model.schema_entry.dynamic_columns - ): - if contract_enforced: - return (_missing_declarations_diagnostic(model),) - return () - diagnostics: list[CompilerDiagnostic] = [] - diagnostics.extend(_dynamic_column_diagnostics(model=model, dialect=dialect)) - dynamic_output_unproven: bool = any( - diagnostic.code == _DYNAMIC_OUTPUT_NOT_PROVEN_CODE for diagnostic in diagnostics - ) - if model.inferred_columns is None: - return tuple(diagnostics) - - inferred_by_name: dict[str, InferredColumn] = { - column.name: column for column in model.inferred_columns - } - if contract_enforced: - diagnostics.extend(_extra_column_diagnostics(model=model)) - declared_column: SchemaColumn - for declared_column in model.schema_entry.columns: - inferred_column: InferredColumn | None = inferred_by_name.get(declared_column.name) - if inferred_column is None: - if validate_declared_shape and not model.fast_lineage_has_star: - diagnostics.append( - _missing_column_diagnostic( - model=model, - column=declared_column, - contract_enforced=contract_enforced, - ) - ) - continue - if validate_declared_shape: - diagnostics.extend( - _nullability_diagnostics( - model=model, - declared_column=declared_column, - inferred_column=inferred_column, - ) - ) - if declared_column.type is None: - continue - type_enforcement: bool = model.schema_entry is not None and bool( - model.schema_entry.type_enforcement - ) - if not validate_declared_shape and not type_enforcement: - continue - if dynamic_output_unproven and inferred_column.type is None: - continue - diagnostics.extend( - _type_diagnostics( - model=model, - declared_column=declared_column, - inferred_column=inferred_column, - dialect=dialect, - contract_enforced=contract_enforced, - ) - ) - return tuple(diagnostics) - - -def _dynamic_column_diagnostics( - *, model: CompiledModel, dialect: TypeDialect | str | None -) -> tuple[CompilerDiagnostic, ...]: - if model.schema_entry is None or not model.schema_entry.dynamic_columns: - return () - proof: DynamicColumnContractProof | None = model.dynamic_column_contract - if proof is None or not proof.output_proven: - failure_reason: str = ( - proof.failure_reason - if proof is not None and proof.failure_reason - else "no compiler evidence" - ) - return ( - CompilerDiagnostic( - phase=DiagnosticPhase.CONTRACT, - severity=DiagnosticSeverity.ERROR, - code=_DYNAMIC_OUTPUT_NOT_PROVEN_CODE, - message=( - f"model '{model.name}' dynamic column contract is not proven: {failure_reason}" - ), - resource_type=CompiledResourceType.MODEL, - resource_name=model.name, - path=model.relative_path, - help=( - "project one supported runtime-dynamic pivot through a wildcard output " - "boundary " - "and declare every generated family" - ), - ), - ) - proof_by_name: dict[str, DynamicColumnFamilyProof] = { - family.name.casefold(): family for family in proof.families - } - diagnostics: list[CompilerDiagnostic] = [] - family: SchemaDynamicColumnFamily - for family in model.schema_entry.dynamic_columns: - family_proof: DynamicColumnFamilyProof | None = proof_by_name.get(family.name.casefold()) - inferred_type: str | None = family_proof.inferred_type if family_proof is not None else None - if inferred_type is None: - diagnostics.append( - CompilerDiagnostic( - phase=DiagnosticPhase.CONTRACT, - severity=DiagnosticSeverity.WARNING, - code=_UNKNOWN_TYPE_CODE, - message=( - f"dynamic column family '{family.name}' type could not be proven against " - f"declared {family.type}" - ), - resource_type=CompiledResourceType.MODEL, - resource_name=model.name, - path=model.relative_path, - help=( - "establish an authoritative type on the pivot value column or CAST the " - "type-preserving aggregate input explicitly" - ), - ) - ) - elif not types_equal(left=family.type, right=inferred_type, dialect=dialect): - diagnostics.append( - CompilerDiagnostic( - phase=DiagnosticPhase.CONTRACT, - severity=DiagnosticSeverity.ERROR, - code=_TYPE_MISMATCH_CODE, - message=( - f"dynamic column family '{family.name}' inferred as {inferred_type} " - f"but declared type is {family.type}" - ), - resource_type=CompiledResourceType.MODEL, - resource_name=model.name, - path=model.relative_path, - help="correct the family type or the pivot aggregate input type", - ) - ) - return tuple(diagnostics) - - -def _missing_declarations_diagnostic(model: CompiledModel) -> CompilerDiagnostic: - return CompilerDiagnostic( - phase=DiagnosticPhase.CONTRACT, - severity=DiagnosticSeverity.ERROR, - code=_MISSING_DECLARATIONS_CODE, - message=f"model '{model.name}' has contract enforced but declares no columns", - resource_type=CompiledResourceType.MODEL, - resource_name=model.name, - path=model.relative_path, - help=( - "add MODEL(columns (...)), declare a proven MODEL(dynamic_columns (...)) family, " - "or set contract none for this model" - ), - ) - - -def _extra_column_diagnostics(model: CompiledModel) -> tuple[CompilerDiagnostic, ...]: - if model.schema_entry is None or model.inferred_columns is None: - return () - declared_names: set[str] = {column.name for column in model.schema_entry.columns} - diagnostics: list[CompilerDiagnostic] = [] - inferred_column: InferredColumn - for inferred_column in model.inferred_columns: - if inferred_column.name in declared_names: - continue - diagnostics.append( - CompilerDiagnostic( - phase=DiagnosticPhase.CONTRACT, - severity=DiagnosticSeverity.ERROR, - code=_EXTRA_COLUMN_CODE, - message=( - f"column '{inferred_column.name}' is not declared in enforced contract " - f"for model '{model.name}'" - ), - resource_type=CompiledResourceType.MODEL, - resource_name=model.name, - column_name=inferred_column.name, - path=model.relative_path, - location=_output_column_location(model=model, column_name=inferred_column.name), - help=( - "add the column to the named SCHEMA or remove it from the SELECT list" - if model.schema_entry.model_schema is not None - else "add the column to MODEL(columns) or remove it from the SELECT list" - ), - ) - ) - return tuple(diagnostics) - - -def _nullability_diagnostics( - *, - model: CompiledModel, - declared_column: SchemaColumn, - inferred_column: InferredColumn, -) -> tuple[CompilerDiagnostic, ...]: - if not _declares_not_null(declared_column): - return () - if inferred_column.nullability != InferredNullability.NULLABLE: - return () - return ( - CompilerDiagnostic( - phase=DiagnosticPhase.CONTRACT, - severity=DiagnosticSeverity.ERROR, - code=_NULLABILITY_MISMATCH_CODE, - message=f"column '{declared_column.name}' is declared non-null but may be nullable", - resource_type=CompiledResourceType.MODEL, - resource_name=model.name, - column_name=declared_column.name, - path=model.relative_path, - location=declared_column.location, - related_locations=_output_related_locations( - model=model, - column_name=declared_column.name, - message="output expression proven nullable", - ), - help="use COALESCE, filter nulls explicitly, or remove the non-null contract", - ), - ) - - -def _declares_not_null(column: SchemaColumn) -> bool: - return column.nullable is False - - -def _missing_column_diagnostic( - *, model: CompiledModel, column: SchemaColumn, contract_enforced: bool -) -> CompilerDiagnostic: - contract_label: str = "enforced contract column" if contract_enforced else "declared column" - declared_in_named_schema: bool = ( - model.schema_entry is not None - and model.schema_entry.model_schema is not None - and column.location is not None - and column.location.path != model.relative_path - ) - declaration_label: str = ( - "the named SCHEMA declaration" if declared_in_named_schema else "MODEL(columns (...))" - ) - help_text: str = ( - f"add {column.name} to the SELECT list or correct {declaration_label}; " - "validation is active because this model declares contract enforced" - if contract_enforced - else ( - f"add {column.name} to the SELECT list or correct/remove {declaration_label}; " - f"{declaration_label} is validated using static SQL analysis because " - 'settings.column_contract_mode is "implicit" (the default). If this project ' - "intentionally uses columns only for metadata and audits, set [settings] " - 'column_contract_mode = "explicit"; models with contract enforced remain validated' - ) - ) - return CompilerDiagnostic( - phase=DiagnosticPhase.CONTRACT, - severity=DiagnosticSeverity.ERROR, - code=_MISSING_COLUMN_CODE, - message=( - f"{contract_label} '{column.name}' was not found in statically inferred output " - f"for model '{model.name}'" - ), - resource_type=CompiledResourceType.MODEL, - resource_name=model.name, - column_name=column.name, - path=model.relative_path, - location=column.location, - help=help_text, - ) - - -def _type_diagnostics( - *, - model: CompiledModel, - declared_column: SchemaColumn, - inferred_column: InferredColumn, - dialect: TypeDialect | str | None, - contract_enforced: bool, -) -> tuple[CompilerDiagnostic, ...]: - declared_type: str | None = declared_column.type - if declared_type is None: - raise CompileInputError( - f"model '{model.name}' column '{declared_column.name}' reached type validation " - "without a declared type", - code="P003", - ) - type_enforcement: bool = model.schema_entry is not None and bool( - model.schema_entry.type_enforcement - ) - if inferred_column.type is None: - if not type_enforcement or inferred_column.name in model.unchecked_output_columns: - return () - return ( - CompilerDiagnostic( - phase=DiagnosticPhase.CONTRACT, - severity=DiagnosticSeverity.WARNING, - code=_UNKNOWN_TYPE_CODE, - message=( - f"column '{declared_column.name}' type could not be proven against " - f"declared {declared_type}" - ), - resource_type=CompiledResourceType.MODEL, - resource_name=model.name, - column_name=declared_column.name, - path=model.relative_path, - location=declared_column.location, - related_locations=_output_related_locations( - model=model, - column_name=declared_column.name, - message="output expression with unproven type", - ), - help="add an explicit CAST if this declared type should be checked statically", - ), - ) - - if types_equal(left=declared_type, right=inferred_column.type, dialect=dialect): - return () - - return ( - CompilerDiagnostic( - phase=DiagnosticPhase.CONTRACT, - severity=DiagnosticSeverity.ERROR - if type_enforcement or contract_enforced - else DiagnosticSeverity.WARNING, - code=_TYPE_MISMATCH_CODE, - message=( - f"column '{declared_column.name}' inferred as {inferred_column.type} " - f"but declared type is {declared_type}" - ), - resource_type=CompiledResourceType.MODEL, - resource_name=model.name, - column_name=declared_column.name, - path=model.relative_path, - location=declared_column.location, - related_locations=_output_related_locations( - model=model, - column_name=declared_column.name, - message=f"inferred {inferred_column.type}", - ), - help="change the declared type or cast the expression explicitly", - ), - ) - - -def _output_related_locations( - *, model: CompiledModel, column_name: str, message: str -) -> tuple[RelatedLocation, ...]: - location: SourceLocation | None = _output_column_location(model=model, column_name=column_name) - if location is None: - return () - return (RelatedLocation(label="output", location=location, message=message),) - - -def _output_column_location(*, model: CompiledModel, column_name: str) -> SourceLocation | None: - location: SourceLocation | None = model.output_column_locations.get(column_name) - if location is not None or not model.authored_sql: - return location - return dict( - _lazy_output_column_locations( - contents=model.authored_sql, - relative_path=model.relative_path, - extract_implicit_alias_columns=model.extract_implicit_alias_columns, - ) - ).get(column_name) - - -@lru_cache(maxsize=256) -def _lazy_output_column_locations( - *, contents: str, relative_path: Path, extract_implicit_alias_columns: bool -) -> tuple[tuple[str, SourceLocation], ...]: - return tuple( - extract_model_output_column_locations( - contents=contents, - relative_path=relative_path, - extract_implicit_alias_columns=extract_implicit_alias_columns, - ).items() - ) diff --git a/src/sqlbuild/compiler/contracts/_helpers/evaluation.py b/src/sqlbuild/compiler/contracts/_helpers/evaluation.py deleted file mode 100644 index 794bf59167..0000000000 --- a/src/sqlbuild/compiler/contracts/_helpers/evaluation.py +++ /dev/null @@ -1,42 +0,0 @@ -"""Which models need contract evaluation, and Python's evaluation of one model.""" - -from __future__ import annotations - -from sqlbuild.adapter.contract.types import TypeDialect -from sqlbuild.compiler.compile.models import CompiledModel, CompilerDiagnostic -from sqlbuild.compiler.contracts._helpers.columns import collect_model_column_contract_diagnostics -from sqlbuild.compiler.planner.types import ContractPolicy -from sqlbuild.spec.contracts.types import ColumnContractMode - - -def requires_contract_evaluation(*, model: CompiledModel, mode: ColumnContractMode) -> bool: - """Whether the model declares a shape to validate or enforces declared types.""" - - if declared_shape_validation_is_active(model=model, mode=mode): - return True - return model.schema_entry is not None and bool(model.schema_entry.type_enforcement) - - -def declared_shape_validation_is_active(*, model: CompiledModel, mode: ColumnContractMode) -> bool: - """Whether the model's declared columns are validated against its inferred output.""" - - contract: object = model.config.values.get("contract") - if contract == ContractPolicy.ENFORCED: - return True - if contract == ContractPolicy.NONE: - return False - return mode == ColumnContractMode.IMPLICIT and bool( - model.schema_entry is not None and model.schema_entry.columns - ) - - -def python_model_contract_diagnostics( - *, model: CompiledModel, mode: ColumnContractMode, dialect: TypeDialect | str | None -) -> tuple[CompilerDiagnostic, ...]: - """Python's contract diagnostics for one model that requires evaluation.""" - - return collect_model_column_contract_diagnostics( - model=model, - validate_declared_shape=declared_shape_validation_is_active(model=model, mode=mode), - dialect=dialect, - ) diff --git a/src/sqlbuild/compiler/contracts/_helpers/native_contracts.py b/src/sqlbuild/compiler/contracts/_helpers/native_contracts.py index 5ed42e44b8..b296483fde 100644 --- a/src/sqlbuild/compiler/contracts/_helpers/native_contracts.py +++ b/src/sqlbuild/compiler/contracts/_helpers/native_contracts.py @@ -16,18 +16,9 @@ DiagnosticPhase, DiagnosticSeverity, ) -from sqlbuild.compiler.contracts._helpers.columns import ( - _output_column_location, - _output_related_locations, -) -from sqlbuild.compiler.contracts._helpers.evaluation import ( - python_model_contract_diagnostics, - requires_contract_evaluation, -) -from sqlbuild.compiler.contracts._helpers.native_deferrals import record_contract_deferral -from sqlbuild.compiler.contracts.constants import ( - NATIVE_CONTRACTS_DEFERRAL_SITE, - NATIVE_CONTRACTS_UNSUPPORTED_INPUT, +from sqlbuild.compiler.contracts._helpers.output_locations import ( + output_column_location, + output_related_locations, ) from sqlbuild.compiler.contracts.models import ContractValidationResult from sqlbuild.compiler.lineage.types import InferredNullability @@ -53,33 +44,19 @@ def native_model_contracts( *, project: CompiledProject, dialect: TypeDialect | str | None -) -> ContractValidationResult | None: - """Return `evaluate_model_contracts`'s result, with deferred models evaluated by Python.""" +) -> ContractValidationResult: + """Return every model's column contract diagnostics, in model order.""" - if not isinstance(dialect, str | None): - record_contract_deferral( - kind=NATIVE_CONTRACTS_UNSUPPORTED_INPUT, site=NATIVE_CONTRACTS_DEFERRAL_SITE - ) - return None mode: ColumnContractMode = project.settings.column_contract_mode - outcomes: list[tuple[str | None, list[_DiagnosticRow]]] = ( - _native.evaluate_native_model_contracts( - ( - str(dialect or "generic"), - mode == ColumnContractMode.IMPLICIT, - [_model_row(model) for model in project.models], - ) + outcomes: list[list[_DiagnosticRow]] = _native.evaluate_native_model_contracts( + ( + str(dialect or "generic"), + mode == ColumnContractMode.IMPLICIT, + [_model_row(model) for model in project.models], ) ) diagnostics: list[CompilerDiagnostic] = [] - for model, (deferral, rows) in zip(project.models, outcomes, strict=True): - if deferral is not None: - record_contract_deferral(kind=deferral, site=NATIVE_CONTRACTS_DEFERRAL_SITE) - if requires_contract_evaluation(model=model, mode=mode): - diagnostics.extend( - python_model_contract_diagnostics(model=model, mode=mode, dialect=dialect) - ) - continue + for model, rows in zip(project.models, outcomes, strict=True): diagnostics.extend(_diagnostic(model=model, row=row) for row in rows) return ContractValidationResult(diagnostics=tuple(diagnostics)) @@ -159,7 +136,7 @@ def _location( if declared_index is not None and model.schema_entry is not None: return model.schema_entry.columns[declared_index].location if output_column is not None: - return _output_column_location(model=model, column_name=output_column) + return output_column_location(model=model, column_name=output_column) return None @@ -169,4 +146,4 @@ def _related_locations( if related is None: return () column_name, message = related - return _output_related_locations(model=model, column_name=column_name, message=message) + return output_related_locations(model=model, column_name=column_name, message=message) diff --git a/src/sqlbuild/compiler/contracts/_helpers/native_deferrals.py b/src/sqlbuild/compiler/contracts/_helpers/native_deferrals.py deleted file mode 100644 index 18d245c041..0000000000 --- a/src/sqlbuild/compiler/contracts/_helpers/native_deferrals.py +++ /dev/null @@ -1,23 +0,0 @@ -"""Debug-only record of contract work the native engine hands back to Python.""" - -from __future__ import annotations - -import json -import os -from pathlib import Path - -from sqlbuild.compiler.lineage.constants import ANALYSIS_DEFERRAL_RECORD_PREFIX -from sqlbuild.compiler.sql_analysis.constants import ANALYSIS_RECORD_DIR_ENV_VAR - - -def record_contract_deferral(*, kind: str, site: str) -> None: - """Append one `{"kind", "site"}` line when the analysis record directory is set.""" - - directory: str | None = os.environ.get(ANALYSIS_RECORD_DIR_ENV_VAR) - if not directory: - return - target: Path = Path(directory) - target.mkdir(parents=True, exist_ok=True) - record: str = json.dumps({"kind": kind, "site": site}) - with open(target / f"{ANALYSIS_DEFERRAL_RECORD_PREFIX}{os.getpid()}.jsonl", "a") as handle: - _ = handle.write(record + "\n") diff --git a/src/sqlbuild/compiler/contracts/_helpers/native_promotion.py b/src/sqlbuild/compiler/contracts/_helpers/native_promotion.py index a345650b26..c143956477 100644 --- a/src/sqlbuild/compiler/contracts/_helpers/native_promotion.py +++ b/src/sqlbuild/compiler/contracts/_helpers/native_promotion.py @@ -3,31 +3,22 @@ from __future__ import annotations import sqlbuild._native as _native +from sqlbuild.adapter.contract.types import TablePromotionMode from sqlbuild.compiler.compile.models import CompiledModel, CompiledProject, CompilerDiagnostic from sqlbuild.compiler.compile.types import ( CompiledResourceType, DiagnosticPhase, DiagnosticSeverity, ) -from sqlbuild.compiler.contracts._helpers.native_deferrals import record_contract_deferral -from sqlbuild.compiler.contracts.constants import ( - NATIVE_CONTRACTS_UNSUPPORTED_INPUT, - NATIVE_PROMOTION_DEFERRAL_SITE, -) from sqlbuild.compiler.planner.types import MaterializationType def native_promotion_conflicts( - *, project: CompiledProject, adapter_default: object, settings_file: str -) -> tuple[CompilerDiagnostic, ...] | None: - """Return `promotion_conflict_diagnostics`'s result, or None where Python must build it.""" + *, project: CompiledProject, adapter_default: TablePromotionMode, settings_file: str +) -> tuple[CompilerDiagnostic, ...]: + """Return one K011 error per enforced-contract table model under immediate promotion.""" - explicit_mode: object = project.settings.table_promotion_mode - if not isinstance(adapter_default, str) or not isinstance(explicit_mode, str | None): - record_contract_deferral( - kind=NATIVE_CONTRACTS_UNSUPPORTED_INPUT, site=NATIVE_PROMOTION_DEFERRAL_SITE - ) - return None + explicit_mode: str | None = project.settings.table_promotion_mode conflicts: list[tuple[int, str, str, str]] = _native.native_promotion_conflicts( ( explicit_mode, diff --git a/src/sqlbuild/compiler/contracts/_helpers/output_locations.py b/src/sqlbuild/compiler/contracts/_helpers/output_locations.py new file mode 100644 index 0000000000..70cf20d658 --- /dev/null +++ b/src/sqlbuild/compiler/contracts/_helpers/output_locations.py @@ -0,0 +1,51 @@ +"""Source locations of a model's output columns, for contract diagnostics.""" + +from __future__ import annotations + +from functools import lru_cache +from pathlib import Path + +from sqlbuild.compiler.compile.models import CompiledModel, RelatedLocation +from sqlbuild.compiler.discovery.main._model_output_column_locations import ( + extract_model_output_column_locations, +) +from sqlbuild.spec.contracts.models import SourceLocation + + +def output_related_locations( + *, model: CompiledModel, column_name: str, message: str +) -> tuple[RelatedLocation, ...]: + """The output column's location as a related location, when the model has one.""" + + location: SourceLocation | None = output_column_location(model=model, column_name=column_name) + if location is None: + return () + return (RelatedLocation(label="output", location=location, message=message),) + + +def output_column_location(*, model: CompiledModel, column_name: str) -> SourceLocation | None: + """Where the model's SQL produces one output column.""" + + location: SourceLocation | None = model.output_column_locations.get(column_name) + if location is not None or not model.authored_sql: + return location + return dict( + _lazy_output_column_locations( + contents=model.authored_sql, + relative_path=model.relative_path, + extract_implicit_alias_columns=model.extract_implicit_alias_columns, + ) + ).get(column_name) + + +@lru_cache(maxsize=256) +def _lazy_output_column_locations( + *, contents: str, relative_path: Path, extract_implicit_alias_columns: bool +) -> tuple[tuple[str, SourceLocation], ...]: + return tuple( + extract_model_output_column_locations( + contents=contents, + relative_path=relative_path, + extract_implicit_alias_columns=extract_implicit_alias_columns, + ).items() + ) diff --git a/src/sqlbuild/compiler/contracts/_helpers/promotion.py b/src/sqlbuild/compiler/contracts/_helpers/promotion.py deleted file mode 100644 index 62d948a78f..0000000000 --- a/src/sqlbuild/compiler/contracts/_helpers/promotion.py +++ /dev/null @@ -1,112 +0,0 @@ -"""Compile-time conflicts between enforced contracts and immediate table promotion.""" - -from __future__ import annotations - -from sqlbuild.adapter.contract.types import TablePromotionMode -from sqlbuild.compiler.compile.models import CompiledModel, CompiledProject, CompilerDiagnostic -from sqlbuild.compiler.compile.types import ( - CompiledResourceType, - DiagnosticPhase, - DiagnosticSeverity, -) -from sqlbuild.compiler.discovery.constants import ( - SETTINGS_SECTION, - STAGED_PROMOTION_MODE, - TABLE_PROMOTION_MODE_SETTING_KEY, -) -from sqlbuild.compiler.planner.types import ContractPolicy, IncrementalMode, MaterializationType -from sqlbuild.errors.setting_help.main.join_helps import join_helps -from sqlbuild.errors.setting_help.main.setting_help import setting_help -from sqlbuild.errors.setting_help.main.setting_note import setting_note -from sqlbuild.errors.setting_help.main.snippet_help import snippet_help - -_PROMOTION_CONFLICT_CODE: str = "K011" -_STAGED_LIFECYCLE_MATERIALIZATIONS: frozenset[MaterializationType] = frozenset( - {MaterializationType.TABLE, MaterializationType.INCREMENTAL} -) - - -def promotion_conflict_diagnostics_impl( - *, - project: CompiledProject, - adapter_default: TablePromotionMode, - settings_file: str, -) -> tuple[CompilerDiagnostic, ...]: - """Report each enforced-contract table model when promotion is immediate.""" - - explicit_mode: str | None = project.settings.table_promotion_mode - effective_mode: str = explicit_mode if explicit_mode is not None else adapter_default - if effective_mode != TablePromotionMode.IMMEDIATE: - return () - help_text: str = _conflict_help( - explicit=explicit_mode is not None, - adapter_default=adapter_default, - settings_file=settings_file, - ) - return tuple( - CompilerDiagnostic( - phase=DiagnosticPhase.CONTRACT, - severity=DiagnosticSeverity.ERROR, - code=_PROMOTION_CONFLICT_CODE, - message=( - f"model '{model.name}': contract enforced requires staged table promotion; " - "immediate table promotion cannot validate runtime output before target mutation" - ), - resource_type=CompiledResourceType.MODEL, - resource_name=model.name, - path=model.relative_path, - help=help_text, - ) - for model in project.models - if _uses_staged_table_lifecycle(model) - ) - - -def _uses_staged_table_lifecycle(model: CompiledModel) -> bool: - values: dict[str, object] = model.config.values - if values.get("contract") != ContractPolicy.ENFORCED: - return False - materialized: object = values.get("materialized", MaterializationType.TABLE) - return ( - materialized in _STAGED_LIFECYCLE_MATERIALIZATIONS - and values.get("incremental_mode") != IncrementalMode.MICROBATCH - ) - - -def _conflict_help( - *, explicit: bool, adapter_default: TablePromotionMode, settings_file: str -) -> str: - current: str = ( - setting_note( - file_name=settings_file, - section=SETTINGS_SECTION, - key=TABLE_PROMOTION_MODE_SETTING_KEY, - value=TablePromotionMode.IMMEDIATE.value, - explicit=explicit, - ) - + "; enforced contracts are validated in a staging table before promotion" - ) - staged_fix: str = ( - snippet_help( - purpose="remove that line to use the default staged promotion", - target=f"or set this in {settings_file}", - lines=( - f"[{SETTINGS_SECTION}]", - f'{TABLE_PROMOTION_MODE_SETTING_KEY} = "{STAGED_PROMOTION_MODE}"', - ), - ) - if explicit and adapter_default == TablePromotionMode.STAGED - else setting_help( - purpose="to validate enforced contracts before promotion", - file_name=settings_file, - section=SETTINGS_SECTION, - key=TABLE_PROMOTION_MODE_SETTING_KEY, - value=STAGED_PROMOTION_MODE, - ) - ) - return join_helps( - current, - staged_fix, - "or remove the model's enforced contract: `contract enforced` in its MODEL header, or " - '`contract = "enforced"` in the [defaults] or [path_defaults] entry that applies to it', - ) diff --git a/src/sqlbuild/compiler/contracts/constants.py b/src/sqlbuild/compiler/contracts/constants.py index d51f5c1015..beb870aca5 100644 --- a/src/sqlbuild/compiler/contracts/constants.py +++ b/src/sqlbuild/compiler/contracts/constants.py @@ -1,6 +1,3 @@ """Model contract decision constants.""" NOT_NULL_AUDIT_NAME: str = "not_null" -NATIVE_CONTRACTS_DEFERRAL_SITE: str = "contracts/columns.py" -NATIVE_PROMOTION_DEFERRAL_SITE: str = "contracts/promotion.py" -NATIVE_CONTRACTS_UNSUPPORTED_INPUT: str = "unsupported_input" diff --git a/src/sqlbuild/compiler/contracts/main/_evaluate_native_model_contracts.py b/src/sqlbuild/compiler/contracts/main/_evaluate_native_model_contracts.py index c35b77e9ef..e9e0e4489f 100644 --- a/src/sqlbuild/compiler/contracts/main/_evaluate_native_model_contracts.py +++ b/src/sqlbuild/compiler/contracts/main/_evaluate_native_model_contracts.py @@ -1,4 +1,4 @@ -"""Evaluate model contracts natively for the preview compiler engine.""" +"""Evaluate model contracts natively.""" from __future__ import annotations @@ -10,7 +10,7 @@ def evaluate_native_model_contracts( *, project: CompiledProject, dialect: TypeDialect | str | None -) -> ContractValidationResult | None: - """Return the contract diagnostics, or None where Python must evaluate the contracts.""" +) -> ContractValidationResult: + """Return the contract diagnostics; Python evaluates only the models native defers.""" return native_model_contracts(project=project, dialect=dialect) diff --git a/src/sqlbuild/compiler/contracts/main/_native_promotion_conflicts.py b/src/sqlbuild/compiler/contracts/main/_native_promotion_conflicts.py index af639c188d..0327b490a2 100644 --- a/src/sqlbuild/compiler/contracts/main/_native_promotion_conflicts.py +++ b/src/sqlbuild/compiler/contracts/main/_native_promotion_conflicts.py @@ -1,15 +1,16 @@ -"""Find promotion conflicts natively for the preview compiler engine.""" +"""Find promotion conflicts natively.""" from __future__ import annotations +from sqlbuild.adapter.contract.types import TablePromotionMode from sqlbuild.compiler.compile.models import CompiledProject, CompilerDiagnostic from sqlbuild.compiler.contracts._helpers.native_promotion import native_promotion_conflicts def native_promotion_conflict_diagnostics( - *, project: CompiledProject, adapter_default: object, settings_file: str -) -> tuple[CompilerDiagnostic, ...] | None: - """Return the K011 promotion conflicts, or None where Python must find them.""" + *, project: CompiledProject, adapter_default: TablePromotionMode, settings_file: str +) -> tuple[CompilerDiagnostic, ...]: + """Return the K011 promotion conflicts.""" return native_promotion_conflicts( project=project, adapter_default=adapter_default, settings_file=settings_file diff --git a/src/sqlbuild/compiler/contracts/main/promotion_conflicts.py b/src/sqlbuild/compiler/contracts/main/promotion_conflicts.py index 33edbfd775..5e0745a85d 100644 --- a/src/sqlbuild/compiler/contracts/main/promotion_conflicts.py +++ b/src/sqlbuild/compiler/contracts/main/promotion_conflicts.py @@ -4,13 +4,9 @@ from sqlbuild.adapter.contract.types import TablePromotionMode from sqlbuild.compiler.compile.models import CompiledProject, CompilerDiagnostic -from sqlbuild.compiler.contracts._helpers.promotion import promotion_conflict_diagnostics_impl from sqlbuild.compiler.contracts.main._native_promotion_conflicts import ( native_promotion_conflict_diagnostics, ) -from sqlbuild.compiler.frontier.main.native_stage_enabled import native_stage_enabled -from sqlbuild.compiler.frontier.main.report_native_answer import report_native_answer -from sqlbuild.compiler.frontier.types import NativeStage def promotion_conflict_diagnostics( @@ -21,13 +17,6 @@ def promotion_conflict_diagnostics( ) -> tuple[CompilerDiagnostic, ...]: """Return one K011 error per enforced-contract table model under immediate promotion.""" - if native_stage_enabled(NativeStage.CONTRACTS): - native: tuple[CompilerDiagnostic, ...] | None = native_promotion_conflict_diagnostics( - project=project, adapter_default=adapter_default, settings_file=settings_file - ) - if native is not None: - report_native_answer(stage=NativeStage.CONTRACTS, kind="promotion_checks") - return native - return promotion_conflict_diagnostics_impl( + return native_promotion_conflict_diagnostics( project=project, adapter_default=adapter_default, settings_file=settings_file ) diff --git a/src/sqlbuild/compiler/contracts/main/validate.py b/src/sqlbuild/compiler/contracts/main/validate.py index a51a6dda3b..548ac16eec 100644 --- a/src/sqlbuild/compiler/contracts/main/validate.py +++ b/src/sqlbuild/compiler/contracts/main/validate.py @@ -3,19 +3,11 @@ from __future__ import annotations from sqlbuild.adapter.contract.types import TypeDialect -from sqlbuild.compiler.compile.models import CompiledProject, CompilerDiagnostic -from sqlbuild.compiler.contracts._helpers.evaluation import ( - python_model_contract_diagnostics, - requires_contract_evaluation, -) +from sqlbuild.compiler.compile.models import CompiledProject from sqlbuild.compiler.contracts.main._evaluate_native_model_contracts import ( evaluate_native_model_contracts, ) from sqlbuild.compiler.contracts.models import ContractValidationResult -from sqlbuild.compiler.frontier.main.native_stage_enabled import native_stage_enabled -from sqlbuild.compiler.frontier.main.report_native_answer import report_native_answer -from sqlbuild.compiler.frontier.types import NativeStage -from sqlbuild.spec.contracts.types import ColumnContractMode def evaluate_model_contracts( @@ -25,21 +17,4 @@ def evaluate_model_contracts( ) -> ContractValidationResult: """Evaluate model header column contracts against inferred output columns.""" - if native_stage_enabled(NativeStage.CONTRACTS): - native_result: ContractValidationResult | None = evaluate_native_model_contracts( - project=project, dialect=dialect - ) - if native_result is not None: - report_native_answer(stage=NativeStage.CONTRACTS, kind="contract_validations") - return native_result - mode: ColumnContractMode = project.settings.column_contract_mode - if not any(requires_contract_evaluation(model=model, mode=mode) for model in project.models): - return ContractValidationResult(diagnostics=()) - - diagnostics: list[CompilerDiagnostic] = [] - for model in project.models: - if requires_contract_evaluation(model=model, mode=mode): - diagnostics.extend( - python_model_contract_diagnostics(model=model, mode=mode, dialect=dialect) - ) - return ContractValidationResult(diagnostics=tuple(diagnostics)) + return evaluate_native_model_contracts(project=project, dialect=dialect) diff --git a/src/sqlbuild/compiler/discovery/_helpers/native/declaration_files.py b/src/sqlbuild/compiler/discovery/_helpers/native/declaration_files.py index 6c1bfba3d9..d06ee98589 100644 --- a/src/sqlbuild/compiler/discovery/_helpers/native/declaration_files.py +++ b/src/sqlbuild/compiler/discovery/_helpers/native/declaration_files.py @@ -48,8 +48,6 @@ ModelSchemaDeclaration, ) from sqlbuild.compiler.discovery.types import NativeFileScope, NativeLocation, NativeScopeFields -from sqlbuild.compiler.frontier.main.report_native_answer import report_native_answer -from sqlbuild.compiler.frontier.types import NativeStage from sqlbuild.compiler.scopes.types import DeclarationKind, ScopeKind type _NativeDeclarationFile = tuple[str, NativeFileScope | None, tuple[object, ...]] @@ -178,7 +176,6 @@ def native_seed_files(*, project_dir: Path) -> tuple[DiscoveredSeedFile, ...]: DiscoveredSeedFile(file_path=project_dir / relative_path, relative_path=Path(relative_path)) for relative_path, _scope, _payload in _native_files(project_dir=project_dir, kind="seed") ) - report_native_answer(stage=NativeStage.DECLARATION_FILES, kind="seed_files", units=len(seeds)) return seeds @@ -259,12 +256,10 @@ def _record[RecordT]( scope, payload = item tag: object = payload[0] if tag == NATIVE_PARSED_TAG: - report_native_answer(stage=NativeStage.DECLARATION_FILES, kind="parsed_files") return build( project_dir=project_dir, relative_path=relative_path, scope=scope, payload=payload ) if tag == NATIVE_FAILED_TAG: - report_native_answer(stage=NativeStage.DECLARATION_FILES, kind="failed_files") raise native_failure(payload) raise native_read_error(payload=payload, file_path=project_dir / relative_path) diff --git a/src/sqlbuild/compiler/discovery/_helpers/native/model_files.py b/src/sqlbuild/compiler/discovery/_helpers/native/model_files.py index ee78a71c88..4c166f2493 100644 --- a/src/sqlbuild/compiler/discovery/_helpers/native/model_files.py +++ b/src/sqlbuild/compiler/discovery/_helpers/native/model_files.py @@ -28,8 +28,6 @@ ) from sqlbuild.compiler.discovery.models import DiscoveredSqlModelFile, DiscoveryFileFault from sqlbuild.compiler.discovery.types import NativeFiles, NativeLocation -from sqlbuild.compiler.frontier.main.report_native_answer import report_native_answer -from sqlbuild.compiler.frontier.types import NativeStage def discover_native_model_files( @@ -60,7 +58,6 @@ def discover_native_model_files( project_dir=project_dir, ) seed_snapshot_listings(project_dir=project_dir, tree=tree) - report_native_answer(stage=NativeStage.DISCOVERY, kind="model_file_listings") return materialise_native_files( project_dir=project_dir, files=( diff --git a/src/sqlbuild/compiler/discovery/main/_require_supported_python.py b/src/sqlbuild/compiler/discovery/main/_require_supported_python.py new file mode 100644 index 0000000000..00332f5cb7 --- /dev/null +++ b/src/sqlbuild/compiler/discovery/main/_require_supported_python.py @@ -0,0 +1,14 @@ +"""Require a Python whose string semantics the native extension reproduces.""" + +from __future__ import annotations + +from typing import cast + +from sqlbuild.compiler.discovery._helpers.native.payloads import native_text_runtime + + +def require_supported_python() -> tuple[int, int]: + """The running Python's version; raises `UnsupportedPythonError` where native lacks its text.""" + + runtime: dict[str, object] = native_text_runtime() + return cast(tuple[int, int], runtime["python_version"]) diff --git a/src/sqlbuild/compiler/frontier/_helpers/engine.py b/src/sqlbuild/compiler/frontier/_helpers/engine.py index 93b9cb5ff0..33a7850b0c 100644 --- a/src/sqlbuild/compiler/frontier/_helpers/engine.py +++ b/src/sqlbuild/compiler/frontier/_helpers/engine.py @@ -6,6 +6,7 @@ COMPILER_ENGINE_ENV_VAR, COMPILER_ENGINE_VALUES, DEFAULT_COMPILER_ENGINE, + REMOVED_PYTHON_ENGINE, ) from sqlbuild.compiler.frontier.exceptions import CompilerEngineError from sqlbuild.compiler.frontier.types import CompilerEngine @@ -17,10 +18,22 @@ def active_compiler_engine() -> CompilerEngine: raw_value: str | None = os.environ.get(COMPILER_ENGINE_ENV_VAR) if not raw_value: return DEFAULT_COMPILER_ENGINE + return parse_compiler_engine(raw_value=raw_value, source=COMPILER_ENGINE_ENV_VAR) + + +def parse_compiler_engine(*, raw_value: str, source: str) -> CompilerEngine: + """Return the engine `raw_value` names, explaining the removed Python engine.""" + + if raw_value == REMOVED_PYTHON_ENGINE: + raise CompilerEngineError( + f"{source} {REMOVED_PYTHON_ENGINE!r} is no longer supported: SQLBuild removed its " + "Python compiler, and the native compiler is the default. Unset " + f"{COMPILER_ENGINE_ENV_VAR} and drop --compiler-engine to use it; to run the " + "Python compiler for comparison, pin an earlier SQLBuild release." + ) try: return CompilerEngine(raw_value) except ValueError as error: raise CompilerEngineError( - f"{COMPILER_ENGINE_ENV_VAR} must be one of {', '.join(COMPILER_ENGINE_VALUES)} " - f"(got {raw_value!r})" + f"{source} must be one of {', '.join(COMPILER_ENGINE_VALUES)} (got {raw_value!r})" ) from error diff --git a/src/sqlbuild/compiler/frontier/_helpers/native_frontier.py b/src/sqlbuild/compiler/frontier/_helpers/native_frontier.py index 031f90ca47..1505be9c60 100644 --- a/src/sqlbuild/compiler/frontier/_helpers/native_frontier.py +++ b/src/sqlbuild/compiler/frontier/_helpers/native_frontier.py @@ -2,8 +2,7 @@ from collections.abc import Callable -from sqlbuild.compiler.frontier.main.native_stage_enabled import native_stage_enabled -from sqlbuild.compiler.frontier.types import CompilerStage, NativeStage +from sqlbuild.compiler.frontier.types import CompilerStage from sqlbuild.compiler.macro_bridge.main.run_with_macro_bridge import run_with_macro_bridge @@ -17,8 +16,6 @@ def native_frontier[T]( if native_stage is not None: return native_stage() - if until is CompilerStage.COMPILE_PROJECT_INPUTS and native_stage_enabled( - NativeStage.MACRO_CALLS - ): + if until is CompilerStage.COMPILE_PROJECT_INPUTS: return run_with_macro_bridge(stage=python_stage) return python_stage() diff --git a/src/sqlbuild/compiler/frontier/constants.py b/src/sqlbuild/compiler/frontier/constants.py index cbb99ff7bb..6dad7ec4e2 100644 --- a/src/sqlbuild/compiler/frontier/constants.py +++ b/src/sqlbuild/compiler/frontier/constants.py @@ -10,31 +10,14 @@ COMPILER_ENGINE_VALUES: tuple[str, ...] = tuple(engine.value for engine in CompilerEngine) NATIVE_CACHE_NAMESPACE_SUFFIX: str = "-native-v1" NATIVE_PREVIEW_CACHE_NAMESPACE_SUFFIX: str = "-native-preview-v1" +REMOVED_PYTHON_ENGINE: str = "python" ENGINE_CACHE_NAMESPACE_SUFFIXES: dict[CompilerEngine, str] = { - CompilerEngine.PYTHON: "", CompilerEngine.NATIVE: NATIVE_CACHE_NAMESPACE_SUFFIX, CompilerEngine.NATIVE_PREVIEW: NATIVE_PREVIEW_CACHE_NAMESPACE_SUFFIX, } -NATIVE_STAGE_TIERS: dict[NativeStage, NativeStageTier] = { - NativeStage.DISCOVERY: NativeStageTier.SHIPPED, - NativeStage.DECLARATION_SCOPES: NativeStageTier.SHIPPED, - NativeStage.MODEL_CONFIG: NativeStageTier.SHIPPED, - NativeStage.REFERENCE_EXTRACTION: NativeStageTier.SHIPPED, - NativeStage.DECLARATION_FILES: NativeStageTier.SHIPPED, - NativeStage.MODEL_LOOP: NativeStageTier.SHIPPED, - NativeStage.MACRO_CALLS: NativeStageTier.SHIPPED, - NativeStage.MACRO_CALL_STORE: NativeStageTier.SHIPPED, - NativeStage.ATTACHMENTS: NativeStageTier.SHIPPED, - NativeStage.TYPE_SYSTEM: NativeStageTier.SHIPPED, - NativeStage.MODEL_ANALYSIS: NativeStageTier.SHIPPED, - NativeStage.SEMANTIC_CHECKS: NativeStageTier.SHIPPED, - NativeStage.CONTRACTS: NativeStageTier.SHIPPED, - NativeStage.LINEAGE_FACTS: NativeStageTier.SHIPPED, - NativeStage.SQL_TEST_GLUE: NativeStageTier.SHIPPED, - NativeStage.PROJECT_ASSEMBLY: NativeStageTier.SHIPPED, -} +RETIRED_CACHE_NAMESPACE_SUFFIXES: tuple[str, ...] = ("", *ENGINE_CACHE_NAMESPACE_SUFFIXES.values()) +NATIVE_STAGE_TIERS: dict[NativeStage, NativeStageTier] = {} ENGINE_NATIVE_STAGE_TIERS: dict[CompilerEngine, frozenset[NativeStageTier]] = { - CompilerEngine.PYTHON: frozenset(), CompilerEngine.NATIVE: frozenset({NativeStageTier.SHIPPED}), CompilerEngine.NATIVE_PREVIEW: frozenset({NativeStageTier.SHIPPED, NativeStageTier.PREVIEW}), } diff --git a/src/sqlbuild/compiler/frontier/main/_compile_frontier.py b/src/sqlbuild/compiler/frontier/main/_compile_frontier.py index 9dee821b4e..c815c36c8d 100644 --- a/src/sqlbuild/compiler/frontier/main/_compile_frontier.py +++ b/src/sqlbuild/compiler/frontier/main/_compile_frontier.py @@ -1,11 +1,10 @@ -"""The single seam between the Python compiler stages and the native frontier.""" +"""The single seam between the compiler stages and the native frontier.""" from collections.abc import Callable -from sqlbuild.compiler.frontier._helpers.engine import active_compiler_engine from sqlbuild.compiler.frontier._helpers.native_frontier import native_frontier from sqlbuild.compiler.frontier._helpers.stage_capture import write_stage_capture -from sqlbuild.compiler.frontier.types import CompilerEngine, CompilerStage +from sqlbuild.compiler.frontier.types import CompilerStage def compile_frontier[T]( @@ -14,12 +13,8 @@ def compile_frontier[T]( python_stage: Callable[[], T], native_stage: Callable[[], T] | None = None, ) -> T: - """Produce the frontier object for `until` on the active engine, capturing it on request.""" + """Produce the frontier object for `until`, capturing it on request.""" - result: T = ( - python_stage() - if active_compiler_engine() is CompilerEngine.PYTHON - else native_frontier(until=until, python_stage=python_stage, native_stage=native_stage) - ) + result: T = native_frontier(until=until, python_stage=python_stage, native_stage=native_stage) write_stage_capture(stage=until, value=result) return result diff --git a/src/sqlbuild/compiler/frontier/main/native_stage_enabled.py b/src/sqlbuild/compiler/frontier/main/_native_stage_enabled.py similarity index 100% rename from src/sqlbuild/compiler/frontier/main/native_stage_enabled.py rename to src/sqlbuild/compiler/frontier/main/_native_stage_enabled.py diff --git a/src/sqlbuild/compiler/frontier/main/report_native_answer.py b/src/sqlbuild/compiler/frontier/main/_report_native_answer.py similarity index 100% rename from src/sqlbuild/compiler/frontier/main/report_native_answer.py rename to src/sqlbuild/compiler/frontier/main/_report_native_answer.py diff --git a/src/sqlbuild/compiler/frontier/main/report_native_fallback.py b/src/sqlbuild/compiler/frontier/main/_report_native_fallback.py similarity index 100% rename from src/sqlbuild/compiler/frontier/main/report_native_fallback.py rename to src/sqlbuild/compiler/frontier/main/_report_native_fallback.py diff --git a/src/sqlbuild/compiler/frontier/main/parse_compiler_engine.py b/src/sqlbuild/compiler/frontier/main/parse_compiler_engine.py new file mode 100644 index 0000000000..584dbac292 --- /dev/null +++ b/src/sqlbuild/compiler/frontier/main/parse_compiler_engine.py @@ -0,0 +1,10 @@ +"""Public compiler engine value parsing entry point.""" + +from sqlbuild.compiler.frontier._helpers.engine import parse_compiler_engine as _parse +from sqlbuild.compiler.frontier.types import CompilerEngine + + +def parse_compiler_engine(*, raw_value: str, source: str) -> CompilerEngine: + """Return the engine `raw_value` names, raising CompilerEngineError naming `source`.""" + + return _parse(raw_value=raw_value, source=source) diff --git a/src/sqlbuild/compiler/frontier/types.py b/src/sqlbuild/compiler/frontier/types.py index bfe1a2857c..892b1502c6 100644 --- a/src/sqlbuild/compiler/frontier/types.py +++ b/src/sqlbuild/compiler/frontier/types.py @@ -6,30 +6,12 @@ class CompilerEngine(StrEnum): """Which compiler implementation produces the frontier objects.""" - PYTHON = "python" NATIVE = "native" NATIVE_PREVIEW = "native-preview" class NativeStage(StrEnum): - """A native implementation that replaces one Python compiler stage when its tier is active.""" - - DISCOVERY = "discovery" - DECLARATION_SCOPES = "declaration_scopes" - MODEL_CONFIG = "model_config" - REFERENCE_EXTRACTION = "reference_extraction" - DECLARATION_FILES = "declaration_files" - MODEL_LOOP = "model_loop" - MACRO_CALLS = "macro_calls" - MACRO_CALL_STORE = "macro_call_store" - ATTACHMENTS = "attachments" - TYPE_SYSTEM = "type_system" - MODEL_ANALYSIS = "model_analysis" - SEMANTIC_CHECKS = "semantic_checks" - CONTRACTS = "contracts" - LINEAGE_FACTS = "lineage_facts" - SQL_TEST_GLUE = "sql_test_glue" - PROJECT_ASSEMBLY = "project_assembly" + """A native implementation behind the preview engine until its tier is shipped.""" class NativeStageTier(StrEnum): @@ -48,15 +30,9 @@ class CompilerStage(StrEnum): class NativeFallbackSite(StrEnum): - """A place where a shipped native stage still hands its work to the Python implementation.""" + """A place where native hands work to Python: a fallback or a user's extension callback.""" SCOPE_REBIND_LOOKUP = "declaration_scopes.rebind_lookup" LINT_EXPANSION = "model_loop.lint_expansion" - MACRO_CALL_SCAN = "macro_calls.scan" - MACRO_CALL_RESOLUTION = "macro_calls.resolution" - MACRO_UNBRIDGED_EXPANSION = "macro_calls.unbridged_expansion" - MACRO_BRIDGE_UNAVAILABLE = "macro_calls.bridge_unavailable" MACRO_CALL_MOCKED = "macro_calls.mocked_evaluation" - PROJECT_ASSEMBLY = "project_assembly.assembly" - TYPE_NORMALIZATION = "type_system.normalization" - SQL_TEST_ASSEMBLY = "sql_test_glue.assembly" + SQL_TEST_MACRO_MOCK_QUERIES = "sql_test_glue.macro_mock_queries" diff --git a/src/sqlbuild/compiler/graph/_helpers/audit_gates.py b/src/sqlbuild/compiler/graph/_helpers/audit_gates.py index eb03e2d935..42df368146 100644 --- a/src/sqlbuild/compiler/graph/_helpers/audit_gates.py +++ b/src/sqlbuild/compiler/graph/_helpers/audit_gates.py @@ -6,8 +6,6 @@ from sqlbuild.compiler.compile.models import CompiledAudit, CompiledObjectKey, CompiledProject from sqlbuild.compiler.compile.types import AttachedAuditTargetKind, CompiledResourceType -from sqlbuild.compiler.graph._helpers.algorithms import transitive_closure_many_impl -from sqlbuild.compiler.graph._helpers.lineage import build_lineage_upstream_deps_impl from sqlbuild.compiler.graph.models import AttachedAuditGateEdge _READABLE_RESOURCE_TYPES: frozenset[CompiledResourceType] = frozenset( @@ -110,39 +108,3 @@ def _extra_reads( for read in audit.scope_deps if read != target and read.resource_type in _READABLE_RESOURCE_TYPES ) - - -def attached_audit_gate_cycles_impl( - *, project: CompiledProject -) -> tuple[AttachedAuditGateEdge, ...]: - """Return every attached-audit read that depends on the audit's own target.""" - - edges: tuple[AttachedAuditGateEdge, ...] = attached_audit_gate_edges_impl(project=project) - upstream: dict[CompiledObjectKey, list[CompiledObjectKey]] = { - key: list(deps) for key, deps in build_lineage_upstream_deps_impl(project).items() - } - cycles: dict[AttachedAuditGateEdge, None] = {} - edge: AttachedAuditGateEdge - for edge in edges: - upstream.setdefault(edge.gated, []).append(edge.read) - audit: CompiledAudit - for audit in sorted(project.audits, key=lambda item: item.name): - if audit.attached_target_kind is None or audit.attached_target_name is None: - continue - target: CompiledObjectKey = CompiledObjectKey( - resource_type=AttachedAuditTargetKind(audit.attached_target_kind).resource_type, - name=audit.attached_target_name, - ) - read: CompiledObjectKey - for read in _extra_reads(audit=audit, target=target): - if target in transitive_closure_many_impl( - starts=(read,), edges=upstream, include_starts=False - ): - cycles[ - AttachedAuditGateEdge( - audit_name=audit.name, target=target, gated=target, read=read - ) - ] = None - return tuple( - sorted(cycles, key=lambda item: (item.audit_name, item.target.name, item.read.name)) - ) diff --git a/src/sqlbuild/compiler/graph/_helpers/hook_reads.py b/src/sqlbuild/compiler/graph/_helpers/hook_reads.py index c072752a17..ec222b1b90 100644 --- a/src/sqlbuild/compiler/graph/_helpers/hook_reads.py +++ b/src/sqlbuild/compiler/graph/_helpers/hook_reads.py @@ -4,11 +4,8 @@ from pathlib import Path -from sqlbuild.compiler.compile.models import CompiledModel, CompiledObjectKey, CompiledProject +from sqlbuild.compiler.compile.models import CompiledModel, CompiledProject from sqlbuild.compiler.discovery.models import PythonHookEntry, SqlHookEntry -from sqlbuild.compiler.graph._helpers.algorithms import transitive_closure_many_impl -from sqlbuild.compiler.graph._helpers.audit_gates import attached_audit_gate_edges_impl -from sqlbuild.compiler.graph._helpers.lineage import build_lineage_upstream_deps_impl from sqlbuild.compiler.graph._helpers.sql_refs import sql_ref_key_impl from sqlbuild.compiler.graph.models import HookReadEdge from sqlbuild.compiler.graph.types import HookReadType @@ -77,26 +74,3 @@ def _sql_hook_read_edges(model: CompiledModel) -> tuple[HookReadEdge, ...]: for ref in entry.reads ) return tuple(edges) - - -def hook_read_cycles_impl(*, project: CompiledProject) -> tuple[HookReadEdge, ...]: - """Return every declared hook read that depends on the model running the hook.""" - - edges: tuple[HookReadEdge, ...] = hook_read_edges_impl(project=project) - if not edges: - return () - upstream: dict[CompiledObjectKey, list[CompiledObjectKey]] = { - key: list(deps) for key, deps in build_lineage_upstream_deps_impl(project).items() - } - for gate in attached_audit_gate_edges_impl(project=project): - upstream.setdefault(gate.gated, []).append(gate.read) - for edge in edges: - upstream.setdefault(edge.gated, []).append(edge.read) - return tuple( - edge - for edge in sorted( - edges, key=lambda item: (item.gated.name, item.hook_name, item.read.name) - ) - if edge.gated - in transitive_closure_many_impl(starts=(edge.read,), edges=upstream, include_starts=False) - ) diff --git a/src/sqlbuild/compiler/graph/main/_attached_audit_gate_cycles.py b/src/sqlbuild/compiler/graph/main/_attached_audit_gate_cycles.py deleted file mode 100644 index 2d117e43f3..0000000000 --- a/src/sqlbuild/compiler/graph/main/_attached_audit_gate_cycles.py +++ /dev/null @@ -1,13 +0,0 @@ -"""Attached-audit gate cycle detection entrypoint.""" - -from __future__ import annotations - -from sqlbuild.compiler.compile.models import CompiledProject -from sqlbuild.compiler.graph._helpers.audit_gates import attached_audit_gate_cycles_impl -from sqlbuild.compiler.graph.models import AttachedAuditGateEdge - - -def attached_audit_gate_cycles(*, project: CompiledProject) -> tuple[AttachedAuditGateEdge, ...]: - """Return every attached-audit read that depends on the audit's own target.""" - - return attached_audit_gate_cycles_impl(project=project) diff --git a/src/sqlbuild/compiler/graph/main/_hook_read_cycles.py b/src/sqlbuild/compiler/graph/main/_hook_read_cycles.py deleted file mode 100644 index 69c6e541a4..0000000000 --- a/src/sqlbuild/compiler/graph/main/_hook_read_cycles.py +++ /dev/null @@ -1,13 +0,0 @@ -"""Python hook read cycle detection entrypoint.""" - -from __future__ import annotations - -from sqlbuild.compiler.compile.models import CompiledProject -from sqlbuild.compiler.graph._helpers.hook_reads import hook_read_cycles_impl -from sqlbuild.compiler.graph.models import HookReadEdge - - -def hook_read_cycles(*, project: CompiledProject) -> tuple[HookReadEdge, ...]: - """Return every declared hook read that depends on the model running the hook.""" - - return hook_read_cycles_impl(project=project) diff --git a/src/sqlbuild/compiler/lineage/_helpers/fast_columns.py b/src/sqlbuild/compiler/lineage/_helpers/fast_columns.py deleted file mode 100644 index aa941ff376..0000000000 --- a/src/sqlbuild/compiler/lineage/_helpers/fast_columns.py +++ /dev/null @@ -1,542 +0,0 @@ -"""Fast Polyglot-backed column lineage analyzer.""" - -from __future__ import annotations - -import logging -from collections.abc import Sequence -from typing import Any, cast - -from sqlbuild.compiler.compile.models import ( - CompiledLineageColumnFact, - CompiledLineageSourceFact, - CompiledModel, - CompiledProject, -) -from sqlbuild.compiler.compile.types import CompiledResourceType -from sqlbuild.compiler.lineage._helpers.columns import ( - _build_schema_mapping, - _build_star_lineage, - _normalize_sqlbuild_refs, -) -from sqlbuild.compiler.lineage.constants import STAR_COLUMN_NAME -from sqlbuild.compiler.lineage.models import ( - ColumnLineage, - ColumnLineageSource, - ModelColumnLineage, - PhysicalResource, - ProjectColumnLineage, -) -from sqlbuild.compiler.lineage.types import ( - ColumnLineageConfidence, - ColumnTransformKind, - InferredNullability, -) -from sqlbuild.compiler.sql_analysis.constants import ( - POLYGLOT_AGGREGATE_KINDS, - POLYGLOT_CAST_KINDS, - POLYGLOT_KIND_ALIAS, - POLYGLOT_KIND_COLUMN, - POLYGLOT_KIND_SELECT, - POLYGLOT_KIND_TABLE, - POLYGLOT_KIND_UNION, - POLYGLOT_SET_OPERATION_KINDS, -) -from sqlbuild.compiler.sql_analysis.main.import_polyglot_sql import import_polyglot_sql -from sqlbuild.diagnostics.main.log_debug_event import log_debug_event - -_DEBUG_LOGGER: logging.Logger = logging.getLogger("sqlbuild.lineage") - - -def build_fast_project_column_lineage( - *, - project: CompiledProject, - dialect: str | None = None, - model_names: frozenset[str] | None = None, -) -> ProjectColumnLineage | None: - """Build a fast, partial project column lineage graph for compiled models.""" - - if not project.settings.sql_analysis: - return None - - schema: dict[str, dict[str, str]] = _build_schema_mapping(project) - model_results: dict[str, ModelColumnLineage] = {} - compact_models: dict[str, tuple[Sequence[CompiledLineageColumnFact], bool]] = {} - model_order: list[str] = [] - - for model in project.models: - if model_names is not None and model.name not in model_names: - continue - if model.fast_lineage_columns is not None: - columns: Sequence[CompiledLineageColumnFact] = model.fast_lineage_columns - if model.fast_lineage_has_star and not model.fast_lineage_star_resolved: - normalized_sql: str - physical_resources: tuple[PhysicalResource, ...] - normalized_sql, physical_resources = _normalize_sqlbuild_refs(model.query_sql) - del normalized_sql - star_columns: tuple[ColumnLineage, ...] = _build_star_lineage( - model=model, - schema=schema, - physical_resources=physical_resources, - existing_columns={column.output_column for column in columns}, - ) - columns = ( - *columns, - *(_compiled_lineage_fact(column) for column in star_columns), - ) - compact_models[model.name] = (columns, model.fast_lineage_has_star) - model_order.append(model.name) - continue - result: ModelColumnLineage | None = _build_polyglot_fast_model_column_lineage( - model=model, - schema=schema, - dialect=dialect, - ) - if result is None: - continue - model_results[model.name] = result - model_order.append(model.name) - - return ProjectColumnLineage.from_fast_facts( - models=model_results, - compact_models=compact_models, - model_order=tuple(model_order), - ) - - -def _compiled_lineage_fact(column: ColumnLineage) -> CompiledLineageColumnFact: - return CompiledLineageColumnFact( - output_column=column.output_column, - upstream_columns=tuple( - CompiledLineageSourceFact( - resource_type=source.resource_type, - resource_name=source.resource_name, - column_name=source.column_name, - ) - for source in column.upstream_columns - ), - transform_kind=column.transform_kind, - confidence=column.confidence, - ) - - -def _build_polyglot_fast_model_column_lineage( - *, - model: CompiledModel, - schema: dict[str, dict[str, str]], - dialect: str | None, -) -> ModelColumnLineage | None: - if model.fast_lineage_columns is not None: - lineages: list[ColumnLineage] = [] - for fact in model.fast_lineage_columns: - upstream_columns: list[ColumnLineageSource] = [] - for source in fact.upstream_columns: - upstream_columns.append( - ColumnLineageSource( - resource_type=source.resource_type, - resource_name=source.resource_name, - column_name=source.column_name, - ) - ) - lineages.append( - ColumnLineage( - output_column=fact.output_column, - transform_kind=fact.transform_kind, - expression_sql=None, - upstream_columns=tuple(upstream_columns), - nullability=InferredNullability.UNKNOWN, - confidence=fact.confidence, - ) - ) - if model.fast_lineage_has_star and not model.fast_lineage_star_resolved: - normalized_sql: str - physical_resources: tuple[PhysicalResource, ...] - normalized_sql, physical_resources = _normalize_sqlbuild_refs(model.query_sql) - del normalized_sql - lineages.extend( - _build_star_lineage( - model=model, - schema=schema, - physical_resources=physical_resources, - existing_columns={lineage.output_column for lineage in lineages}, - ) - ) - return ModelColumnLineage( - model_name=model.name, - columns=tuple(lineages), - has_star=model.fast_lineage_has_star, - ) - - polyglot_module: Any = import_polyglot_sql() - normalized_sql: str - physical_resources: tuple[PhysicalResource, ...] - normalized_sql, physical_resources = _normalize_sqlbuild_refs(model.query_sql) - try: - parsed: Any = polyglot_module.parse_one(normalized_sql, dialect=dialect or "generic") - except polyglot_module.PolyglotError as error: - log_debug_event( - logger=_DEBUG_LOGGER, - message="fast column lineage parse failed; falling back", - sqlbuild_model=model.name, - sqlbuild_error=str(error), - ) - return None - parsed_kind: str = str(getattr(parsed, "kind", "")) - if parsed_kind == POLYGLOT_KIND_UNION: - return _build_polyglot_union_model_column_lineage( - model=model, - parsed=parsed, - schema=schema, - physical_resources=physical_resources, - ) - if parsed_kind != POLYGLOT_KIND_SELECT: - return None - - alias_map: dict[str, PhysicalResource] = _polyglot_table_alias_map( - parsed=parsed, - physical_resources=physical_resources, - ) - unqualified_resource: PhysicalResource | None = _single_alias_resource(alias_map) - lineages: list[ColumnLineage] = [] - has_star: bool = False - projections: tuple[Any, ...] = tuple(getattr(parsed, "expressions", ())) - inferred_names: tuple[str, ...] = tuple(column.name for column in model.inferred_columns or ()) - for index, projection in enumerate(projections): - if bool(getattr(projection, "is_star", False)): - has_star = True - continue - inner: Any = ( - projection.this - if str(getattr(projection, "kind", "")) == POLYGLOT_KIND_ALIAS - else projection - ) - if bool(getattr(inner, "is_star", False)): - has_star = True - continue - output_column: str | None = _polyglot_projection_output_name( - projection=projection, - index=index, - inferred_names=inferred_names, - ) - if output_column is None: - continue - upstream_columns, confidence = _polyglot_projection_upstream_columns( - projection=projection, - alias_map=alias_map, - unqualified_resource=unqualified_resource, - ) - transform_kind: ColumnTransformKind = _polyglot_classify_transform( - expression=inner, - upstream_columns=upstream_columns, - ) - lineages.append( - ColumnLineage( - output_column=output_column, - transform_kind=transform_kind, - expression_sql=None, - upstream_columns=upstream_columns, - nullability=InferredNullability.UNKNOWN, - confidence=confidence - if upstream_columns or transform_kind == ColumnTransformKind.CONSTANT - else ColumnLineageConfidence.UNKNOWN, - ) - ) - - if has_star: - lineages.extend( - _build_star_lineage( - model=model, - schema=schema, - physical_resources=physical_resources, - existing_columns={lineage.output_column for lineage in lineages}, - ) - ) - return ModelColumnLineage(model_name=model.name, columns=tuple(lineages), has_star=has_star) - - -def _build_polyglot_union_model_column_lineage( - *, - model: CompiledModel, - parsed: Any, - schema: dict[str, dict[str, str]], - physical_resources: tuple[PhysicalResource, ...], -) -> ModelColumnLineage | None: - selects: tuple[Any, ...] = _polyglot_set_expression_selects(parsed) - if not selects: - return None - inferred_names: tuple[str, ...] = tuple(column.name for column in model.inferred_columns or ()) - max_projection_count: int = max( - (len(tuple(getattr(select, "expressions", ()) or ())) for select in selects), - default=0, - ) - lineages: list[ColumnLineage] = [] - has_star: bool = False - for index in range(max_projection_count): - output_column: str | None = inferred_names[index] if index < len(inferred_names) else None - upstream_columns: list[ColumnLineageSource] = [] - seen: set[tuple[CompiledResourceType, str, str]] = set() - confidence: ColumnLineageConfidence = ColumnLineageConfidence.HIGH - transform_kind: ColumnTransformKind = ColumnTransformKind.DIRECT - for select in selects: - projections: tuple[Any, ...] = tuple(getattr(select, "expressions", ()) or ()) - if index >= len(projections): - continue - projection: Any = projections[index] - if bool(getattr(projection, "is_star", False)): - has_star = True - continue - inner: Any = ( - projection.this - if str(getattr(projection, "kind", "")) == POLYGLOT_KIND_ALIAS - else projection - ) - if bool(getattr(inner, "is_star", False)): - has_star = True - continue - if output_column is None: - output_column = _polyglot_projection_output_name( - projection=projection, - index=index, - inferred_names=inferred_names, - ) - alias_map: dict[str, PhysicalResource] = _polyglot_table_alias_map( - parsed=select, - physical_resources=physical_resources, - ) - branch_upstream, branch_confidence = _polyglot_projection_upstream_columns( - projection=projection, - alias_map=alias_map, - unqualified_resource=_single_alias_resource(alias_map), - ) - if branch_confidence == ColumnLineageConfidence.UNKNOWN: - confidence = ColumnLineageConfidence.UNKNOWN - elif ( - branch_confidence == ColumnLineageConfidence.MEDIUM - and confidence == ColumnLineageConfidence.HIGH - ): - confidence = ColumnLineageConfidence.MEDIUM - branch_transform: ColumnTransformKind = _polyglot_classify_transform( - expression=inner, - upstream_columns=branch_upstream, - ) - if branch_transform != ColumnTransformKind.DIRECT: - transform_kind = branch_transform - for source in branch_upstream: - key: tuple[CompiledResourceType, str, str] = ( - CompiledResourceType(source.resource_type), - source.resource_name, - source.column_name, - ) - if key in seen: - continue - seen.add(key) - upstream_columns.append(source) - if output_column is None: - continue - if not upstream_columns and transform_kind != ColumnTransformKind.CONSTANT: - confidence = ColumnLineageConfidence.UNKNOWN - lineages.append( - ColumnLineage( - output_column=output_column, - transform_kind=transform_kind, - expression_sql=None, - upstream_columns=tuple(upstream_columns), - nullability=InferredNullability.UNKNOWN, - confidence=confidence, - ) - ) - if has_star: - lineages.extend( - _build_star_lineage( - model=model, - schema=schema, - physical_resources=physical_resources, - existing_columns={lineage.output_column for lineage in lineages}, - ) - ) - return ModelColumnLineage(model_name=model.name, columns=tuple(lineages), has_star=has_star) - - -def _polyglot_set_expression_selects(expression: Any) -> tuple[Any, ...]: - kind: str = str(getattr(expression, "kind", "")) - if kind == POLYGLOT_KIND_SELECT: - return (expression,) - if kind not in POLYGLOT_SET_OPERATION_KINDS: - return () - args: object = getattr(expression, "args", {}) - if not isinstance(args, dict): - return () - selects: list[Any] = [] - for child_name in ("left", "right"): - child: object = args.get(child_name) - if child is not None: - selects.extend(_polyglot_set_expression_selects(child)) - return tuple(selects) - - -def _polyglot_table_alias_map( - *, - parsed: Any, - physical_resources: tuple[PhysicalResource, ...], -) -> dict[str, PhysicalResource]: - physical_resource_by_name: dict[str, PhysicalResource] = { - resource.physical_name: resource for resource in physical_resources - } - physical_resource_by_name.update( - {resource.resource_name: resource for resource in physical_resources} - ) - alias_map: dict[str, PhysicalResource] = {} - tables: tuple[Any, ...] = tuple(parsed.find_all(POLYGLOT_KIND_TABLE)) - for table in tables: - table_name: str = str(getattr(table, "name", "") or "") - resource: PhysicalResource | None = physical_resource_by_name.get(table_name) - if resource is None: - continue - alias_map[table_name] = resource - alias_or_name: str = str(getattr(table, "alias_or_name", "") or "") - if alias_or_name: - alias_map[alias_or_name] = resource - return alias_map - - -def _polyglot_projection_output_name( - *, projection: Any, index: int, inferred_names: tuple[str, ...] -) -> str | None: - raw_name: str = str(getattr(projection, "output_name", "") or "") - if raw_name and raw_name != STAR_COLUMN_NAME: - return raw_name - raw_name = str(getattr(projection, "alias_or_name", "") or "") - if raw_name and raw_name != STAR_COLUMN_NAME: - return raw_name - if index < len(inferred_names): - return inferred_names[index] - return None - - -def _polyglot_projection_upstream_columns( - *, - projection: Any, - alias_map: dict[str, PhysicalResource], - unqualified_resource: PhysicalResource | None, -) -> tuple[tuple[ColumnLineageSource, ...], ColumnLineageConfidence]: - columns: list[ColumnLineageSource] = [] - seen: set[tuple[CompiledResourceType, str, str]] = set() - confidence: ColumnLineageConfidence = ColumnLineageConfidence.HIGH - column_refs: tuple[tuple[str, str], ...] = _polyglot_column_refs_in_expression(projection) - for column_name, table_name in column_refs: - if not column_name: - continue - resource: PhysicalResource | None = None - if table_name: - resource = alias_map.get(table_name) - elif unqualified_resource is not None: - resource = unqualified_resource - confidence = ColumnLineageConfidence.MEDIUM - else: - confidence = ColumnLineageConfidence.UNKNOWN - if resource is None: - continue - key: tuple[CompiledResourceType, str, str] = ( - resource.resource_type, - resource.resource_name, - column_name, - ) - if key in seen: - continue - seen.add(key) - columns.append( - ColumnLineageSource( - resource_type=resource.resource_type, - resource_name=resource.resource_name, - column_name=column_name, - ) - ) - return tuple(columns), confidence - - -def _single_alias_resource(alias_map: dict[str, PhysicalResource]) -> PhysicalResource | None: - resource: PhysicalResource | None = None - for candidate in alias_map.values(): - if resource is None: - resource = candidate - continue - if candidate.resource_name != resource.resource_name: - return None - return resource - - -def _polyglot_column_refs_in_expression(expression: Any) -> tuple[tuple[str, str], ...]: - if str(getattr(expression, "kind", "")) == POLYGLOT_KIND_COLUMN: - return ( - (str(getattr(expression, "name", "") or ""), _polyglot_column_table_name(expression)), - ) - payload: object = expression.to_dict() - refs: list[tuple[str, str]] = [] - - def visit(*, node: object, collected_refs: list[tuple[str, str]]) -> list[tuple[str, str]]: - if isinstance(node, dict): - node_dict: dict[str, object] = cast(dict[str, object], node) - column_payload: object = node_dict.get("column") - if isinstance(column_payload, dict): - column_dict: dict[str, object] = cast(dict[str, object], column_payload) - column_name: str = _polyglot_name_payload_value(column_dict.get("name")) - table_payload: object = column_dict.get("table") - table_name: str = "" - if isinstance(table_payload, dict): - table_dict: dict[str, object] = cast(dict[str, object], table_payload) - table_name = _polyglot_name_payload_value(table_dict.get("name")) - return [*collected_refs, (column_name, table_name)] - for value in node_dict.values(): - collected_refs = visit(node=value, collected_refs=collected_refs) - elif isinstance(node, list): - for value in node: - collected_refs = visit(node=value, collected_refs=collected_refs) - return collected_refs - - refs = visit(node=payload, collected_refs=refs) - return tuple(refs) - - -def _polyglot_name_payload_value(payload: object) -> str: - if isinstance(payload, str): - return payload - if isinstance(payload, dict): - payload_dict: dict[str, object] = cast(dict[str, object], payload) - name: object = payload_dict.get("name") - if isinstance(name, str): - return name - return "" - - -def _polyglot_column_table_name(column: Any) -> str: - payload: object = column.to_dict().get("column", {}) - if not isinstance(payload, dict): - return "" - table_payload: object = payload.get("table") - if not isinstance(table_payload, dict): - return "" - raw_name: object = table_payload.get("name") - return raw_name if isinstance(raw_name, str) else "" - - -def _polyglot_classify_transform( - *, - expression: Any, - upstream_columns: tuple[ColumnLineageSource, ...], -) -> ColumnTransformKind: - kind: str = str(getattr(expression, "kind", "")) - if bool(getattr(expression, "is_star", False)): - return ColumnTransformKind.STAR - if kind in POLYGLOT_CAST_KINDS: - return ColumnTransformKind.CAST - if _polyglot_has_aggregation(expression): - return ColumnTransformKind.AGGREGATION - if not upstream_columns: - return ColumnTransformKind.CONSTANT - if kind == POLYGLOT_KIND_COLUMN and len(upstream_columns) == 1: - return ColumnTransformKind.DIRECT - return ColumnTransformKind.EXPRESSION - - -def _polyglot_has_aggregation(expression: Any) -> bool: - nodes: tuple[Any, ...] = tuple(expression.walk()) - return any(str(getattr(node, "kind", "")) in POLYGLOT_AGGREGATE_KINDS for node in nodes) diff --git a/src/sqlbuild/compiler/lineage/_helpers/native_deferrals.py b/src/sqlbuild/compiler/lineage/_helpers/native_deferrals.py deleted file mode 100644 index 8d7e3cd387..0000000000 --- a/src/sqlbuild/compiler/lineage/_helpers/native_deferrals.py +++ /dev/null @@ -1,26 +0,0 @@ -"""Debug-only record of fast lineage models the native engine hands back to Python.""" - -from __future__ import annotations - -import json -import os -from pathlib import Path - -from sqlbuild.compiler.lineage.constants import ( - ANALYSIS_DEFERRAL_RECORD_PREFIX, - NATIVE_LINEAGE_DEFERRAL_SITE, -) -from sqlbuild.compiler.sql_analysis.constants import ANALYSIS_RECORD_DIR_ENV_VAR - - -def record_lineage_deferral(*, kind: str) -> None: - """Append one `{"kind", "site"}` line when the analysis record directory is set.""" - - directory: str | None = os.environ.get(ANALYSIS_RECORD_DIR_ENV_VAR) - if not directory: - return - target: Path = Path(directory) - target.mkdir(parents=True, exist_ok=True) - record: str = json.dumps({"kind": kind, "site": NATIVE_LINEAGE_DEFERRAL_SITE}) - with open(target / f"{ANALYSIS_DEFERRAL_RECORD_PREFIX}{os.getpid()}.jsonl", "a") as handle: - _ = handle.write(record + "\n") diff --git a/src/sqlbuild/compiler/lineage/_helpers/native_fast_columns.py b/src/sqlbuild/compiler/lineage/_helpers/native_fast_columns.py index 61895dfc95..7f66a866c6 100644 --- a/src/sqlbuild/compiler/lineage/_helpers/native_fast_columns.py +++ b/src/sqlbuild/compiler/lineage/_helpers/native_fast_columns.py @@ -14,18 +14,12 @@ CompiledProject, ) from sqlbuild.compiler.compile.types import CompiledResourceType -from sqlbuild.compiler.lineage._helpers.columns import _build_schema_mapping -from sqlbuild.compiler.lineage._helpers.fast_columns import ( - _build_polyglot_fast_model_column_lineage, -) -from sqlbuild.compiler.lineage._helpers.native_deferrals import record_lineage_deferral from sqlbuild.compiler.lineage.constants import ( NATIVE_LINEAGE_BUILT, - NATIVE_LINEAGE_DEFERRED, - NATIVE_LINEAGE_NO_CATALOG, - NATIVE_LINEAGE_STAR, + NATIVE_LINEAGE_UNKNOWN_DIALECT, NATIVE_LINEAGE_UNPARSED, ) +from sqlbuild.compiler.lineage.exceptions import UnknownLineageDialectError from sqlbuild.compiler.lineage.models import ( ColumnLineage, ColumnLineageSource, @@ -51,7 +45,7 @@ def build_native_fast_project_column_lineage( dialect: str | None, model_names: frozenset[str] | None, ) -> ProjectColumnLineage | None: - """Build `build_fast_project_column_lineage`'s graph with native star expansion and parsing.""" + """Build the fast lineage graph with native star expansion and parsing.""" if not project.settings.sql_analysis: return None @@ -66,17 +60,12 @@ def build_native_fast_project_column_lineage( catalog: object | None = ( project.binding_catalog.native if project.binding_catalog is not None else None ) - if catalog is None and requests: - for _ in requests: - record_lineage_deferral(kind=NATIVE_LINEAGE_NO_CATALOG) - return None outcomes: list[_NativeOutcome] = ( _native.build_fast_column_lineage(catalog, (dialect, _schema_resources(project), requests)) if requests else [] ) outcome_index: int = 0 - python_schema: dict[str, dict[str, str]] | None = None model_results: dict[str, ModelColumnLineage] = {} compact_models: dict[str, tuple[Sequence[CompiledLineageColumnFact], bool]] = {} model_order: list[str] = [] @@ -84,10 +73,8 @@ def build_native_fast_project_column_lineage( if model.fast_lineage_columns is not None: columns: Sequence[CompiledLineageColumnFact] = model.fast_lineage_columns if _needs_star_expansion(model): - status, star_columns, _, _ = outcomes[outcome_index] + _, star_columns, _, _ = outcomes[outcome_index] outcome_index += 1 - if status != NATIVE_LINEAGE_STAR: - return None columns = (*columns, *(_column_fact(column) for column in star_columns)) compact_models[model.name] = (columns, model.fast_lineage_has_star) model_order.append(model.name) @@ -108,13 +95,8 @@ def build_native_fast_project_column_lineage( sqlbuild_model=model.name, sqlbuild_error=detail, ) - elif status == NATIVE_LINEAGE_DEFERRED: - record_lineage_deferral(kind=str(detail)) - if python_schema is None: - python_schema = _build_schema_mapping(project) - result = _build_polyglot_fast_model_column_lineage( - model=model, schema=python_schema, dialect=dialect - ) + elif status == NATIVE_LINEAGE_UNKNOWN_DIALECT: + raise UnknownLineageDialectError(f"Unknown dialect: {detail}") if result is None: continue model_results[model.name] = result diff --git a/src/sqlbuild/compiler/lineage/constants.py b/src/sqlbuild/compiler/lineage/constants.py index f6f49d295b..088054641c 100644 --- a/src/sqlbuild/compiler/lineage/constants.py +++ b/src/sqlbuild/compiler/lineage/constants.py @@ -3,10 +3,7 @@ STAR_COLUMN_NAME: str = "*" POLYGLOT_RESOLVED_SOURCE_CONFIDENCE: str = "resolved" INDEXED_EDGE_RECORD_LENGTH: int = 6 -NATIVE_LINEAGE_STAR: str = "star" NATIVE_LINEAGE_BUILT: str = "built" NATIVE_LINEAGE_UNPARSED: str = "unparsed" -NATIVE_LINEAGE_DEFERRED: str = "deferred" -NATIVE_LINEAGE_NO_CATALOG: str = "no_analysis_catalog" -NATIVE_LINEAGE_DEFERRAL_SITE: str = "fast_columns.py" +NATIVE_LINEAGE_UNKNOWN_DIALECT: str = "unknown_dialect" ANALYSIS_DEFERRAL_RECORD_PREFIX: str = "analysis-deferrals-" diff --git a/src/sqlbuild/compiler/lineage/exceptions.py b/src/sqlbuild/compiler/lineage/exceptions.py index 100f2aaab3..20dee9b906 100644 --- a/src/sqlbuild/compiler/lineage/exceptions.py +++ b/src/sqlbuild/compiler/lineage/exceptions.py @@ -3,3 +3,7 @@ class LineageAnalysisError(RuntimeError): """Raised when the native lineage boundary returns an invalid payload.""" + + +class UnknownLineageDialectError(ValueError): + """Raised, as Python's parser raised `ValueError`, for a dialect Polyglot does not know.""" diff --git a/src/sqlbuild/compiler/lineage/main/_build_native_column_lineage.py b/src/sqlbuild/compiler/lineage/main/_build_native_column_lineage.py index d5acf51a0d..b41d6b2555 100644 --- a/src/sqlbuild/compiler/lineage/main/_build_native_column_lineage.py +++ b/src/sqlbuild/compiler/lineage/main/_build_native_column_lineage.py @@ -12,7 +12,7 @@ def build_native_column_lineage( *, project: CompiledProject, dialect: str | None, model_names: frozenset[str] | None ) -> ProjectColumnLineage | None: - """Return the fast lineage graph, or None where Python must build it.""" + """Return the fast lineage graph, or None without SQL analysis.""" return build_native_fast_project_column_lineage( project=project, dialect=dialect, model_names=model_names diff --git a/src/sqlbuild/compiler/lineage/main/columns.py b/src/sqlbuild/compiler/lineage/main/columns.py index 735a03c3d2..5a421f3e3f 100644 --- a/src/sqlbuild/compiler/lineage/main/columns.py +++ b/src/sqlbuild/compiler/lineage/main/columns.py @@ -3,12 +3,6 @@ from __future__ import annotations from sqlbuild.compiler.compile.models import CompiledProject -from sqlbuild.compiler.frontier.main.native_stage_enabled import native_stage_enabled -from sqlbuild.compiler.frontier.main.report_native_answer import report_native_answer -from sqlbuild.compiler.frontier.types import NativeStage -from sqlbuild.compiler.lineage._helpers.fast_columns import ( - build_fast_project_column_lineage, -) from sqlbuild.compiler.lineage._helpers.rich_columns import ( build_rich_project_column_lineage, ) @@ -30,17 +24,8 @@ def build_project_column_lineage( match mode: case ColumnLineageMode.FAST: - if native_stage_enabled(NativeStage.LINEAGE_FACTS): - native_lineage: ProjectColumnLineage | None = build_native_column_lineage( - project=project, dialect=dialect, model_names=model_names - ) - if native_lineage is not None: - report_native_answer(stage=NativeStage.LINEAGE_FACTS, kind="lineage_graphs") - return native_lineage - return build_fast_project_column_lineage( - project=project, - dialect=dialect, - model_names=model_names, + return build_native_column_lineage( + project=project, dialect=dialect, model_names=model_names ) case ColumnLineageMode.RICH: return build_rich_project_column_lineage( diff --git a/src/sqlbuild/compiler/macro_bridge/classes/macro_bridge.py b/src/sqlbuild/compiler/macro_bridge/classes/macro_bridge.py index 0cf496ca68..0351f995f6 100644 --- a/src/sqlbuild/compiler/macro_bridge/classes/macro_bridge.py +++ b/src/sqlbuild/compiler/macro_bridge/classes/macro_bridge.py @@ -14,8 +14,6 @@ LoadedMacro, MacroContext, ) -from sqlbuild.compiler.frontier.main.report_native_fallback import report_native_fallback -from sqlbuild.compiler.frontier.types import NativeFallbackSite from sqlbuild.compiler.macro_bridge._helpers.store_environment import ( digest_module_files, module_digests_metadata, @@ -30,7 +28,14 @@ macro_store_token, ) from sqlbuild.compiler.macro_bridge.constants import MACRO_CALL_STORE_FILE_NAME -from sqlbuild.compiler.macro_bridge.models import MacroCallClass, MacroCallSite, ModuleSources +from sqlbuild.compiler.macro_bridge.main._scan_macro_calls import scan_macro_calls +from sqlbuild.compiler.macro_bridge.main._splice_macro_calls import splice_macro_calls +from sqlbuild.compiler.macro_bridge.models import ( + MacroCallClass, + MacroCallScan, + MacroCallSite, + ModuleSources, +) from sqlbuild.compiler.macro_bridge.types import MacroCallEvent, MacroCallRecord from sqlbuild.compiler.scopes.models import DeclarationIdentity from sqlbuild.python_nodes.models import SqlResourceRef @@ -132,24 +137,11 @@ def _observe_modules(self) -> bool: self._module_digests.update(digests) return True - def scan(self, sql: str) -> tuple[MacroCallSite, ...] | None: - """Return the top-level call sites of `sql`, or None when Python must expand it.""" + def scan(self, sql: str) -> MacroCallScan: + """The complete top-level call sites of `sql`, and where its scan raises, if it does.""" - rows: list[tuple[int, int, str, list[str], bool]] | None = _native.scan_macro_call_sites( - sql, self._python_version, self._unicode_version - ) - if rows is None: - report_native_fallback(site=NativeFallbackSite.MACRO_CALL_SCAN) - return None - return tuple( - MacroCallSite( - start=start, - end=end, - name=name, - tree_names=tuple(tree_names), - typed_reference_text=typed_reference_text, - ) - for start, end, name, tree_names, typed_reference_text in rows + return scan_macro_calls( + sql=sql, python_version=self._python_version, unicode_version=self._unicode_version ) def call_class( @@ -162,6 +154,8 @@ def call_class( ) -> MacroCallClass | None: """Return what a call's result may depend on besides its text, or None if unresolvable.""" + if site.tree_names is None: + return None owner: object = loaded_macros if declarations is None else declarations macros: Mapping[str, LoadedMacro] = ( loaded_macros if declarations is None else declarations.macros @@ -261,19 +255,7 @@ def splice( ) -> tuple[str, tuple[ExpansionSpan, ...]]: """Replace each call site with its output, returning the SQL and substitution spans.""" - rendered: str - spans: list[tuple[int, int, int, int]] - bounds: list[tuple[int, int]] = [(site.start, site.end) for site in sites] - rendered, spans = _native.splice_macro_calls(sql, bounds, outputs) - return rendered, tuple( - ExpansionSpan( - source_start=source_start, - source_end=source_end, - output_start=output_start, - output_end=output_end, - ) - for source_start, source_end, output_start, output_end in spans - ) + return splice_macro_calls(sql=sql, sites=sites, outputs=outputs) def stats(self) -> tuple[int, int, int]: """Memo hits, misses and recorded results so far.""" diff --git a/src/sqlbuild/compiler/macro_bridge/main/_scan_macro_calls.py b/src/sqlbuild/compiler/macro_bridge/main/_scan_macro_calls.py new file mode 100644 index 0000000000..477f3a12e7 --- /dev/null +++ b/src/sqlbuild/compiler/macro_bridge/main/_scan_macro_calls.py @@ -0,0 +1,42 @@ +"""Scan one authored string's top-level macro call sites natively.""" + +from __future__ import annotations + +import sys +import unicodedata + +import sqlbuild._native as _native +from sqlbuild.compiler.macro_bridge.models import MacroCallScan, MacroCallSite, MacroScanFailure + + +def scan_macro_calls( + *, + sql: str, + python_version: tuple[int, int] | None = None, + unicode_version: str | None = None, +) -> MacroCallScan: + """The complete top-level call sites of `sql`, and where its scan raises, if it does.""" + + rows: list[tuple[int, int, int, str, list[str] | None, bool]] + failure: tuple[int | None, str | None, str] | None + rows, failure = _native.scan_macro_call_sites( + sql, + python_version or (sys.version_info[0], sys.version_info[1]), + unicode_version or unicodedata.unidata_version, + ) + return MacroCallScan( + sites=tuple( + MacroCallSite( + start=start, + args_start=args_start, + end=end, + name=name, + tree_names=None if tree_names is None else tuple(tree_names), + typed_reference_text=typed_reference_text, + ) + for start, args_start, end, name, tree_names, typed_reference_text in rows + ), + failure=None + if failure is None + else MacroScanFailure(call_start=failure[0], call_name=failure[1], message=failure[2]), + ) diff --git a/src/sqlbuild/compiler/macro_bridge/main/_splice_macro_calls.py b/src/sqlbuild/compiler/macro_bridge/main/_splice_macro_calls.py new file mode 100644 index 0000000000..480f4ef956 --- /dev/null +++ b/src/sqlbuild/compiler/macro_bridge/main/_splice_macro_calls.py @@ -0,0 +1,28 @@ +"""Splice macro call outputs into one authored string natively.""" + +from __future__ import annotations + +import sqlbuild._native as _native +from sqlbuild.compiler.compile.models import ExpansionSpan +from sqlbuild.compiler.macro_bridge.models import MacroCallSite + + +def splice_macro_calls( + *, sql: str, sites: tuple[MacroCallSite, ...], outputs: list[str] +) -> tuple[str, tuple[ExpansionSpan, ...]]: + """Replace each call site with its output, returning the SQL and substitution spans.""" + + rendered: str + spans: list[tuple[int, int, int, int]] + rendered, spans = _native.splice_macro_calls( + sql, [(site.start, site.end) for site in sites], outputs + ) + return rendered, tuple( + ExpansionSpan( + source_start=source_start, + source_end=source_end, + output_start=output_start, + output_end=output_end, + ) + for source_start, source_end, output_start, output_end in spans + ) diff --git a/src/sqlbuild/compiler/macro_bridge/main/run_with_macro_bridge.py b/src/sqlbuild/compiler/macro_bridge/main/run_with_macro_bridge.py index 1d53c9869c..3eb1b28d59 100644 --- a/src/sqlbuild/compiler/macro_bridge/main/run_with_macro_bridge.py +++ b/src/sqlbuild/compiler/macro_bridge/main/run_with_macro_bridge.py @@ -3,15 +3,11 @@ from __future__ import annotations import logging -import sys import unicodedata from collections.abc import Callable from contextvars import Token -import sqlbuild._native as _native -from sqlbuild.compiler.frontier.main.report_native_answer import report_native_answer -from sqlbuild.compiler.frontier.main.report_native_fallback import report_native_fallback -from sqlbuild.compiler.frontier.types import NativeFallbackSite, NativeStage +from sqlbuild.compiler.discovery.main._require_supported_python import require_supported_python from sqlbuild.compiler.macro_bridge.classes.macro_bridge import MacroBridge from sqlbuild.compiler.macro_bridge.constants import ACTIVE_MACRO_BRIDGE, STORE_MODULE_PATHS @@ -19,10 +15,7 @@ def run_with_macro_bridge[T](*, stage: Callable[[], T]) -> T: """Run `stage` once with the bridge; its errors are the Python stage's, raised as they occur.""" - python_version: tuple[int, int] = (sys.version_info[0], sys.version_info[1]) - if not _native.native_text_supported(python_version, unicodedata.unidata_version): - report_native_fallback(site=NativeFallbackSite.MACRO_BRIDGE_UNAVAILABLE) - return stage() + python_version: tuple[int, int] = require_supported_python() bridge: MacroBridge = MacroBridge( python_version=python_version, unicode_version=unicodedata.unidata_version ) @@ -35,7 +28,6 @@ def run_with_macro_bridge[T](*, stage: Callable[[], T]) -> T: STORE_MODULE_PATHS.update(bridge.store_module_paths()) hits, misses, recorded = bridge.stats() store_hits, store_records = bridge.store_stats() - report_native_answer(stage=NativeStage.MACRO_CALL_STORE, kind="served_calls", units=store_hits) logging.getLogger(__name__).debug( "Native macro bridge: %d memo hits, %d store hits, %d misses, %d recorded calls, " "%d stored calls", diff --git a/src/sqlbuild/compiler/macro_bridge/models.py b/src/sqlbuild/compiler/macro_bridge/models.py index 91ece77cc5..657fdf907d 100644 --- a/src/sqlbuild/compiler/macro_bridge/models.py +++ b/src/sqlbuild/compiler/macro_bridge/models.py @@ -11,12 +11,31 @@ class MacroCallSite: """One top-level macro call in an authored string, in Python string offsets.""" start: int + args_start: int end: int name: str - tree_names: tuple[str, ...] + tree_names: tuple[str, ...] | None + """Every macro name of the call; None where a nested call is not one the scan completes.""" typed_reference_text: bool +@dataclass(frozen=True) +class MacroScanFailure: + """Where Python's scan of a string raises: in the call at `call_start`, or between calls.""" + + call_start: int | None + call_name: str | None + message: str + + +@dataclass(frozen=True) +class MacroCallScan: + """A string's complete top-level call sites in order, and where its scan raises, if it does.""" + + sites: tuple[MacroCallSite, ...] + failure: MacroScanFailure | None + + @dataclass(frozen=True) class MacroCallClass: """A call's inputs besides its text: by object identity for the memo, by value for the store.""" diff --git a/src/sqlbuild/compiler/model_loop/main/_scan_native_declaration_references.py b/src/sqlbuild/compiler/model_loop/main/_scan_native_declaration_references.py index 744faabeb5..269354d7ca 100644 --- a/src/sqlbuild/compiler/model_loop/main/_scan_native_declaration_references.py +++ b/src/sqlbuild/compiler/model_loop/main/_scan_native_declaration_references.py @@ -4,19 +4,28 @@ import sys import unicodedata +from collections.abc import Callable import sqlbuild._native as _native from sqlbuild.compiler.model_loop.types import NativeDeclarationScan def scan_native_declaration_references( - *, sqls: tuple[str, ...] + *, sqls: tuple[str, ...], skip_malformed: bool = False ) -> tuple[NativeDeclarationScan, ...]: - """Return each string's references and the code of the error ending its walk.""" + """Return each string's references and stop code; `skip_malformed` walks past malformed ones.""" + scan_references: Callable[ + [list[str], tuple[int, int], str], + list[tuple[list[tuple[int, str, str | None, int, int]], int | None]], + ] = ( + _native.scan_sql_declaration_usages + if skip_malformed + else _native.scan_sql_declaration_references + ) return tuple( (tuple(scan[0]), scan[1]) - for scan in _native.scan_sql_declaration_references( + for scan in scan_references( list(sqls), (sys.version_info[0], sys.version_info[1]), unicodedata.unidata_version ) ) diff --git a/src/sqlbuild/compiler/planner/_helpers/sql_tests/native_planning.py b/src/sqlbuild/compiler/planner/_helpers/sql_tests/native_planning.py index 54c533f253..44df9df303 100644 --- a/src/sqlbuild/compiler/planner/_helpers/sql_tests/native_planning.py +++ b/src/sqlbuild/compiler/planner/_helpers/sql_tests/native_planning.py @@ -3,7 +3,6 @@ from __future__ import annotations import time -from typing import Any, cast import orjson @@ -18,11 +17,7 @@ CompiledModelSqlTestPayload, CompiledProject, CompiledSqlTest, - CompileSqlTestCte, ) -from sqlbuild.compiler.compile.types import CompiledResourceType -from sqlbuild.compiler.frontier.main.native_stage_enabled import native_stage_enabled -from sqlbuild.compiler.frontier.types import NativeStage from sqlbuild.compiler.planner._helpers.sql_tests.cursor_window import ( declared_window_cursor_models, declares_cursor_window, @@ -39,7 +34,6 @@ from sqlbuild.compiler.planner.types import WarningSeverity from sqlbuild.compiler.profiling.classes.context import CompileTimingContext from sqlbuild.compiler.profiling.models import CompileTimingCollector -from sqlbuild.compiler.sql_analysis.models import SqlLexicalSyntax from sqlbuild.compiler.sql_test_glue.constants import CURSOR_INTRINSIC_NAMES from sqlbuild.compiler.sql_test_glue.models import ( NativeSqlTestChainRequest, @@ -50,7 +44,6 @@ NativeChainStepRow, NativeSqlTestPlanRow, ) -from sqlbuild.executor.testing.types import NativeSqlTestRenderingModule _UNRESOLVED_REFERENCE_PREFIX: str = "sql_test_reference:" @@ -58,36 +51,6 @@ _NATIVE_WORKERS: int = 4 -def plan_and_render_sql_test_artifacts( - *, - project: CompiledProject, - tests: tuple[CompiledSqlTest, ...], - adapter: BaseAdapter, - sql_analysis_enabled: bool, -) -> tuple[NativeSqlTestArtifact, ...]: - """Plan and render SQL tests in one deterministic native project call.""" - - artifacts: list[NativeSqlTestArtifact] = [] - for plan in _plan_sql_tests_from_json( - project=project, - tests=tests, - adapter=adapter, - sql_analysis_enabled=sql_analysis_enabled, - render_sql=True, - include_plan=False, - ): - if plan.sql is None: - raise NativeSqlTestPlanningError("native SQL-test planning omitted rendered SQL") - artifacts.append( - NativeSqlTestArtifact( - sql=plan.sql, - model_names=plan.model_names, - error_messages=plan.error_messages, - ) - ) - return tuple(artifacts) - - def plan_compiled_sql_test_artifacts( *, project: CompiledProject, @@ -137,16 +100,7 @@ def plan_sql_tests_natively( ) -> tuple[NativeSqlTestPlan, ...]: """Plan SQL-test chains and assertions in one native batch, optionally rendering SQL.""" - if native_stage_enabled(NativeStage.SQL_TEST_GLUE): - return _plan_compiled_sql_tests( - project=project, - tests=tests, - adapter=adapter, - sql_analysis_enabled=sql_analysis_enabled, - render_sql=render_sql, - include_plan=include_plan, - ) - return _plan_sql_tests_from_json( + return _plan_compiled_sql_tests( project=project, tests=tests, adapter=adapter, @@ -307,65 +261,6 @@ def _record_planning_timing(*, start_ns: int, planning_ns: int, rendering_ns: in collector.add(phase="comparison_render_ms", elapsed_ns=rendering_ns) -def _plan_sql_tests_from_json( - *, - project: CompiledProject, - tests: tuple[CompiledSqlTest, ...], - adapter: BaseAdapter, - sql_analysis_enabled: bool, - render_sql: bool, - include_plan: bool, -) -> tuple[NativeSqlTestPlan, ...]: - if not tests: - return () - start_ns: int = time.perf_counter_ns() - request: dict[str, object] = { - "models": _model_requests(project=project, adapter=adapter), - "functions": _function_requests(project=project, adapter=adapter), - "tests": _planning_test_requests(project=project, tests=tests, adapter=adapter), - "sqlAnalysisEnabled": sql_analysis_enabled, - "sqlAnalysisDialect": adapter.sql_analysis_dialect(), - "setDifferenceOperator": adapter.render_set_difference_operator(), - "requiresDerivedTableAliases": adapter.requires_derived_table_aliases(), - "lexicalSyntax": _lexical_syntax_request(project.sql_lexical_syntax), - "workers": _NATIVE_WORKERS, - "renderSql": render_sql, - "includePlan": include_plan, - } - try: - native_response: str = cast( - NativeSqlTestRenderingModule, _native - ).plan_and_render_sql_tests_json( - orjson.dumps(request, option=orjson.OPT_SORT_KEYS).decode() - ) - except ValueError as error: - raise _planning_error(error=error, tests=tests) from None - response_payload: object = orjson.loads(native_response) - if not isinstance(response_payload, dict): - raise NativeSqlTestPlanningError( - "native SQL-test planning returned an invalid batch response" - ) - response: object = response_payload.get("artifacts") - planning_ns: object = response_payload.get("planningNs") - rendering_ns: object = response_payload.get("renderingNs") - if ( - not isinstance(response, list) - or len(response) != len(tests) - or not isinstance(planning_ns, int) - or isinstance(planning_ns, bool) - or not isinstance(rendering_ns, int) - or isinstance(rendering_ns, bool) - ): - raise NativeSqlTestPlanningError( - "native SQL-test planning returned an invalid batch response" - ) - plans: tuple[NativeSqlTestPlan, ...] = tuple( - _plan_from_payload(value=value) for value in response - ) - _record_planning_timing(start_ns=start_ns, planning_ns=planning_ns, rendering_ns=rendering_ns) - return plans - - def resolve_sql_test_model_chains( *, project: CompiledProject, tests: tuple[CompiledSqlTest, ...] ) -> tuple[tuple[str, ...], ...]: @@ -373,36 +268,17 @@ def resolve_sql_test_model_chains( if not tests: return () - if native_stage_enabled(NativeStage.SQL_TEST_GLUE): - try: - native_chains: list[list[str]] = _native.resolve_compiled_sql_test_chains( - NativeSqlTestChainRequest( - models=project.models, - tests=tests, - lexical_syntax=project.sql_lexical_syntax.native_mapping, - ) - ) - except ValueError as error: - raise _planning_error(error=error, tests=tests) from None - return tuple(tuple(chain) for chain in native_chains) - request: dict[str, object] = { - "models": _chain_model_requests(project=project), - "tests": [_test_request(test=test) for test in tests], - "lexicalSyntax": _lexical_syntax_request(project.sql_lexical_syntax), - } try: - native_response: str = cast( - NativeSqlTestRenderingModule, _native - ).resolve_sql_test_chains_json(orjson.dumps(request, option=orjson.OPT_SORT_KEYS).decode()) + native_chains: list[list[str]] = _native.resolve_compiled_sql_test_chains( + NativeSqlTestChainRequest( + models=project.models, + tests=tests, + lexical_syntax=project.sql_lexical_syntax.native_mapping, + ) + ) except ValueError as error: raise _planning_error(error=error, tests=tests) from None - response_payload: object = orjson.loads(native_response) - chains: object = response_payload.get("chains") if isinstance(response_payload, dict) else None - if not isinstance(chains, list) or len(chains) != len(tests): - raise NativeSqlTestPlanningError( - "native SQL-test chain resolution returned an invalid response" - ) - return tuple(_string_tuple(value=chain, context="chain") for chain in chains) + return tuple(tuple(chain) for chain in native_chains) def _planning_error(*, error: ValueError, tests: tuple[CompiledSqlTest, ...]) -> Exception: @@ -450,129 +326,6 @@ def _unresolved_reference_error( ) -def _plan_from_payload(*, value: object) -> NativeSqlTestPlan: - payload: dict[str, Any] = _object(value=value, context="result") - sql: object = payload.get("sql") - chain: object = payload.get("chain") - assertions: object = payload.get("assertions") - warnings: object = payload.get("warnings") - if ( - (sql is not None and not isinstance(sql, str)) - or not isinstance(chain, list) - or not isinstance(assertions, list) - or not isinstance(warnings, list) - ): - raise NativeSqlTestPlanningError("native SQL-test planning returned an invalid result") - plan_warnings: tuple[PlanWarning, ...] = tuple(_warning(value=warning) for warning in warnings) - return NativeSqlTestPlan( - chain=tuple(_chain_step(value=step) for step in chain), - assertions=tuple(_assertion_step(value=step) for step in assertions), - model_names=_string_tuple(value=payload.get("modelNames"), context="model names"), - warnings=plan_warnings, - error_messages=sql_test_plan_error_messages(warnings=plan_warnings), - sql=sql if isinstance(sql, str) else None, - ) - - -def _chain_step(*, value: object) -> ChainStep: - payload: dict[str, Any] = _object(value=value, context="chain step") - return ChainStep( - model_name=_string(value=payload.get("modelName"), context="chain step model"), - resolved_sql=_string(value=payload.get("resolvedSql"), context="chain step SQL"), - expected_cte_sql=_optional_string( - value=payload.get("expectedCteSql"), context="chain step expected SQL" - ), - lifted_ctes=_cte_pairs(value=payload.get("liftedCtes")), - comparison_body_sql=_optional_string( - value=payload.get("comparisonBodySql"), context="chain step comparison SQL" - ), - expected_columns=_optional_string_tuple( - value=payload.get("expectedColumns"), context="chain step expected columns" - ), - expected_lifted_ctes=_cte_pairs(value=payload.get("expectedLiftedCtes", [])), - ) - - -def _assertion_step(*, value: object) -> SqlTestAssertionStep: - payload: dict[str, Any] = _object(value=value, context="assertion step") - return SqlTestAssertionStep( - name=_string(value=payload.get("name"), context="assertion name"), - resolved_sql=_string(value=payload.get("resolvedSql"), context="assertion SQL"), - lifted_ctes=_cte_pairs(value=payload.get("liftedCtes")), - comparison_body_sql=_optional_string( - value=payload.get("comparisonBodySql"), context="assertion comparison SQL" - ), - ) - - -def _warning(*, value: object) -> PlanWarning: - payload: dict[str, Any] = _object(value=value, context="warning") - return PlanWarning( - model_name=_optional_string(value=payload.get("modelName"), context="warning model"), - severity=WarningSeverity( - _string(value=payload.get("severity"), context="warning severity") - ), - message=_string(value=payload.get("message"), context="warning message"), - ) - - -def _cte_pairs(*, value: object) -> tuple[tuple[str, str], ...]: - if not isinstance(value, list): - raise NativeSqlTestPlanningError("native SQL-test planning returned invalid lifted CTEs") - pairs: list[tuple[str, str]] = [] - for pair in value: - name, sql = _string_tuple(value=pair, context="lifted CTE") - pairs.append((name, sql)) - return tuple(pairs) - - -def _object(*, value: object, context: str) -> dict[str, Any]: - if not isinstance(value, dict): - raise NativeSqlTestPlanningError(f"native SQL-test planning returned an invalid {context}") - return cast(dict[str, Any], value) - - -def _string(*, value: object, context: str) -> str: - if not isinstance(value, str): - raise NativeSqlTestPlanningError(f"native SQL-test planning returned an invalid {context}") - return value - - -def _optional_string(*, value: object, context: str) -> str | None: - return None if value is None else _string(value=value, context=context) - - -def _optional_string_tuple(*, value: object, context: str) -> tuple[str, ...] | None: - return None if value is None else _string_tuple(value=value, context=context) - - -def _string_tuple(*, value: object, context: str) -> tuple[str, ...]: - if not isinstance(value, list): - raise NativeSqlTestPlanningError(f"native SQL-test planning returned an invalid {context}") - return tuple(_string(value=item, context=context) for item in value) - - -def _function_requests( - *, project: CompiledProject, adapter: BaseAdapter -) -> list[dict[str, object]]: - return [ - { - "name": name, - "udfPrefix": udf_prefix, - "udfSuffix": udf_suffix, - "tableFunctionPrefix": table_function_prefix, - "tableFunctionSuffix": table_function_suffix, - } - for ( - name, - udf_prefix, - udf_suffix, - table_function_prefix, - table_function_suffix, - ) in _function_templates(project=project, adapter=adapter) - ] - - def _function_templates( *, project: CompiledProject, adapter: BaseAdapter ) -> tuple[tuple[str, str, str, str, str], ...]: @@ -601,40 +354,6 @@ def _function_templates( return tuple(functions) -def _planning_test_requests( - *, project: CompiledProject, tests: tuple[CompiledSqlTest, ...], adapter: BaseAdapter -) -> list[dict[str, object]]: - """Build test requests whose model SQL has cursor intrinsics rendered for the test window.""" - - models_by_name: dict[str, CompiledModel] = {model.name: model for model in project.models} - windowed_indexes: tuple[int, ...] = tuple( - index - for index, test in enumerate(tests) - if isinstance(test.payload, CompiledModelSqlTestPayload) - and declares_cursor_window(test=test) - ) - chains: tuple[tuple[str, ...], ...] = ( - resolve_sql_test_model_chains( - project=project, tests=tuple(tests[index] for index in windowed_indexes) - ) - if windowed_indexes - else () - ) - chains_by_index: dict[int, tuple[str, ...]] = dict(zip(windowed_indexes, chains, strict=True)) - return [ - _test_request( - test=test, - model_query_overrides=_windowed_model_query_overrides( - test=test, - models_by_name=models_by_name, - adapter=adapter, - chain=chains_by_index.get(index), - ), - ) - for index, test in enumerate(tests) - ] - - def _windowed_model_query_overrides( *, test: CompiledSqlTest, @@ -671,87 +390,8 @@ def _windowed_model_query_overrides( return overrides -def _test_request( - *, test: CompiledSqlTest, model_query_overrides: dict[str, str] | None = None -) -> dict[str, object]: - payload: CompiledModelSqlTestPayload | CompiledDirectLogicSqlTestPayload = test.payload - if isinstance(payload, CompiledDirectLogicSqlTestPayload): - payload_request: dict[str, object] = { - "kind": "direct", - "mode": payload.mode.value, - "actualCte": _cte_request(cte=payload.actual_cte), - "expectedCte": _cte_request(cte=payload.expected_cte), - "helperCtes": [_cte_request(cte=cte) for cte in payload.helper_ctes], - } - else: - payload_request = { - "kind": "model", - "authoredCtes": [_cte_request(cte=cte) for cte in payload.authored_ctes], - "modelQueryOverrides": ( - payload.model_query_overrides - if model_query_overrides is None - else model_query_overrides - ), - "expectedCtes": [_cte_request(cte=cte) for cte in payload.expected_ctes], - "expectedModelNames": list(payload.expected_model_names), - "assertionCtes": [_cte_request(cte=cte) for cte in payload.assertion_ctes], - "readHelperNames": list(test.read_helper_names), - "referenceTargetModelNames": list(test.reference_target_model_names), - } - return { - "name": test.name, - "fileLabel": str(test.test_file.relative_path), - "payload": payload_request, - } - - -def _model_requests(*, project: CompiledProject, adapter: BaseAdapter) -> list[dict[str, object]]: - return [ - { - "name": model.name, - "querySql": render_test_cursor_intrinsics( - sql=model.query_sql, model=model, adapter=adapter, test=None - ), - "modelDependencies": _model_dependencies(model=model), - } - for model in project.models - ] - - -def _chain_model_requests(*, project: CompiledProject) -> list[dict[str, object]]: - """Chain ordering reads only declared dependencies, so model SQL is not sent.""" - - return [ - {"name": model.name, "modelDependencies": _model_dependencies(model=model)} - for model in project.models - ] - - -def _model_dependencies(*, model: CompiledModel) -> list[str]: - return [ - dependency.name - for dependency in model.deps - if dependency.resource_type == CompiledResourceType.MODEL - ] - - -def _cte_request(*, cte: CompileSqlTestCte) -> dict[str, str]: - return {"name": cte.name, "sqlBody": cte.sql_body} - - def _render_call_template(*, rendered: str) -> tuple[str, str]: prefix, separator, suffix = rendered.partition(_CALL_SUFFIX_SENTINEL) if not separator or _CALL_SUFFIX_SENTINEL in suffix: raise NativeSqlTestPlanningError("adapter SQL function call template is not deterministic") return prefix, suffix - - -def _lexical_syntax_request(syntax: SqlLexicalSyntax) -> dict[str, object]: - return { - "backslashEscapeQuotes": sorted(syntax.backslash_escape_quotes), - "escapeStringPrefix": syntax.escape_string_prefix, - "rawStringPrefix": syntax.raw_string_prefix, - "tripleQuotedStrings": syntax.triple_quoted_strings, - "nestedBlockComments": syntax.nested_block_comments, - "lineCommentPrefixes": sorted(syntax.line_comment_prefixes), - } diff --git a/src/sqlbuild/compiler/planner/main/execution/sql_test_artifacts.py b/src/sqlbuild/compiler/planner/main/execution/sql_test_artifacts.py deleted file mode 100644 index 8eaffd9f5c..0000000000 --- a/src/sqlbuild/compiler/planner/main/execution/sql_test_artifacts.py +++ /dev/null @@ -1,25 +0,0 @@ -"""Public planner entrypoint for compiled SQL-test artifacts.""" - -from sqlbuild.adapter.contract.classes.base_adapter import BaseAdapter -from sqlbuild.compiler.compile.models import CompiledProject, CompiledSqlTest -from sqlbuild.compiler.planner._helpers.sql_tests.native_planning import ( - plan_and_render_sql_test_artifacts as _plan_and_render_sql_test_artifacts, -) -from sqlbuild.compiler.planner.models import NativeSqlTestArtifact - - -def plan_and_render_sql_test_artifacts( - *, - project: CompiledProject, - tests: tuple[CompiledSqlTest, ...], - adapter: BaseAdapter, - sql_analysis_enabled: bool, -) -> tuple[NativeSqlTestArtifact, ...]: - """Plan and render SQL tests in one deterministic native project call.""" - - return _plan_and_render_sql_test_artifacts( - project=project, - tests=tests, - adapter=adapter, - sql_analysis_enabled=sql_analysis_enabled, - ) diff --git a/src/sqlbuild/compiler/project_assembly/_helpers/deferrals.py b/src/sqlbuild/compiler/project_assembly/_helpers/deferrals.py deleted file mode 100644 index 296c742539..0000000000 --- a/src/sqlbuild/compiler/project_assembly/_helpers/deferrals.py +++ /dev/null @@ -1,24 +0,0 @@ -"""Debug-only record of the project assembly work native hands back to Python.""" - -from __future__ import annotations - -import json -import os -from pathlib import Path - -from sqlbuild.compiler.lineage.constants import ANALYSIS_DEFERRAL_RECORD_PREFIX -from sqlbuild.compiler.project_assembly.constants import PROJECT_ASSEMBLY_DEFERRAL_SITE -from sqlbuild.compiler.sql_analysis.constants import ANALYSIS_RECORD_DIR_ENV_VAR - - -def record_project_assembly_deferral(*, kind: str) -> None: - """Append one `{"kind", "site"}` line when the analysis record directory is set.""" - - directory: str | None = os.environ.get(ANALYSIS_RECORD_DIR_ENV_VAR) - if not directory: - return - target: Path = Path(directory) - target.mkdir(parents=True, exist_ok=True) - record: str = json.dumps({"kind": kind, "site": PROJECT_ASSEMBLY_DEFERRAL_SITE}) - with open(target / f"{ANALYSIS_DEFERRAL_RECORD_PREFIX}{os.getpid()}.jsonl", "a") as handle: - _ = handle.write(record + "\n") diff --git a/src/sqlbuild/compiler/project_assembly/_helpers/request.py b/src/sqlbuild/compiler/project_assembly/_helpers/request.py index 145c5a8964..1fdf58dc0f 100644 --- a/src/sqlbuild/compiler/project_assembly/_helpers/request.py +++ b/src/sqlbuild/compiler/project_assembly/_helpers/request.py @@ -6,6 +6,7 @@ import re from collections.abc import Iterable +from sqlbuild.compiler.authored_values.main._project_var_values import render_project_var_text from sqlbuild.compiler.compile.models import CompileProjectInputs, CompileSqlReference from sqlbuild.compiler.project_assembly.constants import ( BOOLEAN_VARIABLE, @@ -14,9 +15,13 @@ NATIVE_INT_MAX, NATIVE_INT_MIN, NONE_VARIABLE, + OPAQUE_VARIABLE, + RENDER_LABEL, + RENDER_RAISES, + RENDER_REJECTED, + RENDERED_TEXT, TEXT_VARIABLE, TRUE_TEXT, - UNSUPPORTED_VARIABLE, ) from sqlbuild.compiler.project_assembly.types import ( AuditRow, @@ -25,6 +30,7 @@ SyntaxCheckRow, VariableRow, ) +from sqlbuild.compiler.resource_names.main.function_node_type import function_node_type from sqlbuild.spec.contracts.models import DefaultsConfig, TargetConfig @@ -33,9 +39,12 @@ def project_request( inputs: CompileProjectInputs, dialect: str | None, syntax_checks: tuple[tuple[tuple[str, dict[str, str] | None], ...], ...], -) -> ProjectRequestRow: - """Return the request row; `syntax_checks` holds each model's SQL Python would validate.""" +) -> tuple[ProjectRequestRow, list[Exception | None]]: + """Return the request row and, per variable, the exception rendering it as text raises.""" + renders: list[tuple[str, str] | Exception | None] = [ + _opaque_render(value=value) for value in inputs.effective_vars.values() + ] target: TargetConfig | None = inputs.effective_target defaults: DefaultsConfig = inputs.project_config.defaults target_values: tuple[str | None, ...] = ( @@ -50,14 +59,25 @@ def project_request( seed_values: list[str | None] = [] for seed_input in inputs.seed_inputs: seed_values.extend((seed_input.schema_entry.database, seed_input.schema_entry.schema)) - return ( + row: ProjectRequestRow = ( dialect or "generic", (target.database, target.schema, target.loader_schema) if target is not None else None, (defaults.database, defaults.schema, defaults.seed_database, defaults.seed_schema), - [_variable_row(name=name, value=value) for name, value in inputs.effective_vars.items()], + [ + _variable_row(name=name, value=value, render=render, index=index) + for index, ((name, value), render) in enumerate( + zip(inputs.effective_vars.items(), renders, strict=True) + ) + ], _environment_rows((*target_values, *default_values, *seed_values)), [ - (_reference_rows(model_input.references), _syntax_check_rows(checks)) + ( + model_input.model_file.file_path.stem, + str(model_input.model_file.relative_path.parent), + _tag_rows(model_input.config.values.get("tags")), + _reference_rows(model_input.references), + _syntax_check_rows(checks), + ) for model_input, checks in zip(inputs.model_inputs, syntax_checks, strict=True) ], [ @@ -72,13 +92,19 @@ def project_request( [ ( seed_input.schema_entry.name, + list(seed_input.schema_entry.tags), seed_input.schema_entry.database, seed_input.schema_entry.schema, ) for seed_input in inputs.seed_inputs ], [ - _reference_rows(function_input.references) + ( + function_node_type(return_columns=function_input.return_columns), + function_input.name, + list(function_input.tags), + _reference_rows(function_input.references), + ) for function_input in inputs.sql_function_inputs ], [ @@ -90,6 +116,15 @@ def project_request( for audit_input in inputs.audit_inputs ], ) + return row, [render if isinstance(render, Exception) else None for render in renders] + + +def _tag_rows(value: object) -> list[str]: + """Model config tags as the project graph indexes them.""" + + if isinstance(value, list | tuple): + return [str(item) for item in value] + return [] def _environment_rows(values: Iterable[str | None]) -> list[tuple[str, str | None]]: @@ -102,16 +137,38 @@ def _environment_rows(values: Iterable[str | None]) -> list[tuple[str, str | Non return [(name, os.environ.get(name)) for name in names] -def _variable_row(*, name: str, value: object) -> VariableRow: +def _variable_row( + *, name: str, value: object, render: tuple[str, str] | Exception | None, index: int +) -> VariableRow: if value is None: - return (name, NONE_VARIABLE, "") + return (name, NONE_VARIABLE, "", None) if type(value) is bool: - return (name, BOOLEAN_VARIABLE, TRUE_TEXT if value else FALSE_TEXT) + return (name, BOOLEAN_VARIABLE, TRUE_TEXT if value else FALSE_TEXT, None) if type(value) is str: - return (name, TEXT_VARIABLE, value) + return (name, TEXT_VARIABLE, value, None) + if type(value) is int and NATIVE_INT_MIN <= value <= NATIVE_INT_MAX: + return (name, TEXT_VARIABLE, str(value), None) + held: tuple[str, str] = (RENDER_RAISES, str(index)) + return (name, OPAQUE_VARIABLE, str(value), held if isinstance(render, Exception) else render) + + +def _opaque_render(*, value: object) -> tuple[str, str] | Exception | None: + """`render_project_var_text` for any label: text, the message after the label, or the error.""" + + if value is None or type(value) in (bool, str): + return None if type(value) is int and NATIVE_INT_MIN <= value <= NATIVE_INT_MAX: - return (name, TEXT_VARIABLE, str(value)) - return (name, UNSUPPORTED_VARIABLE, "") + return None + try: + text: str = render_project_var_text(value=value, label=RENDER_LABEL) + except ValueError as error: + message: str = str(error) + if message.startswith(RENDER_LABEL): + return (RENDER_REJECTED, message[len(RENDER_LABEL) :]) + return error + except Exception as error: + return error + return (RENDERED_TEXT, text) def _reference_rows(references: tuple[CompileSqlReference, ...]) -> list[ReferenceRow]: diff --git a/src/sqlbuild/compiler/project_assembly/_helpers/resources.py b/src/sqlbuild/compiler/project_assembly/_helpers/resources.py index 4475507e1e..0447acb07b 100644 --- a/src/sqlbuild/compiler/project_assembly/_helpers/resources.py +++ b/src/sqlbuild/compiler/project_assembly/_helpers/resources.py @@ -3,8 +3,11 @@ from __future__ import annotations from dataclasses import replace +from typing import cast +import sqlbuild._native as _native from sqlbuild.compiler.compile.constants import COMPILE_INPUT_READS +from sqlbuild.compiler.compile.exceptions import CompileInputError from sqlbuild.compiler.compile.models import ( CompiledObjectKey, CompiledRelationLocation, @@ -13,38 +16,76 @@ CompileSourceInput, ) from sqlbuild.compiler.compile.types import CompiledResourceType -from sqlbuild.compiler.project_assembly.constants import ENVIRONMENT_READ -from sqlbuild.compiler.project_assembly.models import NativeProjectResources +from sqlbuild.compiler.project_assembly.constants import ( + COMPILE_INPUT_FAILURE, + ENVIRONMENT_READ, + HELD_FAILURE, + VALUE_FAILURE, +) +from sqlbuild.compiler.project_assembly.models import NativeProjectResources, NativeResourceFailure from sqlbuild.compiler.project_assembly.types import ( + FailureRow, NamespaceRow, ObjectKeyRow, ProjectResourcesRow, ) +from sqlbuild.compiler.sql_analysis.constants import NATIVE_FAILURE_PREFIX from sqlbuild.spec.contracts.models import SourceEntry def project_resources( - *, inputs: CompileProjectInputs, row: ProjectResourcesRow + *, inputs: CompileProjectInputs, row: ProjectResourcesRow, held: list[Exception | None] ) -> NativeProjectResources: - """Return the resource facts the native row describes, in input order.""" + """Return the resource facts the native row describes, in input order, up to the failure.""" - model_deps, source_namespaces, seed_namespaces, function_deps, audit_deps, reads = row + ( + model_deps, + source_namespaces, + seed_namespaces, + function_deps, + audit_deps, + reads, + syntax, + failure, + ) = row _ = [_replay_read(kind=kind, name=name) for kind, name in reads] return NativeProjectResources( model_deps=tuple(_keys(keys) for keys in model_deps), + model_syntax_valid=tuple(syntax), source_entries=tuple( _source_entry(source_input=source_input, namespace=namespace) - for source_input, namespace in zip(inputs.source_inputs, source_namespaces, strict=True) + for source_input, namespace in zip( + inputs.source_inputs[: len(source_namespaces)], source_namespaces, strict=True + ) ), seed_destinations=tuple( _seed_destination(seed_input=seed_input, namespace=namespace) - for seed_input, namespace in zip(inputs.seed_inputs, seed_namespaces, strict=True) + for seed_input, namespace in zip( + inputs.seed_inputs[: len(seed_namespaces)], seed_namespaces, strict=True + ) ), function_deps=tuple(_keys(keys) for keys in function_deps), audit_scope_deps=tuple(_keys(keys) for keys in audit_deps), + failure=None if failure is None else _failure(row=failure, held=held), ) +def _failure(*, row: FailureRow, held: list[Exception | None]) -> NativeResourceFailure: + slot, index, kind, message, help_text, held_index = row + error: Exception + if kind == COMPILE_INPUT_FAILURE: + error = CompileInputError(message, help=help_text) + elif kind == VALUE_FAILURE: + error = ValueError(message) + elif kind == HELD_FAILURE and held_index is not None and held[held_index] is not None: + error = cast(Exception, held[held_index]) + else: + raise _native.NativeCompilerError( + f"{NATIVE_FAILURE_PREFIX}native project assembly: unknown failure kind '{kind}'" + ) + return NativeResourceFailure(slot=slot, index=index, error=error) + + def _replay_read(*, kind: str, name: str) -> None: if kind == ENVIRONMENT_READ: COMPILE_INPUT_READS.environment_read(name) diff --git a/src/sqlbuild/compiler/project_assembly/constants.py b/src/sqlbuild/compiler/project_assembly/constants.py index 9b809a1ecd..6435d36097 100644 --- a/src/sqlbuild/compiler/project_assembly/constants.py +++ b/src/sqlbuild/compiler/project_assembly/constants.py @@ -1,10 +1,19 @@ -"""Native project assembly request kinds and deferral record site.""" +"""Native project assembly request and failure kinds.""" -PROJECT_ASSEMBLY_DEFERRAL_SITE: str = "project_assembly" TEXT_VARIABLE: str = "text" BOOLEAN_VARIABLE: str = "bool" NONE_VARIABLE: str = "none" -UNSUPPORTED_VARIABLE: str = "unsupported" +OPAQUE_VARIABLE: str = "opaque" +RENDERED_TEXT: str = "text" +RENDER_REJECTED: str = "rejected" +RENDER_RAISES: str = "raises" +RENDER_LABEL: str = "\x00" +COMPILE_INPUT_FAILURE: str = "compile_input" +VALUE_FAILURE: str = "value" +HELD_FAILURE: str = "held" +SOURCE_SLOT: str = "source" +SEED_SLOT: str = "seed" +AUDIT_SLOT: str = "audit" TRUE_TEXT: str = "1" FALSE_TEXT: str = "0" NATIVE_INT_MIN: int = -(2**63) diff --git a/src/sqlbuild/compiler/project_assembly/main/_assemble_native_project_resources.py b/src/sqlbuild/compiler/project_assembly/main/_assemble_native_project_resources.py index fd3b5d63d0..215c614cd4 100644 --- a/src/sqlbuild/compiler/project_assembly/main/_assemble_native_project_resources.py +++ b/src/sqlbuild/compiler/project_assembly/main/_assemble_native_project_resources.py @@ -1,14 +1,13 @@ -"""Assemble the compiled project's resource facts natively for the preview compiler engine.""" +"""Assemble the compiled project's resource facts natively.""" from __future__ import annotations import sqlbuild._native as _native from sqlbuild.compiler.compile.models import CompileProjectInputs -from sqlbuild.compiler.project_assembly._helpers.deferrals import record_project_assembly_deferral from sqlbuild.compiler.project_assembly._helpers.request import project_request from sqlbuild.compiler.project_assembly._helpers.resources import project_resources from sqlbuild.compiler.project_assembly.models import NativeProjectResources -from sqlbuild.compiler.project_assembly.types import ProjectResourcesRow +from sqlbuild.compiler.project_assembly.types import ProjectRequestRow, ProjectResourcesRow def assemble_native_project_resources( @@ -16,15 +15,11 @@ def assemble_native_project_resources( inputs: CompileProjectInputs, dialect: str | None, syntax_checks: tuple[tuple[tuple[str, dict[str, str] | None], ...], ...], -) -> NativeProjectResources | None: - """Return the resource facts, or None with a deferral record where Python must assemble.""" +) -> NativeProjectResources: + """Return the resource facts and the resource Python's assembly raises at, if any.""" - row: ProjectResourcesRow | None - deferral: str | None - row, deferral = _native.assemble_project_resource_facts( - project_request(inputs=inputs, dialect=dialect, syntax_checks=syntax_checks) - ) - if row is None: - _ = record_project_assembly_deferral(kind=deferral or "unknown") - return None - return project_resources(inputs=inputs, row=row) + request: ProjectRequestRow + held: list[Exception | None] + request, held = project_request(inputs=inputs, dialect=dialect, syntax_checks=syntax_checks) + row: ProjectResourcesRow = _native.assemble_project_resource_facts(request) + return project_resources(inputs=inputs, row=row, held=held) diff --git a/src/sqlbuild/compiler/project_assembly/main/_check_native_sql_syntax.py b/src/sqlbuild/compiler/project_assembly/main/_check_native_sql_syntax.py index a929ed239f..0a00801549 100644 --- a/src/sqlbuild/compiler/project_assembly/main/_check_native_sql_syntax.py +++ b/src/sqlbuild/compiler/project_assembly/main/_check_native_sql_syntax.py @@ -1,24 +1,18 @@ -"""Check SQL syntax natively for the preview compiler engine.""" +"""Check SQL syntax natively.""" from __future__ import annotations import sqlbuild._native as _native -from sqlbuild.compiler.project_assembly._helpers.deferrals import record_project_assembly_deferral def check_native_sql_syntax( *, checks: tuple[tuple[str, dict[str, str] | None], ...], dialect: str | None -) -> bool | None: - """Whether Python's syntax validation accepts every `(sql, placeholders)`; None to check it.""" +) -> bool: + """Whether every `(sql, placeholders)` parses; raises Python's pre-parse `ValueError`.""" - valid: bool | None - deferral: str | None - valid, deferral = _native.check_native_sql_syntax( + return _native.check_native_sql_syntax( ( dialect or "generic", [(sql, list((placeholders or {}).items())) for sql, placeholders in checks], ) ) - if valid is None: - _ = record_project_assembly_deferral(kind=deferral or "unknown") - return valid diff --git a/src/sqlbuild/compiler/project_assembly/main/_native_resource.py b/src/sqlbuild/compiler/project_assembly/main/_native_resource.py new file mode 100644 index 0000000000..61e833139a --- /dev/null +++ b/src/sqlbuild/compiler/project_assembly/main/_native_resource.py @@ -0,0 +1,16 @@ +"""Take one resource's native fact, raising the error Python's assembly raises there.""" + +from __future__ import annotations + +from sqlbuild.compiler.project_assembly.models import NativeProjectResources, NativeResourceFailure + + +def native_resource[T]( + *, resources: NativeProjectResources, slot: str, items: tuple[T, ...], index: int +) -> T: + """Return resource `index` of `slot`, raising the error Python's assembly raises there.""" + + failure: NativeResourceFailure | None = resources.failure + if failure is not None and failure.slot == slot and failure.index == index: + raise failure.error + return items[index] diff --git a/src/sqlbuild/compiler/project_assembly/models.py b/src/sqlbuild/compiler/project_assembly/models.py index 7905511275..89cb67c322 100644 --- a/src/sqlbuild/compiler/project_assembly/models.py +++ b/src/sqlbuild/compiler/project_assembly/models.py @@ -14,26 +14,38 @@ @dataclass(frozen=True, slots=True) class NativeProjectResources: - """Per-resource facts in input order; every requested SQL string passed syntax validation.""" + """Per-resource facts in input order, and whether each model's SQL passed syntax validation.""" model_deps: tuple[tuple[CompiledObjectKey, ...], ...] + model_syntax_valid: tuple[bool, ...] source_entries: tuple[SourceEntry, ...] seed_destinations: tuple[CompiledRelationLocation, ...] function_deps: tuple[tuple[CompiledObjectKey, ...], ...] audit_scope_deps: tuple[tuple[CompiledObjectKey, ...], ...] + failure: NativeResourceFailure | None = None + + +@dataclass(frozen=True, slots=True) +class NativeResourceFailure: + """The resource Python's assembly raises at, and the exception it raises there.""" + + slot: str + index: int + error: Exception @dataclass(frozen=True, slots=True) class NativeModelFacts: - """One model's native facts; each None where Python derives it.""" + """One model's native facts.""" - deps: tuple[CompiledObjectKey, ...] | None + deps: tuple[CompiledObjectKey, ...] dynamic_contract: DynamicColumnContractProof | None + syntax_valid: bool = False @dataclass(frozen=True, slots=True) class NativeProjectFacts: - """Every model's native facts, and the resource facts unless Python must assemble them.""" + """Every model's native facts and the resource facts.""" models: tuple[NativeModelFacts, ...] - resources: NativeProjectResources | None + resources: NativeProjectResources diff --git a/src/sqlbuild/compiler/project_assembly/types.py b/src/sqlbuild/compiler/project_assembly/types.py index a3e8ccf62b..afcec02958 100644 --- a/src/sqlbuild/compiler/project_assembly/types.py +++ b/src/sqlbuild/compiler/project_assembly/types.py @@ -4,10 +4,12 @@ type ReferenceRow = tuple[str, str, str | None] type SyntaxCheckRow = tuple[str, list[tuple[str, str]]] -type VariableRow = tuple[str, str, str] -type ModelRow = tuple[list[ReferenceRow], list[SyntaxCheckRow]] +type VariableRow = tuple[str, str, str, tuple[str, str] | None] +type FailureRow = tuple[str, int, str, str, str | None, int | None] +type ModelRow = tuple[str, str, list[str], list[ReferenceRow], list[SyntaxCheckRow]] type SourceRow = tuple[str, bool, str | None, str | None] -type SeedRow = tuple[str, str | None, str | None] +type SeedRow = tuple[str, list[str], str | None, str | None] +type FunctionRow = tuple[str, str, list[str], list[ReferenceRow]] type AuditRow = tuple[list[ReferenceRow], tuple[str, str] | None] type TargetRow = tuple[str | None, str | None, str | None] type DefaultsRow = tuple[str | None, str | None, str | None, str | None] @@ -20,7 +22,7 @@ list[ModelRow], list[SourceRow], list[SeedRow], - list[list[ReferenceRow]], + list[FunctionRow], list[AuditRow], ] type ObjectKeyRow = tuple[str, str] @@ -32,4 +34,6 @@ list[list[ObjectKeyRow]], list[list[ObjectKeyRow]], list[tuple[str, str]], + list[bool], + FailureRow | None, ] diff --git a/src/sqlbuild/compiler/references/_helpers/project_relations.py b/src/sqlbuild/compiler/references/_helpers/project_relations.py index d634ef504a..28c96a92f0 100644 --- a/src/sqlbuild/compiler/references/_helpers/project_relations.py +++ b/src/sqlbuild/compiler/references/_helpers/project_relations.py @@ -4,25 +4,11 @@ from collections.abc import Iterable, Mapping -from sqlbuild.compiler.compile.constants import MIGRATE_FROM_CONFIG_KEY -from sqlbuild.compiler.compile.models import ( - CompiledModel, - CompiledProject, - CompiledRelationLocation, -) -from sqlbuild.compiler.migrations.main._resolve_old_name_view_retention import ( - resolve_old_name_view_retention, -) from sqlbuild.compiler.references._helpers.relation_names import ( extract_relation_names_impl, - match_project_relation_impl, ) from sqlbuild.compiler.references.models import ProjectRelation, ProjectRelationIndex, RelationName from sqlbuild.python_nodes.models import SqlResourceRef -from sqlbuild.python_nodes.types import SqlResourceRefKind -from sqlbuild.spec.contracts.models import SourceEntry - -_SCHEMA_QUALIFIED_PARTS: int = 2 def build_project_relation_index_impl( @@ -33,92 +19,6 @@ def build_project_relation_index_impl( return ProjectRelationIndex(relations=tuple(dict.fromkeys(relations))) -def compiled_project_relations_impl( - *, project: CompiledProject, old_name_retention: str | None -) -> ProjectRelationIndex: - """Return the project relations a compiled project declares, with declared old names.""" - - relations: list[ProjectRelation] = [ - _location_relation( - ref=SqlResourceRef(kind=SqlResourceRefKind.MODEL, name=model.name), - location=model.destination, - ) - for model in project.models - ] - relations.extend( - _location_relation( - ref=SqlResourceRef(kind=SqlResourceRefKind.SEED, name=seed.name), - location=seed.destination, - ) - for seed in project.seeds - ) - for source in project.sources: - entry: SourceEntry = source.source_entry - if entry.expression is not None: - continue - relations.append( - ProjectRelation( - ref=SqlResourceRef(kind=SqlResourceRefKind.SOURCE, name=source.name), - relation=RelationName( - name=entry.table or entry.name, schema=entry.schema, database=entry.database - ), - ) - ) - declared: ProjectRelationIndex = build_project_relation_index_impl(relations) - return build_project_relation_index_impl( - ( - *declared.relations, - *_declared_old_names( - project=project, declared=declared, old_name_retention=old_name_retention - ), - ) - ) - - -def _declared_old_names( - *, project: CompiledProject, declared: ProjectRelationIndex, old_name_retention: str | None -) -> tuple[ProjectRelation, ...]: - """Return old names that migrate_from declarations keep only as compatibility views.""" - - model_names: frozenset[str] = frozenset(model.name for model in project.models) - old_names: list[ProjectRelation] = [] - model: CompiledModel - for model in project.models: - raw: object = model.config.values.get(MIGRATE_FROM_CONFIG_KEY) - if not isinstance(raw, str) or ( - resolve_old_name_view_retention( - config_values=model.config.values, project_retention=old_name_retention - ) - is None - ): - continue - parts: list[str] = [part.strip().strip('"`') for part in raw.split(".")] - if len(parts) == 1 and parts[0] in model_names: - continue - relation: RelationName = RelationName( - name=parts[-1], - schema=parts[-2] if len(parts) > 1 else model.destination.schema, - database=parts[-3] - if len(parts) > _SCHEMA_QUALIFIED_PARTS - else model.destination.database, - ) - if ( - match_project_relation_impl( - index=declared, relation=relation, default_database=None, default_schema=None - ) - is not None - ): - continue - old_names.append( - ProjectRelation( - ref=SqlResourceRef(kind=SqlResourceRefKind.MODEL, name=model.name), - relation=relation, - compatibility_for=model.name, - ) - ) - return tuple(old_names) - - def runtime_project_relations_impl( *, relations: Mapping[SqlResourceRef, str], dialect: str | None ) -> ProjectRelationIndex: @@ -133,14 +33,3 @@ def runtime_project_relations_impl( continue resolved.append(ProjectRelation(ref=ref, relation=extracted[0][0])) return build_project_relation_index_impl(resolved) - - -def _location_relation( - *, ref: SqlResourceRef, location: CompiledRelationLocation -) -> ProjectRelation: - return ProjectRelation( - ref=ref, - relation=RelationName( - name=location.name, schema=location.schema, database=location.database - ), - ) diff --git a/src/sqlbuild/compiler/references/_helpers/relation_names.py b/src/sqlbuild/compiler/references/_helpers/relation_names.py index ca9f188d6f..8c8fb9eaf8 100644 --- a/src/sqlbuild/compiler/references/_helpers/relation_names.py +++ b/src/sqlbuild/compiler/references/_helpers/relation_names.py @@ -2,20 +2,8 @@ from __future__ import annotations -from collections.abc import Iterator -from typing import Any, cast - +import sqlbuild._native as _native from sqlbuild.compiler.references.models import ProjectRelation, ProjectRelationIndex, RelationName -from sqlbuild.compiler.sql_analysis.main.import_polyglot_sql import import_polyglot_sql - -_GENERIC_DIALECT: str = "generic" -_TABLE_KEYS: frozenset[str] = frozenset({"name", "schema", "catalog", "alias", "hints"}) -_CTE_LIST_KEY: str = "ctes" -_CTE_ALIAS_KEY: str = "alias" -_CREATE_TABLE_KEY: str = "create_table" -_TEMPORARY_KEY: str = "temporary" -_QUALIFIER_SEPARATOR: str = "." -_SCHEMA_QUALIFIED_PART_COUNT: int = 2 def extract_relation_names_impl( @@ -23,23 +11,19 @@ def extract_relation_names_impl( ) -> tuple[tuple[RelationName, ...], frozenset[str]] | None: """Return relations named in ``sql`` and temporary tables it creates, or None if unparseable.""" - polyglot: Any = import_polyglot_sql() - try: - statements: list[Any] = polyglot.parse(sql, dialect=dialect or _GENERIC_DIALECT) - except polyglot.PolyglotError: + extracted: tuple[list[tuple[str, str | None, str | None]], list[str]] | None = ( + _native.extract_sql_relation_names(sql, dialect) + ) + if extracted is None: return None - names: dict[RelationName, None] = {} - temporary: set[str] = set() - for statement in statements: - tree: object = statement.to_dict() - cte_names: frozenset[str] = frozenset(_cte_names(tree)) - temporary.update(_temporary_table_names(tree)) - for relation in _table_names(tree): - if relation.schema is None and relation.database is None: - if relation.name.casefold() in cte_names: - continue - names[relation] = None - return tuple(names), frozenset(temporary) + relations, temporary = extracted + return ( + tuple( + RelationName(name=name, schema=schema, database=database) + for name, schema, database in relations + ), + frozenset(temporary), + ) def match_project_relation_impl( @@ -67,72 +51,3 @@ def match_project_relation_impl( def _parts_compatible(*, left: str | None, right: str | None) -> bool: return left is None or right is None or left.casefold() == right.casefold() - - -def _walk(node: object) -> Iterator[dict[str, object]]: - pending: list[object] = [node] - while pending: - current: object = pending.pop() - if isinstance(current, dict): - mapping: dict[str, object] = cast(dict[str, object], current) - yield mapping - pending.extend(mapping.values()) - elif isinstance(current, list | tuple): - pending.extend(current) - - -def _identifier(value: object) -> str | None: - if isinstance(value, dict): - name: object = cast(dict[str, object], value).get("name") - return name if isinstance(name, str) else None - return None - - -def _table_names(tree: object) -> Iterator[RelationName]: - for node in _walk(tree): - if not _TABLE_KEYS.issubset(node.keys()): - continue - name: str | None = _identifier(node.get("name")) - if name is None: - continue - schema: str | None = _identifier(node.get("schema")) - database: str | None = _identifier(node.get("catalog")) - if schema is None and database is None and _QUALIFIER_SEPARATOR in name: - parts: list[str] = name.split(_QUALIFIER_SEPARATOR) - name = parts[-1] - schema = parts[-2] - database = parts[-3] if len(parts) > _SCHEMA_QUALIFIED_PART_COUNT else None - yield RelationName(name=name, schema=schema, database=database) - - -def _cte_names(tree: object) -> Iterator[str]: - for node in _walk(tree): - ctes: object = node.get(_CTE_LIST_KEY) - if not isinstance(ctes, list): - continue - for cte in ctes: - alias: str | None = ( - _identifier(cast(dict[str, object], cte).get(_CTE_ALIAS_KEY)) - if isinstance(cte, dict) - else None - ) - if alias is not None: - yield alias.casefold() - - -def _temporary_table_names(tree: object) -> Iterator[str]: - for node in _walk(tree): - create: object = node.get(_CREATE_TABLE_KEY) - if not isinstance(create, dict): - continue - create_table: dict[str, object] = cast(dict[str, object], create) - if create_table.get(_TEMPORARY_KEY) is not True: - continue - table: object = create_table.get("name") - name: str | None = ( - _identifier(cast(dict[str, object], table).get("name")) - if isinstance(table, dict) - else None - ) - if name is not None: - yield name.casefold() diff --git a/src/sqlbuild/compiler/references/main/_compiled_project_relations.py b/src/sqlbuild/compiler/references/main/_compiled_project_relations.py deleted file mode 100644 index 317abacd55..0000000000 --- a/src/sqlbuild/compiler/references/main/_compiled_project_relations.py +++ /dev/null @@ -1,15 +0,0 @@ -"""Compile-time project-relation index entrypoint.""" - -from __future__ import annotations - -from sqlbuild.compiler.compile.models import CompiledProject -from sqlbuild.compiler.references._helpers.project_relations import compiled_project_relations_impl -from sqlbuild.compiler.references.models import ProjectRelationIndex - - -def compiled_project_relations( - *, project: CompiledProject, old_name_retention: str | None -) -> ProjectRelationIndex: - """Return the project relations a compiled project declares, with declared old names.""" - - return compiled_project_relations_impl(project=project, old_name_retention=old_name_retention) diff --git a/src/sqlbuild/compiler/semantic_checks/_helpers/completion.py b/src/sqlbuild/compiler/semantic_checks/_helpers/completion.py index 8afb26b9d3..b83283daa8 100644 --- a/src/sqlbuild/compiler/semantic_checks/_helpers/completion.py +++ b/src/sqlbuild/compiler/semantic_checks/_helpers/completion.py @@ -14,9 +14,7 @@ DiagnosticPhase, DiagnosticSeverity, ) -from sqlbuild.compiler.semantic_checks._helpers.deferrals import record_semantic_deferral from sqlbuild.compiler.semantic_checks._helpers.payloads import diagnostic_ids, lineage_payload -from sqlbuild.compiler.semantic_checks.constants import COMPLETION_DEFERRAL_SITE from sqlbuild.spec.contracts.models import SourceLocation _RECOVERED_CODE: str = "B002" @@ -33,8 +31,8 @@ def complete_native_diagnostics( catalog: object, session: Any | None, session_models: frozenset[str], -) -> CompiledProject | None: - """Return the recovered, explained and opt-out-checked project, or None to use Python.""" +) -> CompiledProject: + """The recovered, explained and opt-out-checked project; a native internal failure raises.""" ids: dict[CompilerDiagnostic, int] = diagnostic_ids(project) recovers: bool = any(item.code == _RECOVERED_CODE for item in project.diagnostics) @@ -50,12 +48,7 @@ def complete_native_diagnostics( ], [(name, list(columns.items())) for name, columns in shapes.items()], ) - deferral, completed, model_bindings, order = _native.complete_semantic_checks( - catalog, request, session - ) - if deferral is not None: - record_semantic_deferral(kind=deferral, site=COMPLETION_DEFERRAL_SITE) - return None + completed, model_bindings, order = _native.complete_semantic_checks(catalog, request, session) diagnostics: list[CompilerDiagnostic] = [ _completed(original=project.diagnostics[row[0]], row=row) for row in completed ] diff --git a/src/sqlbuild/compiler/semantic_checks/_helpers/deferrals.py b/src/sqlbuild/compiler/semantic_checks/_helpers/deferrals.py deleted file mode 100644 index 67a2ec2bea..0000000000 --- a/src/sqlbuild/compiler/semantic_checks/_helpers/deferrals.py +++ /dev/null @@ -1,23 +0,0 @@ -"""Debug-only record of semantic completion stages the native engine hands back to Python.""" - -from __future__ import annotations - -import json -import os -from pathlib import Path - -from sqlbuild.compiler.lineage.constants import ANALYSIS_DEFERRAL_RECORD_PREFIX -from sqlbuild.compiler.sql_analysis.constants import ANALYSIS_RECORD_DIR_ENV_VAR - - -def record_semantic_deferral(*, kind: str, site: str) -> None: - """Append one `{"kind", "site"}` line when the analysis record directory is set.""" - - directory: str | None = os.environ.get(ANALYSIS_RECORD_DIR_ENV_VAR) - if not directory: - return - target: Path = Path(directory) - target.mkdir(parents=True, exist_ok=True) - record: str = json.dumps({"kind": kind, "site": site}) - with open(target / f"{ANALYSIS_DEFERRAL_RECORD_PREFIX}{os.getpid()}.jsonl", "a") as handle: - _ = handle.write(record + "\n") diff --git a/src/sqlbuild/compiler/semantic_checks/_helpers/metadata.py b/src/sqlbuild/compiler/semantic_checks/_helpers/metadata.py index 46b0366874..5cc53c77be 100644 --- a/src/sqlbuild/compiler/semantic_checks/_helpers/metadata.py +++ b/src/sqlbuild/compiler/semantic_checks/_helpers/metadata.py @@ -24,10 +24,8 @@ DiagnosticSeverity, ) from sqlbuild.compiler.discovery.constants import SQL_ANALYSIS_CONFIG_KEY -from sqlbuild.compiler.semantic_checks._helpers.deferrals import record_semantic_deferral from sqlbuild.compiler.semantic_checks.constants import ( METADATA_CONFIG_KEYS, - METADATA_DEFERRAL_SITE, METADATA_FUNCTION_REFERENCE_KINDS, ) from sqlbuild.spec.contracts.models import SourceLocation @@ -42,8 +40,8 @@ def native_metadata_diagnostics( profile: ExpressionInferenceProfile, resource_sql_analysis: bool, catalog: object, -) -> tuple[CompilerDiagnostic, ...] | None: - """Return `get_semantic_metadata_diagnostics`' result, or None where Python must check.""" +) -> tuple[CompilerDiagnostic, ...]: + """The project's semantic metadata diagnostics; a native internal failure raises.""" if not project.settings.sql_analysis: return () @@ -78,12 +76,9 @@ def native_metadata_diagnostics( for test in tests ], ) - deferral, model_rows, source_rows, test_rows, fallback_types = ( - _native.check_semantic_metadata_rows(catalog, request) + model_rows, source_rows, test_rows, fallback_types = _native.check_semantic_metadata_rows( + catalog, request ) - if deferral is not None: - record_semantic_deferral(kind=deferral, site=METADATA_DEFERRAL_SITE) - return None for type_sql in fallback_types: _ = normalize_type(type_sql=type_sql, dialect=profile.sql_analysis_dialect) diagnostics: list[CompilerDiagnostic] = [] diff --git a/src/sqlbuild/compiler/semantic_checks/_helpers/stage.py b/src/sqlbuild/compiler/semantic_checks/_helpers/stage.py index 922ca72ff2..3976377b0c 100644 --- a/src/sqlbuild/compiler/semantic_checks/_helpers/stage.py +++ b/src/sqlbuild/compiler/semantic_checks/_helpers/stage.py @@ -5,18 +5,14 @@ from dataclasses import replace from typing import Any +import sqlbuild._native as _native from sqlbuild.adapter.contract.models import ExpressionInferenceProfile -from sqlbuild.compiler.compile.classes.semantic_completion_inputs import SemanticCompletionInputs from sqlbuild.compiler.compile.models import CompiledProject, CompilerDiagnostic from sqlbuild.compiler.semantic_checks._helpers.completion import complete_native_diagnostics -from sqlbuild.compiler.semantic_checks._helpers.deferrals import record_semantic_deferral from sqlbuild.compiler.semantic_checks._helpers.metadata import native_metadata_diagnostics from sqlbuild.compiler.semantic_checks._helpers.payloads import session_fact_models from sqlbuild.compiler.semantic_checks._helpers.type_recovery import recover_native_output_types -from sqlbuild.compiler.semantic_checks.constants import ( - COMPLETION_DEFERRAL_SITE, - NATIVE_SEMANTIC_NO_CATALOG, -) +from sqlbuild.compiler.semantic_checks.constants import NATIVE_SEMANTIC_NO_CATALOG from sqlbuild.compiler.sql_analysis.models import SqlBindingDiagnostic @@ -27,33 +23,26 @@ def completed_semantic_project( binding_results: dict[str, tuple[SqlBindingDiagnostic, ...]], resource_sql_analysis: bool, session: Any | None, -) -> CompiledProject | None: - """Python's completed project, or None where any native step hands the stage back.""" +) -> CompiledProject: + """The completed project; a native internal failure raises `NativeCompilerError`.""" if project.binding_catalog is None: - record_semantic_deferral(kind=NATIVE_SEMANTIC_NO_CATALOG, site=COMPLETION_DEFERRAL_SITE) - return None + raise _native.NativeCompilerError(NATIVE_SEMANTIC_NO_CATALOG) catalog: object = project.binding_catalog.native session_models: frozenset[str] = session_fact_models(project=project, session=session) - recovered: CompiledProject | None = recover_native_output_types( + recovered: CompiledProject = recover_native_output_types( project=project, binding_results=binding_results, catalog=catalog, session=session, session_models=session_models, ) - if recovered is None: - return None - metadata: tuple[CompilerDiagnostic, ...] | None = native_metadata_diagnostics( + metadata: tuple[CompilerDiagnostic, ...] = native_metadata_diagnostics( project=recovered, profile=profile, resource_sql_analysis=resource_sql_analysis, catalog=catalog, ) - if metadata is None: - metadata = SemanticCompletionInputs.metadata_diagnostics( - project=recovered, profile=profile, resource_sql_analysis=resource_sql_analysis - ) return complete_native_diagnostics( project=replace(recovered, diagnostics=(*recovered.diagnostics, *metadata)), catalog=catalog, diff --git a/src/sqlbuild/compiler/semantic_checks/_helpers/type_recovery.py b/src/sqlbuild/compiler/semantic_checks/_helpers/type_recovery.py index d433974d15..868a91e6b6 100644 --- a/src/sqlbuild/compiler/semantic_checks/_helpers/type_recovery.py +++ b/src/sqlbuild/compiler/semantic_checks/_helpers/type_recovery.py @@ -14,7 +14,6 @@ InferredColumn, ) from sqlbuild.compiler.compile.types import CompiledResourceType -from sqlbuild.compiler.semantic_checks._helpers.deferrals import record_semantic_deferral from sqlbuild.compiler.semantic_checks._helpers.payloads import ( diagnostic_ids, has_blocking_binding, @@ -22,10 +21,7 @@ raw_binding_ids, ) from sqlbuild.compiler.semantic_checks.constants import ( - NATIVE_SEMANTIC_FAILURE, - NATIVE_TYPE_RECOVERY_DEFERRED, NATIVE_TYPE_RECOVERY_UNCHANGED, - TYPE_RECOVERY_DEFERRAL_SITE, UNKNOWN_RECOVERED_TYPE, ) from sqlbuild.compiler.sql_analysis.main._schema_validation import get_schema_validations @@ -41,8 +37,8 @@ def recover_native_output_types( catalog: object, session: Any | None, session_models: frozenset[str], -) -> CompiledProject | None: - """Return `recover_output_types`'s project, or None where Python must recover the types.""" +) -> CompiledProject: + """The project with recovered output types; a native internal failure raises.""" if not has_blocking_binding(project): return project @@ -75,16 +71,10 @@ def recover_native_output_types( ) if recovery.status == NATIVE_TYPE_RECOVERY_UNCHANGED: return project - if recovery.status == NATIVE_TYPE_RECOVERY_DEFERRED: - record_semantic_deferral(kind=str(recovery.deferral), site=TYPE_RECOVERY_DEFERRAL_SITE) - return None poisoned: list[tuple[str, str]] = recovery.poisoned - outcome: tuple[list[tuple[int, str | None]], list[list[int]]] | None = recovery.finish( + outcome: tuple[list[tuple[int, str | None]], list[list[int]]] = recovery.finish( _revalidated(project=project, revalidated=recovery.revalidated, poisoned=poisoned) ) - if outcome is None: - record_semantic_deferral(kind=NATIVE_SEMANTIC_FAILURE, site=TYPE_RECOVERY_DEFERRAL_SITE) - return None kept, model_bindings = outcome diagnostics: tuple[CompilerDiagnostic, ...] = tuple( _with_note(diagnostic=project.diagnostics[index], note=note) for index, note in kept diff --git a/src/sqlbuild/compiler/semantic_checks/constants.py b/src/sqlbuild/compiler/semantic_checks/constants.py index 53d2036c0e..853738663f 100644 --- a/src/sqlbuild/compiler/semantic_checks/constants.py +++ b/src/sqlbuild/compiler/semantic_checks/constants.py @@ -1,14 +1,11 @@ -"""Native semantic completion statuses and deferral record sites.""" +"""Native semantic completion statuses and inputs.""" from sqlbuild.compiler.references.types import SqlReferenceKind NATIVE_TYPE_RECOVERY_UNCHANGED: str = "unchanged" -NATIVE_TYPE_RECOVERY_DEFERRED: str = "deferred" -NATIVE_SEMANTIC_NO_CATALOG: str = "no_analysis_catalog" -NATIVE_SEMANTIC_FAILURE: str = "native_failure" -TYPE_RECOVERY_DEFERRAL_SITE: str = "type_recovery.py" -COMPLETION_DEFERRAL_SITE: str = "recovery.py" -METADATA_DEFERRAL_SITE: str = "metadata_validation.py" +NATIVE_SEMANTIC_NO_CATALOG: str = ( + "NativeCompilerError: native semantic completion: the project has no analysis catalog" +) UNKNOWN_RECOVERED_TYPE: str = "UNKNOWN" METADATA_CONFIG_KEYS: tuple[str, ...] = ( "unique_key", diff --git a/src/sqlbuild/compiler/semantic_checks/main/_complete_native_semantic_diagnostics.py b/src/sqlbuild/compiler/semantic_checks/main/_complete_native_semantic_diagnostics.py index ca8f3e64ce..8ebffec6a9 100644 --- a/src/sqlbuild/compiler/semantic_checks/main/_complete_native_semantic_diagnostics.py +++ b/src/sqlbuild/compiler/semantic_checks/main/_complete_native_semantic_diagnostics.py @@ -17,8 +17,8 @@ def complete_native_semantic_diagnostics( binding_results: dict[str, tuple[SqlBindingDiagnostic, ...]], resource_sql_analysis: bool, session: Any | None = None, -) -> CompiledProject | None: - """Return the completed project, or None where Python must complete its diagnostics.""" +) -> CompiledProject: + """The completed project; a native internal failure raises `NativeCompilerError`.""" return completed_semantic_project( project=project, diff --git a/src/sqlbuild/compiler/sql_analysis/_helpers/scanning.py b/src/sqlbuild/compiler/sql_analysis/_helpers/scanning.py index e88be3e72d..b1a580421b 100644 --- a/src/sqlbuild/compiler/sql_analysis/_helpers/scanning.py +++ b/src/sqlbuild/compiler/sql_analysis/_helpers/scanning.py @@ -231,50 +231,6 @@ def iter_code_positions_impl( index += 1 -def skip_ignorable_impl( - *, sql: str, start: int, context: str = "SQL", syntax: SqlLexicalSyntax | None = None -) -> int: - """Return the first offset at or after `start` that is not whitespace or a comment.""" - - index: int = start - while index < len(sql): - if sql[index].isspace(): - index += 1 - continue - if sql[index] in SQL_TEXT_START_CHARACTERS: - return index - comment_end: int | None = _non_code_end( - sql=sql, index=index, context=context, syntax=syntax - ) - if comment_end is None: - return index - index = comment_end - return index - - -def strip_ignorable_impl( - *, sql: str, context: str = "SQL", syntax: SqlLexicalSyntax | None = None -) -> str: - """Return the SQL without leading or trailing whitespace and comments.""" - - code_start: int = skip_ignorable_impl(sql=sql, start=0, context=context, syntax=syntax) - code_end: int = code_start - index: int = code_start - while index < len(sql): - non_code_end: int | None = _non_code_end( - sql=sql, index=index, context=context, syntax=syntax - ) - if non_code_end is None: - index += 1 - if not sql[index - 1].isspace(): - code_end = index - continue - if sql[index] in SQL_TEXT_START_CHARACTERS: - code_end = non_code_end - index = non_code_end - return sql[code_start:code_end] - - def _non_code_end( *, sql: str, index: int, context: str, syntax: SqlLexicalSyntax | None ) -> int | None: @@ -287,15 +243,3 @@ def _non_code_end( if sql[index] in SQL_TEXT_START_CHARACTERS: return quoted_text_end_impl(sql=sql, start=index, context=context) return None - - -def is_identifier_start_impl(character: str) -> bool: - """Return whether a character can begin an SQL identifier.""" - - return character.isalpha() or character == SQL_IDENTIFIER_PREFIX - - -def is_identifier_character_impl(character: str) -> bool: - """Return whether a character can continue an SQL identifier.""" - - return character.isalnum() or character == SQL_IDENTIFIER_PREFIX diff --git a/src/sqlbuild/compiler/sql_analysis/constants.py b/src/sqlbuild/compiler/sql_analysis/constants.py index 7de538663f..240a115d0f 100644 --- a/src/sqlbuild/compiler/sql_analysis/constants.py +++ b/src/sqlbuild/compiler/sql_analysis/constants.py @@ -7,8 +7,6 @@ SQL_TEXT_START_CHARACTERS: frozenset[str] = frozenset({*SQL_QUOTE_CHARACTERS, "$"}) SQL_OPEN_PARENTHESIS: str = "(" SQL_CLOSE_PARENTHESIS: str = ")" -SQL_OPEN_BRACKET: str = "[" -SQL_CLOSE_BRACKET: str = "]" SQL_STRING_QUOTE_CHARACTER: str = "'" SQL_ESCAPE_CHARACTER: str = "\\" SQL_ESCAPE_STRING_PREFIX: str = "e" @@ -20,10 +18,8 @@ SUPPORTED_SQL_LINE_COMMENT_PREFIXES: frozenset[str] = frozenset({"--", "//", "#"}) SQL_BLOCK_COMMENT_OPEN: str = "/*" SQL_BLOCK_COMMENT_CLOSE: str = "*/" -SQL_DOLLAR_QUOTE_DELIMITER: str = "$$" SQL_DOLLAR_QUOTE_CHARACTER: str = "$" SQL_IDENTIFIER_PREFIX: str = "_" -SQL_NULL_KEYWORD: str = "NULL" SNOWFLAKE_DIALECT_NAME: str = "snowflake" POLYGLOT_ANALYZE_QUERY_ENTRY_POINT: str = "analyze_query" POLYGLOT_ANALYZE_QUERY_OPTIONS_ARGUMENT_COUNT: int = 2 @@ -36,143 +32,35 @@ POLYGLOT_SITE_RECORD_PREFIX: str = "polyglot-sites-" BINDING_UNKNOWN_TABLE_INTERNAL_CODE: str = "B000" -POLYGLOT_KIND_ALIAS: str = "alias" -POLYGLOT_KIND_AND: str = "and" POLYGLOT_KIND_ANNOTATED: str = "annotated" -POLYGLOT_KIND_ARRAY_AGG: str = "array_agg" -POLYGLOT_KIND_AVG: str = "avg" -POLYGLOT_KIND_BOOLEAN: str = "boolean" -POLYGLOT_KIND_CASE: str = "case" -POLYGLOT_KIND_CAST: str = "cast" -POLYGLOT_KIND_COALESCE: str = "coalesce" POLYGLOT_KIND_COLUMN: str = "column" -POLYGLOT_KIND_CONCAT: str = "concat" -POLYGLOT_KIND_COUNT: str = "count" POLYGLOT_KIND_EXCEPT: str = "except" -POLYGLOT_KIND_FUNCTION: str = "function" -POLYGLOT_KIND_IF_FUNC: str = "if_func" POLYGLOT_KIND_INTERSECT: str = "intersect" -POLYGLOT_KIND_IS_NULL: str = "is_null" -POLYGLOT_KIND_LITERAL: str = "literal" -POLYGLOT_KIND_MAX: str = "max" -POLYGLOT_KIND_MIN: str = "min" -POLYGLOT_KIND_NULL: str = "null" -POLYGLOT_KIND_PAREN: str = "paren" POLYGLOT_KIND_SELECT: str = "select" -POLYGLOT_KIND_STRING_AGG: str = "string_agg" -POLYGLOT_KIND_SUBSTRING: str = "substring" -POLYGLOT_KIND_SUM: str = "sum" POLYGLOT_KIND_TABLE: str = "table" -POLYGLOT_KIND_TIMESTAMP: str = "timestamp" -POLYGLOT_KIND_TRY_CAST: str = "try_cast" POLYGLOT_KIND_UNION: str = "union" -POLYGLOT_KIND_WINDOW_FUNCTION: str = "window_function" -POLYGLOT_KIND_WITHIN_GROUP: str = "within_group" -POLYGLOT_BOOLEAN_RESULT_KINDS: frozenset[str] = frozenset( - { - POLYGLOT_KIND_BOOLEAN, - "and", - "between", - "eq", - "exists", - "gt", - "gte", - "ilike", - "in", - "is", - POLYGLOT_KIND_IS_NULL, - "like", - "lt", - "lte", - "neq", - "not", - "or", - "regexp_like", - } -) POLYGLOT_SET_OPERATION_KINDS: frozenset[str] = frozenset( {POLYGLOT_KIND_UNION, POLYGLOT_KIND_INTERSECT, POLYGLOT_KIND_EXCEPT} ) -POLYGLOT_CAST_KINDS: frozenset[str] = frozenset({POLYGLOT_KIND_CAST, POLYGLOT_KIND_TRY_CAST}) -POLYGLOT_TYPE_PASSTHROUGH_KINDS: frozenset[str] = frozenset( - { - POLYGLOT_KIND_MAX, - POLYGLOT_KIND_MIN, - POLYGLOT_KIND_WINDOW_FUNCTION, - POLYGLOT_KIND_WITHIN_GROUP, - } -) -POLYGLOT_AGGREGATE_KINDS: frozenset[str] = frozenset( - { - POLYGLOT_KIND_AVG, - POLYGLOT_KIND_COUNT, - POLYGLOT_KIND_MAX, - POLYGLOT_KIND_MIN, - POLYGLOT_KIND_SUM, - POLYGLOT_KIND_ARRAY_AGG, - POLYGLOT_KIND_STRING_AGG, - } -) -POLYGLOT_PAYLOAD_ALIAS: str = "alias" POLYGLOT_PAYLOAD_COLUMN: str = "column" -POLYGLOT_PAYLOAD_DATA_TYPE: str = "data_type" -POLYGLOT_VARCHAR_DATA_TYPES: frozenset[str] = frozenset({"var_char", "varchar"}) -POLYGLOT_PAYLOAD_FROM: str = "from" -POLYGLOT_PAYLOAD_LEFT: str = "left" -POLYGLOT_PAYLOAD_EXPRESSIONS: str = "expressions" -POLYGLOT_PAYLOAD_JOINS: str = "joins" -POLYGLOT_PAYLOAD_KIND: str = "kind" -POLYGLOT_PAYLOAD_LITERAL_TYPE: str = "literal_type" POLYGLOT_PAYLOAD_NAME: str = "name" -POLYGLOT_PAYLOAD_NOT: str = "not" -POLYGLOT_PAYLOAD_PRECISION: str = "precision" -POLYGLOT_PAYLOAD_SCALE: str = "scale" -POLYGLOT_PAYLOAD_SELECT: str = "select" -POLYGLOT_PAYLOAD_RIGHT: str = "right" -POLYGLOT_PAYLOAD_TABLE: str = "table" -POLYGLOT_PAYLOAD_THIS: str = "this" -POLYGLOT_PAYLOAD_WHERE_CLAUSE: str = "where_clause" -POLYGLOT_PAYLOAD_TIMEZONE: str = "timezone" -POLYGLOT_PAYLOAD_TO: str = "to" -TIMESTAMP_WITH_TIME_ZONE_SQL_TYPE_NAME: str = "TIMESTAMPTZ" -POLYGLOT_JOIN_FULL: str = "FULL" -POLYGLOT_JOIN_LEFT: str = "LEFT" -POLYGLOT_JOIN_RIGHT: str = "RIGHT" -POLYGLOT_LITERAL_TYPE_STRING: str = "string" -POLYGLOT_NULLIF_FUNCTION_NAME: str = "NULLIF" -POLYGLOT_BINARY_OPERAND_COUNT: int = 2 -POLYGLOT_ANALYSIS_BASE_TABLES: str = "baseTables" -POLYGLOT_ANALYSIS_CAST_TYPE: str = "castType" -POLYGLOT_ANALYSIS_COLUMN_USES: str = "columnUses" -POLYGLOT_ANALYSIS_CONTEXT: str = "context" -POLYGLOT_ANALYSIS_CONTEXT_FILTER: str = "filter" -POLYGLOT_ANALYSIS_EXPRESSION_SQL: str = "expressionSql" POLYGLOT_ANALYSIS_IS_STAR: str = "isStar" POLYGLOT_ANALYSIS_NAME: str = "name" POLYGLOT_ANALYSIS_NULLABILITY: str = "nullability" POLYGLOT_ANALYSIS_NULLABILITY_NON_NULL: str = "non_null" POLYGLOT_ANALYSIS_NULLABILITY_NULLABLE: str = "nullable" POLYGLOT_ANALYSIS_PROJECTIONS: str = "projections" -POLYGLOT_ANALYSIS_RELATIONS: str = "relations" -POLYGLOT_ANALYSIS_SHAPE: str = "shape" POLYGLOT_ANALYSIS_SOURCE_ALIAS: str = "sourceAlias" POLYGLOT_ANALYSIS_SOURCE_CONFIDENCE: str = "confidence" POLYGLOT_ANALYSIS_SOURCE_NAME: str = "sourceName" POLYGLOT_ANALYSIS_TABLE: str = "table" POLYGLOT_ANALYSIS_TRANSFORM_KIND: str = "transformKind" -POLYGLOT_ANALYSIS_TRANSFORM_FUNCTION: str = "transformFunction" -POLYGLOT_ANALYSIS_FUNCTION_NAME: str = "name" POLYGLOT_ANALYSIS_STAR_PROJECTIONS: str = "starProjections" -POLYGLOT_ANALYSIS_TYPE_HINT: str = "typeHint" POLYGLOT_ANALYSIS_UPSTREAM: str = "upstream" -POLYGLOT_ANALYSIS_SHAPE_SELECT: str = "select" -POLYGLOT_ANALYSIS_SHAPE_SET_OPERATION: str = "set_operation" POLYGLOT_ANALYSIS_TRANSFORM_AGGREGATION: str = "aggregation" POLYGLOT_ANALYSIS_TRANSFORM_CAST: str = "cast" POLYGLOT_ANALYSIS_TRANSFORM_CONSTANT: str = "constant" POLYGLOT_ANALYSIS_TRANSFORM_DIRECT: str = "direct" -POLYGLOT_ANALYSIS_TRANSFORM_STAR: str = "star" -POLYGLOT_ANALYSIS_UNSAFE_TRANSFORMS: frozenset[str] = frozenset() TYPE_CHECKED_DIALECTS: frozenset[str] = frozenset({"duckdb", "snowflake", "postgresql", "bigquery"}) SQL_QUOTED_IDENTIFIER_DELIMITER: str = '"' CASE_SENSITIVE_BINDING_DIALECTS: frozenset[str] = frozenset({"snowflake", "postgresql"}) @@ -183,3 +71,5 @@ "sqlserver": "tsql", } ANALYSIS_NORMALIZATION_CHUNK_SIZE: int = 256 +TABLE_FUNCTION_ANALYSIS_PREFIX: str = "__sqlbuild_table_function_" +NATIVE_FAILURE_PREFIX: str = "NativeCompilerError: " diff --git a/src/sqlbuild/compiler/sql_analysis/main/_is_identifier_character.py b/src/sqlbuild/compiler/sql_analysis/main/_is_identifier_character.py deleted file mode 100644 index 69f0707cb9..0000000000 --- a/src/sqlbuild/compiler/sql_analysis/main/_is_identifier_character.py +++ /dev/null @@ -1,9 +0,0 @@ -"""SQL identifier character classification entrypoint.""" - -from sqlbuild.compiler.sql_analysis._helpers.scanning import is_identifier_character_impl - - -def is_identifier_character(character: str) -> bool: - """Return whether a character can continue an SQL identifier.""" - - return is_identifier_character_impl(character) diff --git a/src/sqlbuild/compiler/sql_analysis/main/_is_identifier_start.py b/src/sqlbuild/compiler/sql_analysis/main/_is_identifier_start.py deleted file mode 100644 index feb399f26f..0000000000 --- a/src/sqlbuild/compiler/sql_analysis/main/_is_identifier_start.py +++ /dev/null @@ -1,9 +0,0 @@ -"""SQL identifier start classification entrypoint.""" - -from sqlbuild.compiler.sql_analysis._helpers.scanning import is_identifier_start_impl - - -def is_identifier_start(character: str) -> bool: - """Return whether a character can begin an SQL identifier.""" - - return is_identifier_start_impl(character) diff --git a/src/sqlbuild/compiler/sql_test_glue/_helpers/assembly.py b/src/sqlbuild/compiler/sql_test_glue/_helpers/assembly.py index cb452078f9..c3b1d80537 100644 --- a/src/sqlbuild/compiler/sql_test_glue/_helpers/assembly.py +++ b/src/sqlbuild/compiler/sql_test_glue/_helpers/assembly.py @@ -2,6 +2,7 @@ from __future__ import annotations +from dataclasses import replace from pathlib import Path from sqlbuild.compiler.compile.constants import SQL_TEST_HELPER_REFERENCE_CODE @@ -21,8 +22,7 @@ DiagnosticPhase, DiagnosticSeverity, ) -from sqlbuild.compiler.sql_test_glue._helpers.deferrals import record_sql_test_assembly_deferral -from sqlbuild.compiler.sql_test_glue.models import NativeSqlTestAssembly +from sqlbuild.compiler.sql_test_glue.models import NativeSqlTestAssembly, NativeSqlTestFailure from sqlbuild.compiler.sql_test_glue.types import ( NativeSqlTestAssemblyRow, NativeSqlTestDiagnosticRow, @@ -33,16 +33,23 @@ def native_sql_test_assemblies( *, test_inputs: tuple[CompileSqlTestInput, ...], rows: list[NativeSqlTestAssemblyRow] -) -> tuple[NativeSqlTestAssembly | None, ...]: - """One assembly per test input, or None, recorded, where the native assembly defers.""" +) -> tuple[NativeSqlTestAssembly, ...]: + """One assembly per test input, with the error its assembly raises, if any.""" - assemblies: list[NativeSqlTestAssembly | None] = [] - for test_input, (facts, deferral) in zip(test_inputs, rows, strict=True): + assemblies: list[NativeSqlTestAssembly] = [] + for test_input, (facts, failure_row) in zip(test_inputs, rows, strict=True): + failure: NativeSqlTestFailure | None = ( + None + if failure_row is None + else NativeSqlTestFailure(kind=failure_row[0], message=failure_row[1]) + ) if facts is None: - record_sql_test_assembly_deferral(kind=str(deferral)) - assemblies.append(None) + assemblies.append(NativeSqlTestAssembly(test=None, diagnostics=(), failure=failure)) continue - assemblies.append(native_sql_test_assembly(test_input=test_input, facts=facts)) + assembled: NativeSqlTestAssembly = native_sql_test_assembly( + test_input=test_input, facts=facts + ) + assemblies.append(replace(assembled, failure=failure)) return tuple(assemblies) diff --git a/src/sqlbuild/compiler/sql_test_glue/_helpers/deferrals.py b/src/sqlbuild/compiler/sql_test_glue/_helpers/deferrals.py deleted file mode 100644 index bf25fb8907..0000000000 --- a/src/sqlbuild/compiler/sql_test_glue/_helpers/deferrals.py +++ /dev/null @@ -1,24 +0,0 @@ -"""Debug-only record of SQL tests the native assembly hands back to Python.""" - -from __future__ import annotations - -import json -import os -from pathlib import Path - -from sqlbuild.compiler.lineage.constants import ANALYSIS_DEFERRAL_RECORD_PREFIX -from sqlbuild.compiler.sql_analysis.constants import ANALYSIS_RECORD_DIR_ENV_VAR -from sqlbuild.compiler.sql_test_glue.constants import SQL_TEST_ASSEMBLY_DEFERRAL_SITE - - -def record_sql_test_assembly_deferral(*, kind: str) -> None: - """Append one `{"kind", "site"}` line when the analysis record directory is set.""" - - directory: str | None = os.environ.get(ANALYSIS_RECORD_DIR_ENV_VAR) - if not directory: - return - target: Path = Path(directory) - target.mkdir(parents=True, exist_ok=True) - record: str = json.dumps({"kind": kind, "site": SQL_TEST_ASSEMBLY_DEFERRAL_SITE}) - with open(target / f"{ANALYSIS_DEFERRAL_RECORD_PREFIX}{os.getpid()}.jsonl", "a") as handle: - _ = handle.write(record + "\n") diff --git a/src/sqlbuild/compiler/sql_test_glue/constants.py b/src/sqlbuild/compiler/sql_test_glue/constants.py index 8c14439660..78d8b5b284 100644 --- a/src/sqlbuild/compiler/sql_test_glue/constants.py +++ b/src/sqlbuild/compiler/sql_test_glue/constants.py @@ -3,4 +3,6 @@ from __future__ import annotations CURSOR_INTRINSIC_NAMES: tuple[str, ...] = ("__cursor_start", "__cursor_end") -SQL_TEST_ASSEMBLY_DEFERRAL_SITE: str = "sql_test_assembly" +SQL_TEST_INPUT_FAILURE: str = "input" +SQL_TEST_DECIMAL_OVERFLOW: str = "decimal_overflow" +SQL_TEST_EXTENSION_CALLBACK: str = "extension_callback" diff --git a/src/sqlbuild/compiler/sql_test_glue/main/_assemble_native_sql_tests.py b/src/sqlbuild/compiler/sql_test_glue/main/_assemble_native_sql_tests.py index 30b1e4dd08..b40a25cde0 100644 --- a/src/sqlbuild/compiler/sql_test_glue/main/_assemble_native_sql_tests.py +++ b/src/sqlbuild/compiler/sql_test_glue/main/_assemble_native_sql_tests.py @@ -12,10 +12,8 @@ from sqlbuild.compiler.sql_test_glue.types import NativeSqlTestAssemblyRow -def assemble_native_sql_tests( - *, inputs: CompileProjectInputs -) -> tuple[NativeSqlTestAssembly | None, ...]: - """Return one assembly per test input, or None for each test Python must assemble.""" +def assemble_native_sql_tests(*, inputs: CompileProjectInputs) -> tuple[NativeSqlTestAssembly, ...]: + """Return one assembly per test input, with the error its assembly raises, if any.""" rows: list[NativeSqlTestAssemblyRow] = native_module.assemble_compiled_sql_tests( NativeSqlTestAssemblyRequest( diff --git a/src/sqlbuild/compiler/sql_test_glue/models.py b/src/sqlbuild/compiler/sql_test_glue/models.py index 69403cb491..69d1bdc130 100644 --- a/src/sqlbuild/compiler/sql_test_glue/models.py +++ b/src/sqlbuild/compiler/sql_test_glue/models.py @@ -11,6 +11,7 @@ CompilerDiagnostic, CompileSqlTestInput, ) +from sqlbuild.compiler.sql_test_glue.types import SqlTestAssemblyFailureKind @dataclass(frozen=True) @@ -49,9 +50,18 @@ class NativeSqlTestAssemblyRequest: lexical_syntax: dict[str, object] +@dataclass(frozen=True) +class NativeSqlTestFailure: + """The error one test's assembly raises: its kind and message.""" + + kind: SqlTestAssemblyFailureKind + message: str + + @dataclass(frozen=True) class NativeSqlTestAssembly: - """One natively assembled test and the keyed diagnostics to report before it.""" + """One natively assembled test, its keyed diagnostics, and the error its assembly raises.""" - test: CompiledSqlTest + test: CompiledSqlTest | None diagnostics: tuple[tuple[tuple[str, ...], CompilerDiagnostic], ...] + failure: NativeSqlTestFailure | None = None diff --git a/src/sqlbuild/compiler/sql_test_glue/types.py b/src/sqlbuild/compiler/sql_test_glue/types.py index 3e995450c1..d8bc6a8a6d 100644 --- a/src/sqlbuild/compiler/sql_test_glue/types.py +++ b/src/sqlbuild/compiler/sql_test_glue/types.py @@ -2,6 +2,8 @@ from __future__ import annotations +from typing import Literal + type CtePairRow = tuple[str, str] type NativeChainStepRow = tuple[ str, @@ -31,4 +33,7 @@ str, list[NativeSqlTestDiagnosticRow], ] -type NativeSqlTestAssemblyRow = tuple[NativeSqlTestFactsRow | None, str | None] +type SqlTestAssemblyFailureKind = Literal["input", "internal", "decimal_overflow"] +type NativeSqlTestAssemblyRow = tuple[ + NativeSqlTestFactsRow | None, tuple[SqlTestAssemblyFailureKind, str] | None +] diff --git a/src/sqlbuild/executor/testing/types.py b/src/sqlbuild/executor/testing/types.py index 3a1d96b2e7..f26fb0dea4 100644 --- a/src/sqlbuild/executor/testing/types.py +++ b/src/sqlbuild/executor/testing/types.py @@ -11,10 +11,6 @@ class NativeSqlTestRenderingModule(Protocol): def render_sql_test_comparisons_json(self, request_json: str) -> str: ... - def plan_and_render_sql_tests_json(self, request_json: str) -> str: ... - - def resolve_sql_test_chains_json(self, request_json: str) -> str: ... - def render_sql_test_difference_sample_json(self, request_json: str) -> str: ... diff --git a/src/sqlbuild/sql_values/main/identity.py b/src/sqlbuild/sql_values/main/identity.py deleted file mode 100644 index 8ba2ccddff..0000000000 --- a/src/sqlbuild/sql_values/main/identity.py +++ /dev/null @@ -1,10 +0,0 @@ -"""Public entry point for typed SQL value identity.""" - -from sqlbuild.sql_values._helpers.normalization import sql_value_identity as _sql_value_identity -from sqlbuild.sql_values.models import SqlValue - - -def sql_value_identity(*, value: SqlValue) -> tuple[object, ...]: - """Return the normalized typed identity of a SQL value.""" - - return _sql_value_identity(value=value) diff --git a/tests/conftest.py b/tests/conftest.py index ad1fd020f1..2427d418f2 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -7,7 +7,6 @@ import pytest from sqlbuild.cli.compile_reuse.constants import REUSE_DISABLE_ENV_VAR, REUSE_DISABLE_VALUE -from sqlbuild.compiler.frontier.constants import COMPILER_ENGINE_ENV_VAR def pytest_configure(config: pytest.Config) -> None: @@ -15,10 +14,3 @@ def pytest_configure(config: pytest.Config) -> None: del config os.environ.setdefault(REUSE_DISABLE_ENV_VAR, REUSE_DISABLE_VALUE) - - -@pytest.fixture -def python_compiler_engine(monkeypatch: pytest.MonkeyPatch) -> None: - """Compile with the Python engine, for tests observing its analysis and planning internals.""" - - monkeypatch.setenv(COMPILER_ENGINE_ENV_VAR, "python") diff --git a/tests/e2e/scripts/compile_performance_ratio/test_compare_compile_performance.py b/tests/e2e/scripts/compile_performance_ratio/test_compare_compile_performance.py index 4faf2e6433..36d9e53d8e 100644 --- a/tests/e2e/scripts/compile_performance_ratio/test_compare_compile_performance.py +++ b/tests/e2e/scripts/compile_performance_ratio/test_compare_compile_performance.py @@ -173,12 +173,12 @@ def test_given_base_root_when_comparing_compile_performance_then_each_side_uses_ "test_case", ( EnginePhaseRatioTestCase( - description="native-preview contracts within a generous limit of python's", + description="native-preview contracts within a generous limit of native's", max_ratio="1000", phase_noise_floor_ms="1000", expected_return_code=0, expected_fragments=( - "Engines: base `python`, head `native-preview`.", + "Engines: base `native`, head `native-preview`.", "Gated phases: contracts_cpu_ms.", "| contracts_cpu_ms |", "**Result: passed.**", @@ -245,7 +245,7 @@ def test_given_two_engines_when_gating_a_phase_then_enforces_only_that_phase( "--head-python", sys.executable, "--base-engine", - "python", + "native", "--head-engine", "native-preview", "--gate-phase", diff --git a/tests/e2e/scripts/compiler_differential/_test_types.py b/tests/e2e/scripts/compiler_differential/_test_types.py index 0369dcd081..fd86575f11 100644 --- a/tests/e2e/scripts/compiler_differential/_test_types.py +++ b/tests/e2e/scripts/compiler_differential/_test_types.py @@ -19,19 +19,6 @@ class HarnessRunTestCase: expected_absent: tuple[str, ...] -@dataclass(frozen=True) -class SharedAnalysisSeedTestCase: - """A generated seed that must compile cleanly and reuse shared analyses.""" - - description: str - seed: int - expected_lines: tuple[str, ...] - expected_capture_sides: tuple[str, ...] - expected_compile_exit_code: int - expected_minimum_shareable_members: int - expected_minimum_shared_reuse: int - - @dataclass(frozen=True) class ProjectExpectationTestCase: """A broken project run with one --expect value and the verdict the harness must reach.""" diff --git a/tests/e2e/scripts/compiler_differential/helpers.py b/tests/e2e/scripts/compiler_differential/helpers.py index f58bd67b3c..117529835c 100644 --- a/tests/e2e/scripts/compiler_differential/helpers.py +++ b/tests/e2e/scripts/compiler_differential/helpers.py @@ -99,36 +99,14 @@ def _perturbed(self, **changes): _record.write(json.dumps({"kind": "legacy_fallback", "site": "orders.sql"}) + "\\n") """ -MACRO_RESOLUTION_SABOTAGE: str = """ -from sqlbuild.compiler.macro_bridge.classes.macro_bridge import MacroBridge +FALLBACK_RECORD_PERTURBATION: str = """ +from sqlbuild.compiler.frontier._helpers.process_recorder import process_recorder -MacroBridge.call_class = lambda self, **_: None +recorder = process_recorder() +if recorder is not None: + recorder.record(site="analysis_session", kind="session") """ -MODEL_ANALYSIS_SABOTAGE: str = """ -import sqlbuild._native as native - -native.start_model_analysis_session = lambda *_args: None -""" - -_STAGE_DISABLE_SABOTAGE: str = """ -import sqlbuild.compiler.frontier.main.native_stage_enabled as enabled -from sqlbuild.compiler.frontier.types import NativeStage - -_original = enabled.native_stage_enabled -_disabled = {{{stages}}} -enabled.native_stage_enabled = lambda stage: stage not in _disabled and _original(stage) -""" - - -def stage_disable_sabotage(stages: tuple[str, ...]) -> str: - """A perturbation switching these native stages off, so their work runs in Python.""" - - return _STAGE_DISABLE_SABOTAGE.format( - stages=", ".join(f"NativeStage({stage!r})" for stage in stages) - ) - - _BROKEN_REF_FILES: dict[str, str] = { "sqlbuild_project.toml": ( 'name = "broken_orders"\nadapter = "duckdb"\n\n' @@ -193,28 +171,3 @@ def perturbation_arguments(directory: Path, *, source: str = _SITECUSTOMIZE) -> "--engine-env", f"native-preview:PYTHONPATH={write_native_perturbation(directory, source=source)}", ) - - -SHARED_ANALYSIS_SEED: int = 34 -COMPILED_PROJECT_CAPTURE: str = "0-compile/003-compiled_project.json" - - -def shared_analysis_seed_arguments(*, work_dir: Path, seed: int) -> list[str]: - """Harness arguments comparing one generated seed with itself, capturing every stage.""" - - return [ - "--jobs", - "1", - "--work-dir", - str(work_dir), - "--corpus", - "seeds", - "--seed-start", - str(seed), - "--seeds", - "1", - "--engines", - "python", - "python", - "--stage-captures", - ] diff --git a/tests/e2e/scripts/compiler_differential/test_compiler_differential.py b/tests/e2e/scripts/compiler_differential/test_compiler_differential.py index 72e273cd74..668aae3025 100644 --- a/tests/e2e/scripts/compiler_differential/test_compiler_differential.py +++ b/tests/e2e/scripts/compiler_differential/test_compiler_differential.py @@ -4,7 +4,6 @@ import json import re -import shutil from pathlib import Path import pytest @@ -14,28 +13,19 @@ CoverageFailureTestCase, HarnessRunTestCase, ProjectExpectationTestCase, - SharedAnalysisSeedTestCase, WheelSiteReportTestCase, ) from tests.e2e.scripts.compiler_differential.helpers import ( CATALOG_PERTURBATION, - COMPILED_PROJECT_CAPTURE, DEFERRAL_PERTURBATION, DISCOVERY_PERTURBATION, NATIVE_ONLY_STDERR_LINE, RENDER_PERTURBATION, - SHARED_ANALYSIS_SEED, harness_arguments, perturbation_arguments, - shared_analysis_seed_arguments, write_broken_ref_project, write_failure_case_project, ) -from tests.integration.src.sqlbuild.compiler.pipeline.helpers import ( - CompiledProjectRun, - compiled_project_capture, - use_wave_analysis, -) @pytest.mark.parametrize( @@ -47,7 +37,7 @@ expected_exit_code=0, expected_lines=( "OK project/waffle_shop", - "Compiler differential passed: 1 projects identical (python vs native-preview)", + "Compiler differential passed: 1 projects identical (native vs native-preview)", ), expected_patterns=(), expected_absent=("DIFF",), @@ -338,62 +328,6 @@ def test_given_required_coverage_missing_when_comparing_then_harness_fails_and_s assert not any(text in output for text in test_case.expected_absent), output -@pytest.mark.parametrize( - "test_case", - [ - SharedAnalysisSeedTestCase( - description="shared_analysis_seed_against_itself", - seed=SHARED_ANALYSIS_SEED, - expected_lines=( - f"OK seed/{SHARED_ANALYSIS_SEED}", - "Compiler differential passed: 3 projects identical (python vs python)", - ), - expected_capture_sides=("left-python-captures", "right-python-captures"), - expected_compile_exit_code=0, - expected_minimum_shareable_members=1, - expected_minimum_shared_reuse=1, - ) - ], - ids=lambda case: case.description, -) -@pytest.mark.usefixtures("python_compiler_engine") -def test_given_python_engine_twice_when_capturing_stages_then_captures_are_identical( - test_case: SharedAnalysisSeedTestCase, - tmp_path: Path, - capsys: pytest.CaptureFixture[str], - monkeypatch: pytest.MonkeyPatch, -) -> None: - work_dir: Path = tmp_path / "work" - exit_code: int = run_compiler_differential( - shared_analysis_seed_arguments(work_dir=work_dir, seed=test_case.seed) - ) - output: str = capsys.readouterr().out - seed_dir: Path = work_dir / f"seed__{test_case.seed}" - project_dir: Path = Path(shutil.copytree(seed_dir / "source", tmp_path / "project")) - with monkeypatch.context() as waves_patch: - use_wave_analysis(waves_patch) - compiled: CompiledProjectRun = compiled_project_capture( - project_dir=project_dir, - capture_dir=tmp_path / "captures", - capsys=capsys, - monkeypatch=waves_patch, - ) - - assert (exit_code, all(line in output for line in test_case.expected_lines)) == (0, True), ( - output - ) - assert "DIFF" not in output, output - assert all( - (seed_dir / side / COMPILED_PROJECT_CAPTURE).is_file() - for side in test_case.expected_capture_sides - ), output - assert ( - compiled.exit_code, - compiled.shareable_members >= test_case.expected_minimum_shareable_members, - compiled.shared_reuse >= test_case.expected_minimum_shared_reuse, - ) == (test_case.expected_compile_exit_code, True, True), compiled - - @pytest.mark.parametrize( "test_case", [ @@ -437,19 +371,19 @@ def test_given_failure_expectation_when_code_is_not_the_first_error_then_harness "test_case", [ WheelSiteReportTestCase( - description="python_and_preview_wheel_calls_without_preview_deferrals", + description="native_and_preview_wheel_calls_without_preview_deferrals", perturbation="", expected_lines=( - "Polyglot wheel calls (python):", + "Polyglot wheel calls (native):", "Polyglot wheel calls (native-preview):", - "Analysis deferrals (python): none recorded", + "Analysis deferrals (native): none recorded", "Analysis deferrals (native-preview): none recorded", "Compiler differential passed: 1 projects identical", ), expected_sites=frozenset( { - "compiler/compile/_helpers/analysis/validation.py:" - "_validate_sql_syntax_with_message parse_one", + "compiler/compile/_helpers/analysis/required_columns.py:" + "resolve_required_external_columns parse_one", } ), expected_deferrals=frozenset(), @@ -458,7 +392,7 @@ def test_given_failure_expectation_when_code_is_not_the_first_error_then_harness description="preview_deferrals_are_counted_per_kind_and_site", perturbation=DEFERRAL_PERTURBATION, expected_lines=( - "Analysis deferrals (python): none recorded", + "Analysis deferrals (native): none recorded", "Analysis deferrals (native-preview):", " legacy_fallback orders.sql (project ", ), @@ -490,10 +424,10 @@ def test_given_wheel_site_report_when_comparing_then_sites_and_deferrals_are_rep preview: dict[str, dict[str, dict[str, int]]] = report["native-preview"] assert exit_code == 0, output assert all(line in output for line in test_case.expected_lines), output - assert test_case.expected_sites <= set(report["python"]["wheel_sites"]), report + assert test_case.expected_sites <= set(report["native"]["wheel_sites"]), report assert set(preview["deferrals"]) == test_case.expected_deferrals assert all(sum(by_corpus.values()) > 0 for by_corpus in preview["deferrals"].values()) - assert report["python"]["deferrals"] == {} + assert report["native"]["deferrals"] == {} if __name__ == "__main__": diff --git a/tests/e2e/scripts/compiler_differential/test_engine_error_cases.py b/tests/e2e/scripts/compiler_differential/test_engine_error_cases.py index 6cd931ccf1..0ba94842af 100644 --- a/tests/e2e/scripts/compiler_differential/test_engine_error_cases.py +++ b/tests/e2e/scripts/compiler_differential/test_engine_error_cases.py @@ -15,7 +15,7 @@ from scripts.compiler_differential.models import DifferentialOptions, EmittedCodes from tests.e2e.scripts.compiler_differential._test_types import EngineErrorCaseTestCase -_ENGINES: tuple[str, ...] = ("python", "native", "native-preview") +_ENGINES: tuple[str, ...] = ("native", "native-preview") @pytest.mark.parametrize( diff --git a/tests/e2e/scripts/compiler_differential/test_failure_corpus_codes.py b/tests/e2e/scripts/compiler_differential/test_failure_corpus_codes.py index 172a53588d..cb3524f5f4 100644 --- a/tests/e2e/scripts/compiler_differential/test_failure_corpus_codes.py +++ b/tests/e2e/scripts/compiler_differential/test_failure_corpus_codes.py @@ -32,7 +32,7 @@ "test_case", [ FailureCorpusCodesTestCase( - description="python_engine", + description="native_engine", expected_first_errors={ f"failure/{case.name}": case.expected_code for case in failure_cases() }, @@ -82,7 +82,7 @@ def test_given_failure_corpus_when_compiling_then_first_errors_match_and_cover_e ) -> None: emitted: dict[str, EmittedCodes] = emitted_failure_codes( options=DifferentialOptions( - engines=("python", "python"), + engines=("native", "native"), work_dir=tmp_path, jobs=4, stage_captures=False, diff --git a/tests/e2e/scripts/compiler_differential/test_golden_outputs.py b/tests/e2e/scripts/compiler_differential/test_golden_outputs.py index 493038863e..e19a229912 100644 --- a/tests/e2e/scripts/compiler_differential/test_golden_outputs.py +++ b/tests/e2e/scripts/compiler_differential/test_golden_outputs.py @@ -15,7 +15,13 @@ _CASE: str = "engine-error-week-date-cursor-start" _PROJECT: str = "orders" -_ENGINE_ARGUMENTS: tuple[str, ...] = ("--engines", "python", "native", "--expect", "failure:P001") +_ENGINE_ARGUMENTS: tuple[str, ...] = ( + "--engines", + "native", + "native-preview", + "--expect", + "failure:P001", +) @pytest.mark.parametrize( @@ -32,8 +38,8 @@ golden_edit=("hour must be in 0..23", "hour must be in 1..24"), expected_exit_code=1, expected_lines=( - " - golden (python) at /commands/0/diagnostics/0/message", " - golden (native) at /commands/0/diagnostics/0/message", + " - golden (native-preview) at /commands/0/diagnostics/0/message", "Compiler differential FAILED: 1 of 1 projects differ", ), ), diff --git a/tests/e2e/scripts/compiler_differential/test_native_fallback_gate.py b/tests/e2e/scripts/compiler_differential/test_native_fallback_gate.py index 8899688f5d..ad31837751 100644 --- a/tests/e2e/scripts/compiler_differential/test_native_fallback_gate.py +++ b/tests/e2e/scripts/compiler_differential/test_native_fallback_gate.py @@ -1,4 +1,4 @@ -"""The fallback allow-list gate fails on sabotaged native stages and on stale entries.""" +"""The fallback allow-list gate fails on sabotaged native work and on stale entries.""" from __future__ import annotations @@ -9,26 +9,11 @@ from scripts.compiler_differential.main.differential import run_compiler_differential from tests.e2e.scripts.compiler_differential._test_types import NativeFallbackGateTestCase from tests.e2e.scripts.compiler_differential.helpers import ( - MACRO_RESOLUTION_SABOTAGE, - MODEL_ANALYSIS_SABOTAGE, + FALLBACK_RECORD_PERTURBATION, harness_arguments, - stage_disable_sabotage, write_native_perturbation, ) -_WAFFLE_SHOP_NATIVE_STAGES: tuple[str, ...] = ( - "attachments", - "contracts", - "lineage_facts", - "macro_call_store", - "macro_calls", - "model_analysis", - "semantic_checks", -) -_ANSWER_VANISHED: str = "native no longer answers here, so this work now runs in Python" -_FALLBACK_WITHOUT_ANSWERS: str = ( - "fallback disappeared but native answers did not appear; the stage may be switched off" -) _VANISHED_ENTRY: str = ( '\n[[entry]]\nengine = "native-preview"\nstage = "macro_calls"\n' 'site = "macro_calls.resolution"\nkind = "deferred"\ncounts = { project = 1 }\n' @@ -46,60 +31,27 @@ expected_lines=("Compiler differential passed: 1 projects identical",), ), NativeFallbackGateTestCase( - description="entry_that_no_longer_occurs_without_new_native_answers_fails", + description="entry_that_no_longer_occurs_fails", perturbation="", appended_entries=_VANISHED_ENTRY, expected_exit_code=1, expected_lines=( "Native fallback allow-list: native-preview macro_calls " - f"macro_calls.resolution deferred (project): {_FALLBACK_WITHOUT_ANSWERS}", - ), - ), - NativeFallbackGateTestCase( - description="shipped_macro_resolution_sabotaged_to_python_fails", - perturbation=MACRO_RESOLUTION_SABOTAGE, - appended_entries="", - expected_exit_code=1, - expected_lines=( - "Native fallback allow-list: native-preview macro_calls " - "macro_calls.resolution deferred (project): ", - "not on the allow-list; port it or list it with a reason", + "macro_calls.resolution deferred (project): listed but no longer occurs; remove it " + "from the allow-list", ), ), NativeFallbackGateTestCase( - description="preview_model_analysis_sabotaged_to_python_fails", - perturbation=MODEL_ANALYSIS_SABOTAGE, + description="unexpected_preview_fallback_record_fails", + perturbation=FALLBACK_RECORD_PERTURBATION, appended_entries="", expected_exit_code=1, expected_lines=( - "Native fallback allow-list: native-preview model_analysis analysis_session " + "Native fallback allow-list: native-preview analysis_session analysis_session " "session (project): ", "Compiler differential FAILED: 0 of 1 projects differ", ), ), - NativeFallbackGateTestCase( - description="shipped_stages_switched_to_python_fail", - perturbation=stage_disable_sabotage(("attachments", "macro_calls")), - appended_entries="", - expected_exit_code=1, - expected_lines=( - "Native fallback allow-list: native-preview attachments " - f"attachments.native seed_pairs (project): {_ANSWER_VANISHED}", - "Native fallback allow-list: native-preview macro_calls " - f"macro_calls.native bridged_calls (project): {_ANSWER_VANISHED}", - "Intended? Run `make compiler-baselines`", - ), - ), - NativeFallbackGateTestCase( - description="every_native_stage_switched_to_python_fails_by_name", - perturbation=stage_disable_sabotage(_WAFFLE_SHOP_NATIVE_STAGES), - appended_entries="", - expected_exit_code=1, - expected_lines=tuple( - f"Native fallback allow-list: native-preview {stage} {stage}.native " - for stage in _WAFFLE_SHOP_NATIVE_STAGES - ), - ), ], ids=lambda case: case.description, ) @@ -139,50 +91,5 @@ def test_given_recorded_allow_list_when_native_defers_more_or_less_then_the_gate assert all(line in output for line in test_case.expected_lines), output -@pytest.mark.parametrize( - "test_case", - [ - NativeFallbackGateTestCase( - description="sql_test_glue_switched_off_is_not_a_finished_port", - perturbation=stage_disable_sabotage(("sql_test_glue",)), - appended_entries="", - expected_exit_code=1, - expected_lines=( - "Native fallback allow-list: native-preview sql_test_glue sql_test_glue.native " - f"sql_test_assemblies (fixture): {_ANSWER_VANISHED}", - "Native fallback allow-list: native-preview sql_test_glue sql_test_glue.native " - f"sql_test_plans (fixture): {_ANSWER_VANISHED}", - "Native fallback allow-list: 2 problems", - ), - ), - ], - ids=lambda case: case.description, -) -def test_given_committed_allow_list_when_fallback_only_stage_is_switched_off_then_gate_refuses( - test_case: NativeFallbackGateTestCase, tmp_path: Path, capsys: pytest.CaptureFixture[str] -) -> None: - sabotage: Path = write_native_perturbation(tmp_path / "sabotage", source=test_case.perturbation) - _ = capsys.readouterr() - - exit_code: int = run_compiler_differential( - [ - "--corpus", - "fixtures", - "--jobs", - "2", - "--work-dir", - str(tmp_path / "check"), - "--native-fallbacks", - "check", - "--engine-env", - f"native-preview:PYTHONPATH={sabotage}", - ] - ) - - output: str = capsys.readouterr().out - assert exit_code == test_case.expected_exit_code, output - assert all(line in output for line in test_case.expected_lines), output - - if __name__ == "__main__": pytest.main([__file__, "-vv"]) diff --git a/tests/e2e/scripts/compiler_differential/test_reference_differential.py b/tests/e2e/scripts/compiler_differential/test_reference_differential.py index fb4140add6..af0b4613e1 100644 --- a/tests/e2e/scripts/compiler_differential/test_reference_differential.py +++ b/tests/e2e/scripts/compiler_differential/test_reference_differential.py @@ -42,7 +42,7 @@ expected_exit_code=0, expected_lines=( "OK project/table_function_orders", - "Compiler differential passed: 1 projects identical (python vs native-preview)", + "Compiler differential passed: 1 projects identical (native vs native-preview)", ), expected_patterns=(), expected_absent=("DIFF",), diff --git a/tests/e2e/scripts/compiler_differential/test_scope_differential.py b/tests/e2e/scripts/compiler_differential/test_scope_differential.py index 5a3032b21d..a0f0bec182 100644 --- a/tests/e2e/scripts/compiler_differential/test_scope_differential.py +++ b/tests/e2e/scripts/compiler_differential/test_scope_differential.py @@ -53,18 +53,7 @@ expected_exit_code=0, expected_lines=( "OK project/scoped_orders", - "Compiler differential passed: 1 projects identical (python vs native-preview)", - ), - expected_patterns=(), - expected_absent=("DIFF",), - ), - HarnessRunTestCase( - description="shipped_native_stages_only", - extra_arguments=("--engines", "python", "native"), - expected_exit_code=0, - expected_lines=( - "OK project/scoped_orders", - "Compiler differential passed: 1 projects identical (python vs native)", + "Compiler differential passed: 1 projects identical (native vs native-preview)", ), expected_patterns=(), expected_absent=("DIFF",), diff --git a/tests/e2e/src/sqlbuild/cli/commands/main/build/test_model_config_engines.py b/tests/e2e/src/sqlbuild/cli/commands/main/build/test_model_config_engines.py index d3e3ae5bfe..0e09890c18 100644 --- a/tests/e2e/src/sqlbuild/cli/commands/main/build/test_model_config_engines.py +++ b/tests/e2e/src/sqlbuild/cli/commands/main/build/test_model_config_engines.py @@ -87,30 +87,6 @@ @pytest.mark.parametrize( "test_case", [ - ModelConfigEnginesBuildE2ETestCase( - description="layered and templated config builds on python", - engine="python", - overrides={}, - expected_exit_code=0, - expected_output_fragments=_PASSING_FRAGMENTS, - expected_relations=_BUILT_RELATIONS, - ), - ModelConfigEnginesBuildE2ETestCase( - description="reversed cursor bounds are the Python error on python", - engine="python", - overrides=_REVERSED_CURSOR_BOUNDS, - expected_exit_code=1, - expected_output_fragments=_REVERSED_BOUNDS_FRAGMENTS, - expected_relations=(), - ), - ModelConfigEnginesBuildE2ETestCase( - description="a snapshot without a unique key is the Python error on python", - engine="python", - overrides=_SNAPSHOT_WITHOUT_KEY, - expected_exit_code=1, - expected_output_fragments=_SNAPSHOT_WITHOUT_KEY_FRAGMENTS, - expected_relations=(), - ), ModelConfigEnginesBuildE2ETestCase( description="layered and templated config builds on native", engine="native", @@ -120,7 +96,7 @@ expected_relations=_BUILT_RELATIONS, ), ModelConfigEnginesBuildE2ETestCase( - description="reversed cursor bounds are the Python error on native", + description="reversed cursor bounds are the expected error on native", engine="native", overrides=_REVERSED_CURSOR_BOUNDS, expected_exit_code=1, @@ -144,7 +120,7 @@ expected_relations=_BUILT_RELATIONS, ), ModelConfigEnginesBuildE2ETestCase( - description="reversed cursor bounds are the Python error on native-preview", + description="reversed cursor bounds are the expected error on native-preview", engine="native-preview", overrides=_REVERSED_CURSOR_BOUNDS, expected_exit_code=1, diff --git a/tests/e2e/src/sqlbuild/cli/commands/main/compile/_test_types.py b/tests/e2e/src/sqlbuild/cli/commands/main/compile/_test_types.py index b5e13f46ea..2b3efe39ea 100644 --- a/tests/e2e/src/sqlbuild/cli/commands/main/compile/_test_types.py +++ b/tests/e2e/src/sqlbuild/cli/commands/main/compile/_test_types.py @@ -792,22 +792,14 @@ class RetiredCompilerCacheTestCase: expected_removed: bool -@dataclass(frozen=True) -class DenseBatchedPreparationTestCase: - description: str - model_count: int - expected_exit_code: int - - type DensePreparedCompile = PreparedCompile @dataclass(frozen=True) class SharedCacheKeyTestCase: - """A model analysis schedule under which two models share one analysis cache key.""" + """Expected parity when identical SQL models share native cached analysis.""" description: str - schedule: Callable[[pytest.MonkeyPatch], None] expected_matches_uncached: bool = True @@ -822,18 +814,6 @@ class CompilerEngineParityTestCase: expected_exit_codes: tuple[int, int] -@dataclass(frozen=True) -class DefaultEngineParityTestCase: - """The Python oracle and the unset default compiling copies of one project, with stores.""" - - description: str - oracle_engine: str - default_engine: str - expected_engines: tuple[str, str] - expected_exit_codes: tuple[int, int] - expected_macro_call_stores: tuple[tuple[str, ...], tuple[str, ...]] - - @dataclass(frozen=True) class NativeTypeSystemTestCase: """Compiles of one project by each engine whose contracts compare types or fail.""" @@ -852,39 +832,6 @@ class NativeAnalysisSeamTestCase: expected_native_returns: dict[str, list[object]] -@dataclass(frozen=True) -class CompilerEngineMacroParityTestCase: - """Two engines compiling separate copies of one macro-heavy project.""" - - description: str - files: dict[str, str] - expected_exit_codes: tuple[int, int] - expected_compiled_fragments: tuple[str, ...] - - -@dataclass(frozen=True) -class CompilerEngineStoreTestCase: - """A sequence of engine compiles in one project and which of them reuse a stored compile.""" - - description: str - engines: tuple[str, ...] - expected_reused: tuple[bool, ...] - expected_python_stores: tuple[str, ...] - expected_native_stores: tuple[str, ...] - - -@dataclass(frozen=True) -class CompilerEngineRulesStoreTestCase: - """Compile plus Rules under each engine and the store files each engine must own.""" - - description: str - rules_selector: str - stores: tuple[str, ...] - native_marker: str - expected_python_files: tuple[str, ...] - expected_native_files: tuple[str, ...] - - @dataclass(frozen=True) class CompilerEngineTierStoreTestCase: """Alternating compiles under two native tiers and the stores each tier must own alone.""" @@ -896,19 +843,6 @@ class CompilerEngineTierStoreTestCase: expected_second_engine_stores: tuple[str, ...] -@dataclass(frozen=True) -class NativeModelConfigParityTestCase: - """Authored model config compiled by two engines that must report and write the same.""" - - description: str - project_files: dict[str, str] - project_config_replacements: tuple[tuple[str, str], ...] - environment: dict[str, str] - engines: tuple[str, str] - expected_exit_codes: tuple[int, int] - expected_report_text: str - - @dataclass(frozen=True) class ReplaceableReferenceCallTestCase: """A compiler engine that must build double-quoted reference calls end to end.""" @@ -929,17 +863,6 @@ class RejectedReferenceCallTestCase: expected_diagnostics: tuple[tuple[str, str, str, int, int, str], ...] -@dataclass(frozen=True) -class NativeModelLoopParityTestCase: - """Models whose declarations two engines must resolve, report and write the same way.""" - - description: str - project_files: dict[str, str] - engines: tuple[str, str] - expected_exit_codes: tuple[int, int] - expected_report_text: str - - @dataclass(frozen=True) class NativeDeclarationErrorTestCase: """A failing project whose declaration error both engines must report the same way.""" @@ -957,7 +880,7 @@ class ReferenceScanErrorTestCase: description: str project_files: dict[str, str] expected_message: str - expected_macro_calls: tuple[int, int, int] + expected_macro_calls: tuple[int, int] expected_error_types: tuple[str, ...] diff --git a/tests/e2e/src/sqlbuild/cli/commands/main/compile/attachment_errors/_test_types.py b/tests/e2e/src/sqlbuild/cli/commands/main/compile/attachment_errors/_test_types.py index 4b42c4ca3f..dbb25bfb0a 100644 --- a/tests/e2e/src/sqlbuild/cli/commands/main/compile/attachment_errors/_test_types.py +++ b/tests/e2e/src/sqlbuild/cli/commands/main/compile/attachment_errors/_test_types.py @@ -9,5 +9,5 @@ class NativeAttachmentErrorTestCase: description: str case_name: str - expected_macro_calls: tuple[int, int, int] - expected_error_types: tuple[str, str, str] + expected_macro_calls: tuple[int, int] + expected_error_types: tuple[str, str] diff --git a/tests/e2e/src/sqlbuild/cli/commands/main/compile/attachment_errors/test_native_attachment_errors.py b/tests/e2e/src/sqlbuild/cli/commands/main/compile/attachment_errors/test_native_attachment_errors.py index 3bf28e5ad2..38e5b9a7f8 100644 --- a/tests/e2e/src/sqlbuild/cli/commands/main/compile/attachment_errors/test_native_attachment_errors.py +++ b/tests/e2e/src/sqlbuild/cli/commands/main/compile/attachment_errors/test_native_attachment_errors.py @@ -24,7 +24,7 @@ write_project_file, ) -_ENGINES: tuple[str, ...] = ("python", "native", "native-preview") +_ENGINES: tuple[str, ...] = ("native", "native-preview") _CALL_LOG: str = "macro_calls.log" _COUNTED_MACRO: str = ( "from pathlib import Path\n\n\n" @@ -36,7 +36,7 @@ ' _ = log.write("call\\n")\n' " return expression\n" ) -_ERROR_TYPES: tuple[str, str, str] = ("CompileInputError", "CompileInputError", "CompileInputError") +_ERROR_TYPES: tuple[str, str] = ("CompileInputError", "CompileInputError") _CASES: dict[str, FailureCase] = {case.name: case for case in attachment_failure_cases()} @@ -46,55 +46,55 @@ NativeAttachmentErrorTestCase( description="an unknown audit run scope", case_name="generic-audit-unknown-run-scope", - expected_macro_calls=(1, 1, 1), + expected_macro_calls=(1, 1), expected_error_types=_ERROR_TYPES, ), NativeAttachmentErrorTestCase( description="an audit argument overriding the implicit model", case_name="generic-audit-overrides-implicit-model", - expected_macro_calls=(1, 1, 1), + expected_macro_calls=(1, 1), expected_error_types=_ERROR_TYPES, ), NativeAttachmentErrorTestCase( description="a cursor intrinsic in a generic audit reads expanded SQL", case_name="generic-audit-cursor-intrinsic", - expected_macro_calls=(1, 1, 1), + expected_macro_calls=(1, 1), expected_error_types=_ERROR_TYPES, ), NativeAttachmentErrorTestCase( description="an unknown project variable in audit SQL", case_name="audit-unknown-project-variable", - expected_macro_calls=(1, 1, 1), + expected_macro_calls=(1, 1), expected_error_types=_ERROR_TYPES, ), NativeAttachmentErrorTestCase( description="an unknown project variable inside doubled backticks in audit SQL", case_name="audit-variable-in-doubled-backticks", - expected_macro_calls=(1, 1, 1), + expected_macro_calls=(1, 1), expected_error_types=_ERROR_TYPES, ), NativeAttachmentErrorTestCase( description="a SQL function return type the adapter dialect cannot parse", case_name="sql-function-invalid-return-type", - expected_macro_calls=(1, 1, 1), + expected_macro_calls=(1, 1), expected_error_types=_ERROR_TYPES, ), NativeAttachmentErrorTestCase( description="a SQL function without returns", case_name="sql-function-missing-returns", - expected_macro_calls=(1, 1, 1), + expected_macro_calls=(1, 1), expected_error_types=_ERROR_TYPES, ), NativeAttachmentErrorTestCase( description="an unsupported template namespace in a function header", case_name="sql-function-template-namespace", - expected_macro_calls=(1, 1, 1), + expected_macro_calls=(1, 1), expected_error_types=_ERROR_TYPES, ), NativeAttachmentErrorTestCase( description="an unknown variable in a source description", case_name="source-description-unknown-variable", - expected_macro_calls=(1, 1, 1), + expected_macro_calls=(1, 1), expected_error_types=_ERROR_TYPES, ), ], @@ -136,7 +136,7 @@ def test_given_attachment_error_when_compiling_with_each_engine_then_errors_and_ tuple(macro_calls), tuple(error_types), ) == ( - (1, 1, 1), + (1, 1), True, True, True, @@ -145,8 +145,8 @@ def test_given_attachment_error_when_compiling_with_each_engine_then_errors_and_ test_case.expected_error_types, ), ( runs[0].report, - runs[2].report, - runs[2].stderr, + runs[1].report, + runs[1].stderr, ) diff --git a/tests/e2e/src/sqlbuild/cli/commands/main/compile/fast_lineage/_test_types.py b/tests/e2e/src/sqlbuild/cli/commands/main/compile/fast_lineage/_test_types.py index 3b48472302..76762a2cc5 100644 --- a/tests/e2e/src/sqlbuild/cli/commands/main/compile/fast_lineage/_test_types.py +++ b/tests/e2e/src/sqlbuild/cli/commands/main/compile/fast_lineage/_test_types.py @@ -11,5 +11,4 @@ class NativeFastLineageCliTestCase: files: dict[str, str] lineage_targets: tuple[str, ...] expected_lineage: dict[str, dict[str, object]] - expected_minimum_python_fallback_parses: int expected_minimum_traced_edges: int diff --git a/tests/e2e/src/sqlbuild/cli/commands/main/compile/fast_lineage/helpers.py b/tests/e2e/src/sqlbuild/cli/commands/main/compile/fast_lineage/helpers.py index e8d1fe7758..fab6ff3cec 100644 --- a/tests/e2e/src/sqlbuild/cli/commands/main/compile/fast_lineage/helpers.py +++ b/tests/e2e/src/sqlbuild/cli/commands/main/compile/fast_lineage/helpers.py @@ -3,31 +3,24 @@ import json import re import subprocess -from collections import Counter from itertools import product from pathlib import Path from typing import NamedTuple, cast from sqlbuild.cli.compile_reuse.constants import REUSE_DISABLE_ENV_VAR -from sqlbuild.compiler.lineage.constants import NATIVE_LINEAGE_DEFERRAL_SITE from sqlbuild.compiler.sql_analysis.constants import ANALYSIS_RECORD_DIR_ENV_VAR from tests.e2e.src.sqlbuild.cli.commands.main.compile.helpers import run_installed_sqb _TIMING: re.Pattern[str] = re.compile(r" \(\d+\.\d+s\)") _DIRECTIONS: tuple[str, ...] = ("upstream", "downstream") -FALLBACK_SITE: str = ( - "compiler/lineage/_helpers/fast_columns.py:_build_polyglot_fast_model_column_lineage" -) class EngineLineageRun(NamedTuple): - """One engine's compile report, lineage traces, wheel fallback parses and lineage deferrals.""" + """One engine's compile report and lineage traces.""" compile_report: str compile_returncode: int traces: list[tuple[int, str, str]] - fallback_parses: int - lineage_deferrals: int def engine_lineage_run( @@ -75,11 +68,6 @@ def engine_lineage_run( compile_report=json.dumps(report, indent=2), compile_returncode=compiled.returncode, traces=traces, - fallback_parses=_site_calls(record_dir)[FALLBACK_SITE], - lineage_deferrals=sum( - path.read_text("utf-8").count(f'"site": "{NATIVE_LINEAGE_DEFERRAL_SITE}"') - for path in record_dir.glob("analysis-deferrals-*.jsonl") - ), ) @@ -91,11 +79,3 @@ def model_lineage_summaries(compile_report: str) -> dict[str, object]: list[dict[str, object]], cast(dict[str, object], payload["resources"])["models"] ) return {str(model["name"]): model["lineage"] for model in models} - - -def _site_calls(record_dir: Path) -> Counter[str]: - calls: Counter[str] = Counter() - for path in record_dir.glob("polyglot-sites-*.json"): - for site, _, count in json.loads(path.read_text("utf-8"))["calls"]: - calls[site] += count - return calls diff --git a/tests/e2e/src/sqlbuild/cli/commands/main/compile/fast_lineage/test_native_fast_lineage.py b/tests/e2e/src/sqlbuild/cli/commands/main/compile/fast_lineage/test_native_fast_lineage.py index 1c472b1b45..f1a07bf755 100644 --- a/tests/e2e/src/sqlbuild/cli/commands/main/compile/fast_lineage/test_native_fast_lineage.py +++ b/tests/e2e/src/sqlbuild/cli/commands/main/compile/fast_lineage/test_native_fast_lineage.py @@ -1,4 +1,4 @@ -"""The native engines build fast column lineage natively with Python's exact CLI output.""" +"""Both native engines build fast column lineage natively with the expected CLI output.""" from __future__ import annotations @@ -15,7 +15,7 @@ model_lineage_summaries, ) -_ENGINES: tuple[str, ...] = ("python", "native", "native-preview") +_ENGINES: tuple[str, ...] = ("native", "native-preview") _PROJECT_FILES: dict[str, str] = { "sqlbuild_project.toml": ( 'name = "orders_lineage"\nadapter = "duckdb"\n\n[connection]\ndatabase = "orders.duckdb"\n' @@ -86,7 +86,6 @@ "has_star": True, } }, - expected_minimum_python_fallback_parses=2, expected_minimum_traced_edges=4, ), NativeFastLineageCliTestCase( @@ -107,7 +106,6 @@ "has_star": False, }, }, - expected_minimum_python_fallback_parses=2, expected_minimum_traced_edges=2, ), ], @@ -125,21 +123,18 @@ def test_given_project_when_compiling_with_each_engine_then_fast_lineage_output_ ) for engine in _ENGINES } - python: EngineLineageRun = runs["python"] - summaries: dict[str, object] = model_lineage_summaries(python.compile_report) + native: EngineLineageRun = runs["native"] + summaries: dict[str, object] = model_lineage_summaries(native.compile_report) - assert python.compile_returncode == 0, python.compile_report - assert [code for code, _, _ in python.traces] == [0] * len(python.traces) + assert native.compile_returncode == 0, native.compile_report + assert [code for code, _, _ in native.traces] == [0] * len(native.traces) assert {name: summaries[name] for name in test_case.expected_lineage} == ( test_case.expected_lineage ) - assert sum('"source"' in stdout for _, stdout, _ in python.traces) >= ( + assert sum('"source"' in stdout for _, stdout, _ in native.traces) >= ( test_case.expected_minimum_traced_edges ) - assert python.fallback_parses >= test_case.expected_minimum_python_fallback_parses - assert runs["native"]._replace(fallback_parses=python.fallback_parses) == python - assert runs["native-preview"]._replace(fallback_parses=python.fallback_parses) == python - assert (runs["native"].fallback_parses, runs["native-preview"].fallback_parses) == (0, 0) + assert runs["native-preview"] == native if __name__ == "__main__": diff --git a/tests/e2e/src/sqlbuild/cli/commands/main/compile/helpers.py b/tests/e2e/src/sqlbuild/cli/commands/main/compile/helpers.py index 591fd47e67..5f86309c58 100644 --- a/tests/e2e/src/sqlbuild/cli/commands/main/compile/helpers.py +++ b/tests/e2e/src/sqlbuild/cli/commands/main/compile/helpers.py @@ -35,8 +35,6 @@ import sqlbuild.cli.compile_reuse._helpers.attempt as reuse_attempt import sqlbuild.cli.compile_reuse._helpers.project_files as reuse_project_files import sqlbuild.cli.compile_reuse._helpers.store as reuse_store -import sqlbuild.compiler.compile._helpers.assembly.binding_waves as binding_waves -import sqlbuild.compiler.compile._helpers.assembly.project as project_assembly import sqlbuild.compiler.compile._helpers.diagnostics.recovery as diagnostic_recovery import sqlbuild.compiler.compile._helpers.macro_bridge.call_store as call_store_module import sqlbuild.compiler.compile._helpers.native_stages.assembly as native_stages @@ -76,7 +74,7 @@ from sqlbuild.compiler.frontier.constants import ( COMPILER_CACHE_DIRECTORY_NAME, COMPILER_ENGINE_ENV_VAR, - ENGINE_CACHE_NAMESPACE_SUFFIXES, + RETIRED_CACHE_NAMESPACE_SUFFIXES, ) from sqlbuild.compiler.frontier.main.compiler_cache_directory import compiler_cache_directory from sqlbuild.compiler.macro_bridge.constants import MACRO_CALL_STORE_FILE_NAME @@ -3880,19 +3878,6 @@ def twin_header_changed(root: Path) -> None: ) -def analyze_one_model_at_a_time(monkeypatch: pytest.MonkeyPatch) -> None: - """Run the binding dataflow with one worker taking one model at a time.""" - - for name in ("_DATAFLOW_WORKERS", "_DATAFLOW_BATCH_MIN", "_DATAFLOW_BATCH_LIMIT"): - monkeypatch.setattr(binding_waves, name, 1) - - -def analyze_in_one_batch(monkeypatch: pytest.MonkeyPatch) -> None: - """Analyze every model in one batch, without dependency-ordered binding.""" - - monkeypatch.setattr(project_assembly, "binding_schema_for_model", lambda **_kwargs: None) - - def star_chain_added(root: Path) -> None: """Add two models that each select every column of the one before, below staging orders.""" @@ -4215,7 +4200,7 @@ def write_retired_compiler_cache_files(project_dir: Path) -> tuple[Path, ...]: / f"{COMPILER_CACHE_DIRECTORY_NAME}{suffix}" / RETIRED_FACT_CACHE_DIRECTORY_NAME / "sql-tests.sqlite3" - for suffix in ENGINE_CACHE_NAMESPACE_SUFFIXES.values() + for suffix in RETIRED_CACHE_NAMESPACE_SUFFIXES ] written.extend( compiler_cache_directory(project_dir) / REUSE_ENTRY_DIRECTORY_NAME / name @@ -4293,20 +4278,6 @@ def ignore_project_changes(monkeypatch: pytest.MonkeyPatch) -> None: ) -def ignore_query_in_analysis_key(monkeypatch: pytest.MonkeyPatch) -> None: - """Key Python's cached model analyses without their query, so an edited query reads a stale - analysis; the Python engine runs, since native analysis keys its own cache.""" - - monkeypatch.setenv(COMPILER_ENGINE_ENV_VAR, "python") - analysis_key: Callable[..., str] = project_assembly.model_analysis_cache_key - - def query_blind_key(**kwargs: Any) -> str: - kwargs["query_sql"] = "" - return analysis_key(**kwargs) - - monkeypatch.setattr(project_assembly, "model_analysis_cache_key", query_blind_key) - - EXTERNAL_FLAVOR_MODULE: str = "extflavor" @@ -4406,23 +4377,6 @@ def engine_reuse_compile(*, project_dir: Path, engine: str) -> CompileReuseRun: return run_reuse_compile(project_dir=project_dir, global_args=("--compiler-engine", engine)) -def environment_engine_reuse_compile(*, project_dir: Path, engine: str) -> CompileReuseRun: - """Compile with reuse enabled under the engine the environment selects; empty means default.""" - - return run_reuse_compile(project_dir=project_dir, env={COMPILER_ENGINE_ENV_VAR: engine}) - - -def engine_compile_and_rules(*, project_dir: Path, engine: str, rules_selector: str) -> int: - """Compile and run Rules under one engine; return the Rules exit code.""" - - _ = engine_reuse_compile(project_dir=project_dir, engine=engine) - return run_installed_sqb( - project_dir=project_dir, - args=("--compiler-engine", engine, "rules", "run", rules_selector), - env=COMPILE_REUSE_ENV, - ).returncode - - def report_engine(run: CompileReuseRun) -> str: """Return the engine named in a JSON compile report.""" @@ -4991,11 +4945,10 @@ def engine_in_process_compile( class NativeTypeAnswers(NamedTuple): """What the native type system answered in one compile: each Python-side normalization, - contract results that compared at least one typed column, and contract handbacks.""" + and contract results that compared at least one typed column.""" normalized: list[bool] typed_comparisons: int - handbacks: int def type_system_engine_compile( @@ -5022,7 +4975,6 @@ def recorded(type_sql: str, dialect: str) -> object: def recorded_contracts(request: NativeContractRequest) -> list[NativeContractOutcome]: outcomes: list[NativeContractOutcome] = evaluate_contracts(request) contract_statuses.update(native_contract_statuses(request=request, outcomes=outcomes)) - contract_statuses["handbacks"] += sum(deferral is not None for deferral, _ in outcomes) return outcomes type_normalization.normalize_type.cache_clear() @@ -5036,7 +4988,6 @@ def recorded_contracts(request: NativeContractRequest) -> list[NativeContractOut return run, NativeTypeAnswers( normalized=normalized, typed_comparisons=contract_statuses["typed_comparisons"], - handbacks=contract_statuses["handbacks"], ) @@ -5087,20 +5038,6 @@ def fallback(**_kwargs: object) -> object: return run, called -def python_engine_compile( - *, project_dir: Path, monkeypatch: pytest.MonkeyPatch, capsys: pytest.CaptureFixture[str] -) -> CompileReuseRun: - """Compile under the Python engine in this process.""" - - with monkeypatch.context() as patch: - for variable, value in { - COMPILER_ENGINE_ENV_VAR: "python", - REUSE_DISABLE_ENV_VAR: "1", - }.items(): - patch.setenv(variable, value) - return in_process_reuse_run(project_dir=project_dir, capsys=capsys) - - def write_counted_error_project(*, project_dir: Path, files: dict[str, str]) -> None: """Write the failure base project with `files` added or replaced into a fresh directory.""" diff --git a/tests/e2e/src/sqlbuild/cli/commands/main/compile/semantic_checks/_test_types.py b/tests/e2e/src/sqlbuild/cli/commands/main/compile/semantic_checks/_test_types.py index 098f7b42a1..894ebd68e6 100644 --- a/tests/e2e/src/sqlbuild/cli/commands/main/compile/semantic_checks/_test_types.py +++ b/tests/e2e/src/sqlbuild/cli/commands/main/compile/semantic_checks/_test_types.py @@ -11,4 +11,3 @@ class NativeSemanticChecksCliTestCase: files: dict[str, str] expected_codes: tuple[str, ...] expected_notes: tuple[str, ...] - expected_native_deferrals: tuple[tuple[str, str], ...] diff --git a/tests/e2e/src/sqlbuild/cli/commands/main/compile/semantic_checks/helpers.py b/tests/e2e/src/sqlbuild/cli/commands/main/compile/semantic_checks/helpers.py index a1b15992d4..243d8eced2 100644 --- a/tests/e2e/src/sqlbuild/cli/commands/main/compile/semantic_checks/helpers.py +++ b/tests/e2e/src/sqlbuild/cli/commands/main/compile/semantic_checks/helpers.py @@ -2,72 +2,39 @@ import json import subprocess -from collections import Counter from itertools import chain from pathlib import Path from typing import Any, NamedTuple, cast from sqlbuild.cli.compile_reuse.constants import REUSE_DISABLE_ENV_VAR -from sqlbuild.compiler.semantic_checks.constants import ( - COMPLETION_DEFERRAL_SITE, - METADATA_DEFERRAL_SITE, - TYPE_RECOVERY_DEFERRAL_SITE, -) -from sqlbuild.compiler.sql_analysis.constants import ANALYSIS_RECORD_DIR_ENV_VAR from tests.e2e.src.sqlbuild.cli.commands.main.compile.helpers import run_installed_sqb -SEMANTIC_WHEEL_SITES: tuple[str, ...] = ( - "compiler/compile/_helpers/diagnostics/type_recovery.py:_projection_spans", - "compiler/compile/_helpers/diagnostics/details.py:_parsed_model", - "compiler/compile/_helpers/assembly/metadata_validation.py:_function_errors", -) -SEMANTIC_DEFERRAL_SITES: frozenset[str] = frozenset( - {COMPLETION_DEFERRAL_SITE, METADATA_DEFERRAL_SITE, TYPE_RECOVERY_DEFERRAL_SITE} -) - class EngineSemanticRun(NamedTuple): - """One engine's compile report, semantic wheel calls and semantic-stage deferrals.""" + """One engine's compile report and exit code.""" report: dict[str, object] returncode: int - semantic_wheel_calls: int - deferrals: tuple[tuple[str, str], ...] def engine_semantic_run( *, project_dir: Path, files: dict[str, str], engine: str ) -> EngineSemanticRun: - """Write the project and compile it once under `engine` with analysis records on.""" + """Write the project and compile it once under `engine`.""" for relative_path, contents in files.items(): path: Path = project_dir / "project" / relative_path path.parent.mkdir(parents=True, exist_ok=True) _ = path.write_text(contents, encoding="utf-8") - record_dir: Path = project_dir / "records" compiled: subprocess.CompletedProcess[str] = run_installed_sqb( project_dir=project_dir / "project", args=("--compiler-engine", engine, "compile", "--json", "--no-cache"), - env={REUSE_DISABLE_ENV_VAR: "1", ANALYSIS_RECORD_DIR_ENV_VAR: str(record_dir)}, + env={REUSE_DISABLE_ENV_VAR: "1"}, ) report: dict[str, object] = json.loads(compiled.stdout.replace(str(project_dir), "")) _ = report.pop("compiler_engine", None) _ = report.pop("compile_timings", None) - calls: Counter[str] = Counter() - for path in record_dir.glob("polyglot-sites-*.json"): - for site, _, count in json.loads(path.read_text("utf-8"))["calls"]: - calls[site] += count - deferrals: list[tuple[str, str]] = [] - for path in sorted(record_dir.glob("analysis-deferrals-*.jsonl")): - for line in path.read_text("utf-8").splitlines(): - record: dict[str, str] = json.loads(line) - deferrals.append((record["kind"], record["site"])) - return EngineSemanticRun( - report=report, - returncode=compiled.returncode, - semantic_wheel_calls=sum(calls[site] for site in SEMANTIC_WHEEL_SITES), - deferrals=tuple(filter(lambda deferral: deferral[1] in SEMANTIC_DEFERRAL_SITES, deferrals)), - ) + return EngineSemanticRun(report=report, returncode=compiled.returncode) def diagnostic_codes(report: dict[str, object]) -> tuple[str, ...]: diff --git a/tests/e2e/src/sqlbuild/cli/commands/main/compile/semantic_checks/test_native_semantic_checks_cli.py b/tests/e2e/src/sqlbuild/cli/commands/main/compile/semantic_checks/test_native_semantic_checks_cli.py index f0559ee404..e2b3b24729 100644 --- a/tests/e2e/src/sqlbuild/cli/commands/main/compile/semantic_checks/test_native_semantic_checks_cli.py +++ b/tests/e2e/src/sqlbuild/cli/commands/main/compile/semantic_checks/test_native_semantic_checks_cli.py @@ -1,4 +1,4 @@ -"""The native engines complete semantic diagnostics natively with Python's exact CLI output.""" +"""Both native engines complete semantic diagnostics natively with the expected CLI output.""" from __future__ import annotations @@ -16,7 +16,7 @@ engine_semantic_run, ) -_ENGINES: tuple[str, ...] = ("python", "native", "native-preview") +_ENGINES: tuple[str, ...] = ("native", "native-preview") _CONFIG: str = ( 'name = "orders_semantics"\nadapter = "duckdb"\n\n[connection]\ndatabase = "orders.duckdb"\n' ) @@ -103,14 +103,12 @@ "o.ordered_at is TIMESTAMP, 5 is INTEGER", "raw_orders has: amount, status, ordered_at, customer_id, order_id", ), - expected_native_deferrals=(), ), NativeSemanticChecksCliTestCase( description="UDF calls, config and cursor references, a source cursor and a SQL test", files=_METADATA_FILES, expected_codes=("B301", "B102", "B300", "B300", "B301", "B300", "B302"), expected_notes=(), - expected_native_deferrals=(), ), ], ids=lambda case: case.description, @@ -124,18 +122,13 @@ def test_given_failing_project_when_compiling_with_each_engine_then_diagnostics_ ) for engine in _ENGINES } - python: EngineSemanticRun = runs["python"] native: EngineSemanticRun = runs["native"] preview: EngineSemanticRun = runs["native-preview"] - assert python.returncode == 1 - assert diagnostic_codes(python.report) == test_case.expected_codes - assert set(test_case.expected_notes) <= diagnostic_notes(python.report) - assert python.semantic_wheel_calls > 0 - assert (native.report, native.returncode) == (python.report, python.returncode) - assert (preview.report, preview.returncode) == (python.report, python.returncode) - assert (native.semantic_wheel_calls, preview.semantic_wheel_calls) == (0, 0) - assert native.deferrals == preview.deferrals == test_case.expected_native_deferrals + assert native.returncode == 1 + assert diagnostic_codes(native.report) == test_case.expected_codes + assert set(test_case.expected_notes) <= diagnostic_notes(native.report) + assert (preview.report, preview.returncode) == (native.report, native.returncode) if __name__ == "__main__": diff --git a/tests/e2e/src/sqlbuild/cli/commands/main/compile/sql_test_errors/test_native_sql_test_errors.py b/tests/e2e/src/sqlbuild/cli/commands/main/compile/sql_test_errors/test_native_sql_test_errors.py index 411ed75228..1f16be8069 100644 --- a/tests/e2e/src/sqlbuild/cli/commands/main/compile/sql_test_errors/test_native_sql_test_errors.py +++ b/tests/e2e/src/sqlbuild/cli/commands/main/compile/sql_test_errors/test_native_sql_test_errors.py @@ -25,7 +25,7 @@ NativeSqlTestErrorTestCase, ) -_ENGINES: tuple[str, ...] = ("python", "native", "native-preview") +_ENGINES: tuple[str, ...] = ("native", "native-preview") _CALL_LOG: str = "macro_calls.log" _COUNTED_MACRO: str = ( "from pathlib import Path\n\n\n" @@ -154,7 +154,7 @@ def test_given_sql_test_error_when_compiling_with_each_engine_then_errors_and_ty len(set(macro_calls)), tuple(error_types), ) == ( - (1, 1, 1), + (1, 1), True, True, True, @@ -162,11 +162,11 @@ def test_given_sql_test_error_when_compiling_with_each_engine_then_errors_and_ty True, True, test_case.expected_distinct_macro_call_counts, - ("CompileInputError", "CompileInputError", "CompileInputError"), + ("CompileInputError", "CompileInputError"), ), ( runs[0].report, runs[0].stderr, - runs[2].report, + runs[1].report, macro_calls, ) diff --git a/tests/e2e/src/sqlbuild/cli/commands/main/compile/test_compile_incremental_edits.py b/tests/e2e/src/sqlbuild/cli/commands/main/compile/test_compile_incremental_edits.py index 9c98cf36d3..721cb03b5a 100644 --- a/tests/e2e/src/sqlbuild/cli/commands/main/compile/test_compile_incremental_edits.py +++ b/tests/e2e/src/sqlbuild/cli/commands/main/compile/test_compile_incremental_edits.py @@ -21,8 +21,6 @@ RandomEditChain, adapter_switched, add_external_flavor_macro, - analyze_in_one_batch, - analyze_one_model_at_a_time, build_between, change_adapter_lexical_rules, compare_incremental_compile, @@ -48,7 +46,6 @@ fact_quantity_type_declared, fact_quantity_type_removed, ignore_project_changes, - ignore_query_in_analysis_key, ignore_test_text_in_scan_key, in_process_reuse_run, keep_invalidation, @@ -373,12 +370,6 @@ def test_given_random_edit_chain_when_compiling_with_caches_then_each_step_match sabotage=keep_invalidation, expected_matches_uncached=True, ), - BrokenEditInvalidationTestCase( - description="stale_python_analysis_despite_query_edit", - edit=fact_error_introduced, - sabotage=ignore_query_in_analysis_key, - expected_matches_uncached=False, - ), BrokenEditInvalidationTestCase( description="intact_invalidation_after_test_edit", edit=stg_orders_test_edit, @@ -419,12 +410,7 @@ def test_given_broken_cache_invalidation_when_compiling_an_edit_then_the_oracle_ @pytest.mark.parametrize( "test_case", - [ - SharedCacheKeyTestCase( - description="dataflow_one_model_at_a_time", schedule=analyze_one_model_at_a_time - ), - SharedCacheKeyTestCase(description="one_batch", schedule=analyze_in_one_batch), - ], + [SharedCacheKeyTestCase(description="native_dependency_order")], ids=lambda case: case.description, ) def test_given_models_sharing_an_analysis_cache_key_when_upstream_changes_then_it_matches_uncached( @@ -435,7 +421,6 @@ def test_given_models_sharing_an_analysis_cache_key_when_upstream_changes_then_i ) -> None: project_dir: Path = compile_reuse_project enable_compile_reuse(monkeypatch) - test_case.schedule(monkeypatch) star_chain_with_twin_added(project_dir) assert compile_in_process(project_dir=project_dir) == 0 staging_extra_flag(project_dir) diff --git a/tests/e2e/src/sqlbuild/cli/commands/main/compile/test_compile_macro_call_store.py b/tests/e2e/src/sqlbuild/cli/commands/main/compile/test_compile_macro_call_store.py index a8734227cc..daeb1db80a 100644 --- a/tests/e2e/src/sqlbuild/cli/commands/main/compile/test_compile_macro_call_store.py +++ b/tests/e2e/src/sqlbuild/cli/commands/main/compile/test_compile_macro_call_store.py @@ -289,12 +289,6 @@ def test_given_broken_store_key_when_compiling_an_edit_then_the_oracle_reports_a expected_logged_calls=(1, 0), expected_store_files=("target/cache/compiler-native-v1/macro-calls.bin",), ), - EngineMacroCallGateTestCase( - description="python", - engine="python", - expected_logged_calls=(3, 3), - expected_store_files=(), - ), EngineMacroCallGateTestCase( description="native", engine="native", @@ -310,7 +304,7 @@ def test_given_broken_store_key_when_compiling_an_edit_then_the_oracle_reports_a ], ids=lambda case: case.description, ) -def test_given_engine_when_compiling_repeatedly_then_only_native_engines_batch_and_store_macro_calls( +def test_given_engine_when_compiling_repeatedly_then_macro_calls_are_batched_and_stored( tmp_path: Path, test_case: EngineMacroCallGateTestCase ) -> None: project_dir: Path = tmp_path / "project" @@ -333,11 +327,6 @@ def test_given_engine_when_compiling_repeatedly_then_only_native_engines_batch_a @pytest.mark.parametrize( "test_case", [ - MacroReferenceCallStoreTestCase( - description="python", - engine="python", - expected_logged_calls=(2, 2), - ), MacroReferenceCallStoreTestCase( description="native_memo_then_store", engine="native", @@ -346,13 +335,13 @@ def test_given_engine_when_compiling_repeatedly_then_only_native_engines_batch_a ], ids=lambda case: case.description, ) -def test_given_macro_returning_rejected_reference_call_when_replaying_then_reports_match_python( +def test_given_macro_returning_rejected_reference_call_when_replaying_then_reports_match_first( tmp_path: Path, test_case: MacroReferenceCallStoreTestCase ) -> None: oracle: MacroReferenceCallRuns = macro_reference_call_runs( - project_dir=prepare_macro_reference_call_project(tmp_path=tmp_path / "python"), - log_path=tmp_path / "python.log", - engine="python", + project_dir=prepare_macro_reference_call_project(tmp_path=tmp_path / "oracle"), + log_path=tmp_path / "oracle.log", + engine="native", runs=1, ) @@ -518,7 +507,7 @@ def test_given_no_proc_filesystem_when_compiling_repeatedly_then_the_store_still description="a lone surrogate var is rejected before any macro runs", project_files=_TAGGED_STAGING, compile_args=("--vars", '{"regions": ["\\udcff"]}'), - expected_returncodes=(1, 1, 1), + expected_returncodes=(1, 1), expected_report_fragment=( "Variable 'regions' holds a lone surrogate in its value[0] at UTF-8 byte 0, " "which is not valid Unicode text" @@ -532,7 +521,7 @@ def test_given_unencodable_var_when_compiling_then_every_engine_rejects_it( ) -> None: project_dir: Path = tmp_path / "orders" runs: list[CompileReuseRun] = [] - for engine in ("python", "native", "native-preview"): + for engine in ("native", "native-preview"): shutil.rmtree(project_dir, ignore_errors=True) for relative_path, contents in {**FAILURE_BASE_FILES, **test_case.project_files}.items(): write_project_file(project_dir, relative_path, contents) diff --git a/tests/e2e/src/sqlbuild/cli/commands/main/compile/test_compiler_engine_switch.py b/tests/e2e/src/sqlbuild/cli/commands/main/compile/test_compiler_engine_switch.py deleted file mode 100644 index f8b5f2195f..0000000000 --- a/tests/e2e/src/sqlbuild/cli/commands/main/compile/test_compiler_engine_switch.py +++ /dev/null @@ -1,236 +0,0 @@ -"""Both compiler engines produce identical compiles and never share on-disk compile stores.""" - -from __future__ import annotations - -from pathlib import Path - -import pytest - -from tests.e2e.src.sqlbuild.cli.commands.main.compile._test_types import ( - CompilerEngineMacroParityTestCase, - CompilerEngineParityTestCase, - CompilerEngineRulesStoreTestCase, - CompilerEngineStoreTestCase, - DefaultEngineParityTestCase, -) -from tests.e2e.src.sqlbuild.cli.commands.main.compile.helpers import ( - CompileReuseRun, - copy_compile_project, - engine_compile_and_rules, - engine_reuse_compile, - environment_engine_reuse_compile, - prepare_compile_reuse_project, - report_engine, - report_without_engine, - store_digests, - store_files, -) -from tests.integration.src.sqlbuild.compiler.compile.helpers import ( - MACRO_BRIDGE_PROJECT_FILES, - write_project, -) - - -@pytest.mark.parametrize( - "test_case", - [ - CompilerEngineParityTestCase( - description="python_and_native", - left_engine="python", - right_engine="native", - expected_engines=("python", "native"), - expected_exit_codes=(0, 0), - ) - ], - ids=lambda case: case.description, -) -def test_given_same_project_when_compiling_with_each_engine_then_outputs_are_identical( - test_case: CompilerEngineParityTestCase, tmp_path: Path -) -> None: - prepared_project: Path = tmp_path / "orders" - prepare_compile_reuse_project(project_dir=prepared_project) - left: CompileReuseRun = engine_reuse_compile( - project_dir=copy_compile_project(source=prepared_project, destination=tmp_path / "left"), - engine=test_case.left_engine, - ) - right: CompileReuseRun = engine_reuse_compile( - project_dir=copy_compile_project(source=prepared_project, destination=tmp_path / "right"), - engine=test_case.right_engine, - ) - - assert (left.returncode, right.returncode) == test_case.expected_exit_codes - assert (report_engine(left), report_engine(right)) == test_case.expected_engines - assert report_without_engine(right) == report_without_engine(left) - assert right.compiled == left.compiled - assert left.compiled - - -@pytest.mark.parametrize( - "test_case", - [ - DefaultEngineParityTestCase( - description="python_oracle_and_unset_default", - oracle_engine="python", - default_engine="", - expected_engines=("python", "native"), - expected_exit_codes=(0, 0), - expected_macro_call_stores=((), ("target/cache/compiler-native-v1/macro-calls.bin",)), - ) - ], - ids=lambda case: case.description, -) -def test_given_no_engine_selection_when_compiling_then_native_rendering_runs_and_matches_python( - test_case: DefaultEngineParityTestCase, tmp_path: Path -) -> None: - prepared_project: Path = tmp_path / "orders" - prepare_compile_reuse_project(project_dir=prepared_project) - oracle_dir: Path = copy_compile_project( - source=prepared_project, destination=tmp_path / "oracle" - ) - default_dir: Path = copy_compile_project( - source=prepared_project, destination=tmp_path / "default" - ) - oracle: CompileReuseRun = environment_engine_reuse_compile( - project_dir=oracle_dir, engine=test_case.oracle_engine - ) - default: CompileReuseRun = environment_engine_reuse_compile( - project_dir=default_dir, engine=test_case.default_engine - ) - - assert (oracle.returncode, default.returncode) == test_case.expected_exit_codes - assert (report_engine(oracle), report_engine(default)) == test_case.expected_engines - assert report_without_engine(default) == report_without_engine(oracle) - assert default.compiled == oracle.compiled - assert oracle.compiled - assert ( - tuple(store_files(oracle_dir)), - tuple(store_files(default_dir)), - ) == test_case.expected_macro_call_stores - - -@pytest.mark.parametrize( - "test_case", - [ - CompilerEngineMacroParityTestCase( - description="macros_in_models_hooks_tests_audits_sources_functions", - files={ - path: content.replace("WHERE id IN @generated_join()\n", "") - for path, content in MACRO_BRIDGE_PROJECT_FILES.items() - }, - expected_exit_codes=(0, 0), - expected_compiled_fragments=("amount * 21", "'__SQLBUILD_RELATION_1__'"), - ) - ], - ids=lambda case: case.description, -) -def test_given_macro_heavy_project_when_compiling_with_each_engine_then_outputs_are_identical( - test_case: CompilerEngineMacroParityTestCase, tmp_path: Path -) -> None: - python_run: CompileReuseRun = engine_reuse_compile( - project_dir=write_project(root=tmp_path / "python", files=test_case.files), - engine="python", - ) - native_run: CompileReuseRun = engine_reuse_compile( - project_dir=write_project(root=tmp_path / "native", files=test_case.files), - engine="native", - ) - compiled_text: str = b"".join(python_run.compiled.values()).decode() - - assert (python_run.returncode, native_run.returncode) == test_case.expected_exit_codes - assert report_without_engine(native_run) == report_without_engine(python_run) - assert native_run.compiled == python_run.compiled - assert all(map(compiled_text.__contains__, test_case.expected_compiled_fragments)) - - -@pytest.mark.parametrize( - "test_case", - [ - CompilerEngineStoreTestCase( - description="python_native_native_python", - engines=("python", "native", "native", "python"), - expected_reused=(False, False, True, True), - expected_python_stores=("target/cache/compiler", "target/rules-cache"), - expected_native_stores=( - "target/cache/compiler-native-v1", - "target/rules-cache-native-v1", - ), - ) - ], - ids=lambda case: case.description, -) -def test_given_compile_by_one_engine_when_other_engine_compiles_then_no_store_is_shared( - test_case: CompilerEngineStoreTestCase, tmp_path: Path -) -> None: - project_dir: Path = tmp_path / "orders" - prepare_compile_reuse_project(project_dir=project_dir) - - first: CompileReuseRun = engine_reuse_compile( - project_dir=project_dir, engine=test_case.engines[0] - ) - python_stores: dict[str, str] = store_digests( - project_dir=project_dir, stores=test_case.expected_python_stores - ) - later: list[CompileReuseRun] = [ - engine_reuse_compile(project_dir=project_dir, engine=engine) - for engine in test_case.engines[1:-1] - ] - python_stores_after_native: dict[str, str] = store_digests( - project_dir=project_dir, stores=test_case.expected_python_stores - ) - last: CompileReuseRun = engine_reuse_compile( - project_dir=project_dir, engine=test_case.engines[-1] - ) - runs: list[CompileReuseRun] = [first, *later, last] - - assert tuple(run.reused for run in runs) == test_case.expected_reused - assert python_stores - assert python_stores_after_native == python_stores - assert store_digests(project_dir=project_dir, stores=test_case.expected_native_stores) - assert {report_without_engine(run) for run in runs[2:]} == {report_without_engine(last)} - - -@pytest.mark.parametrize( - "test_case", - [ - CompilerEngineRulesStoreTestCase( - description="built_in_rules_after_compile", - rules_selector="SQBR", - stores=("target/cache", "target/rules-cache", "target/rules-cache-native-v1"), - native_marker="-native-v1/", - expected_python_files=( - "target/rules-cache/bulk/native.json", - "target/rules-cache/bulk/sql.json", - ), - expected_native_files=( - "target/rules-cache-native-v1/bulk/native.json", - "target/rules-cache-native-v1/bulk/sql.json", - ), - ) - ], - ids=lambda case: case.description, -) -def test_given_python_compile_and_rules_when_native_runs_them_then_native_writes_only_its_stores( - test_case: CompilerEngineRulesStoreTestCase, tmp_path: Path -) -> None: - project_dir: Path = tmp_path / "orders" - prepare_compile_reuse_project(project_dir=project_dir) - - python_exit: int = engine_compile_and_rules( - project_dir=project_dir, engine="python", rules_selector=test_case.rules_selector - ) - python_files: dict[str, str] = store_digests(project_dir=project_dir, stores=test_case.stores) - native_exit: int = engine_compile_and_rules( - project_dir=project_dir, engine="native", rules_selector=test_case.rules_selector - ) - all_files: dict[str, str] = store_digests(project_dir=project_dir, stores=test_case.stores) - native_files: set[str] = set(all_files) - set(python_files) - - assert native_exit == python_exit - assert {path: all_files.get(path) for path in python_files} == python_files - assert all(test_case.native_marker in path for path in native_files), sorted(native_files) - assert set(test_case.expected_python_files) <= set(python_files) - assert set(test_case.expected_native_files) <= native_files - - -if __name__ == "__main__": - pytest.main([__file__, "-vv"]) diff --git a/tests/e2e/src/sqlbuild/cli/commands/main/compile/test_compiler_engine_tiers.py b/tests/e2e/src/sqlbuild/cli/commands/main/compile/test_compiler_engine_tiers.py index 519651f2d4..812b5c4841 100644 --- a/tests/e2e/src/sqlbuild/cli/commands/main/compile/test_compiler_engine_tiers.py +++ b/tests/e2e/src/sqlbuild/cli/commands/main/compile/test_compiler_engine_tiers.py @@ -1,4 +1,4 @@ -"""The native-preview tier matches Python and never shares stores with the shipped native tier.""" +"""The native-preview tier matches shipped native and never shares stores with it.""" from __future__ import annotations @@ -25,16 +25,16 @@ "test_case", [ CompilerEngineParityTestCase( - description="python_and_native_preview", - left_engine="python", + description="native_and_native_preview", + left_engine="native", right_engine="native-preview", - expected_engines=("python", "native-preview"), + expected_engines=("native", "native-preview"), expected_exit_codes=(0, 0), ) ], ids=lambda case: case.description, ) -def test_given_same_project_when_compiling_with_preview_tier_then_outputs_match_python( +def test_given_same_project_when_compiling_with_preview_tier_then_outputs_match_native( test_case: CompilerEngineParityTestCase, tmp_path: Path ) -> None: prepared_project: Path = tmp_path / "orders" diff --git a/tests/e2e/src/sqlbuild/cli/commands/main/compile/test_deep_header_nesting.py b/tests/e2e/src/sqlbuild/cli/commands/main/compile/test_deep_header_nesting.py index 62a291291b..0a782253b9 100644 --- a/tests/e2e/src/sqlbuild/cli/commands/main/compile/test_deep_header_nesting.py +++ b/tests/e2e/src/sqlbuild/cli/commands/main/compile/test_deep_header_nesting.py @@ -18,7 +18,7 @@ _ORDERS_MODEL: str = "MODEL (description 'Orders.');\n\nSELECT 1 AS order_id\n" _COMPILE_TIME_BOUND_SECONDS: float = 120.0 _NESTING_HELP: str = "help: flatten the value so it nests at most 256 levels deep" -_ENGINES: tuple[str, ...] = ("python", "native", "native-preview") +_ENGINES: tuple[str, ...] = ("native", "native-preview") _CONSTANT_CALL_NESTING: tuple[str, ...] = ( "error[D013]", "constants/limits.sql:3' contains invalid SQLBuild header syntax: " @@ -31,8 +31,8 @@ "test_case", [ DeepHeaderNestingCompileCase( - description="python_model_1k", - engine="python", + description="native_model_1k", + engine="native", path="models/orders.sql", prefix="MODEL (\n description 'Orders.',\n tags ", suffix=",\n);\n\nSELECT 1 AS order_id\n", @@ -72,20 +72,6 @@ _NESTING_HELP, ), ), - DeepHeaderNestingCompileCase( - description="python_hook_100k", - engine="python", - path="hooks/sql/record_refresh.sql", - prefix="HOOK (\n description ", - suffix=",\n);\n\nSELECT 1\n", - depth=100_000, - expected_fragments=( - "error[D014]", - "hooks/sql/record_refresh.sql:2' contains invalid SQLBuild header syntax: " - "values nest deeper than 256 levels", - _NESTING_HELP, - ), - ), ], ids=lambda case: case.description, ) diff --git a/tests/e2e/src/sqlbuild/cli/commands/main/compile/test_dense_batched_preparation.py b/tests/e2e/src/sqlbuild/cli/commands/main/compile/test_dense_batched_preparation.py deleted file mode 100644 index fffac8f29e..0000000000 --- a/tests/e2e/src/sqlbuild/cli/commands/main/compile/test_dense_batched_preparation.py +++ /dev/null @@ -1,61 +0,0 @@ -"""Dense batched analysis preparation must match per-model preparation byte for byte.""" - -from pathlib import Path - -import pytest - -from scripts.cold_compile_performance._helpers.dense_project import write_dense_compile_project -from sqlbuild.compiler.compile.constants import COMPACT_RELATION_STUB_PREFIX -from tests.e2e.src.sqlbuild.cli.commands.main.compile._test_types import ( - DenseBatchedPreparationTestCase, - DensePreparedCompile, -) -from tests.integration.src.sqlbuild.compiler.pipeline.helpers import ( - keep_batched_normalization, - prepared_compile, - use_per_model_normalization, -) - - -@pytest.mark.performance -@pytest.mark.parametrize( - "test_case", - (DenseBatchedPreparationTestCase("dense_models_3000", 3000, 0),), - ids=lambda case: case.description, -) -def test_given_dense_project_when_compiling_cold_then_batched_preparation_matches_per_model( - test_case: DenseBatchedPreparationTestCase, - tmp_path: Path, - capsys: pytest.CaptureFixture[str], - monkeypatch: pytest.MonkeyPatch, -) -> None: - batched_dir: Path = tmp_path / "batched" - reference_dir: Path = tmp_path / "reference" - write_dense_compile_project(project_dir=batched_dir, model_count=test_case.model_count) - write_dense_compile_project(project_dir=reference_dir, model_count=test_case.model_count) - - expected: DensePreparedCompile = prepared_compile( - project_dir=reference_dir, - args=(), - capsys=capsys, - monkeypatch=monkeypatch, - normalization=use_per_model_normalization, - ) - actual: DensePreparedCompile = prepared_compile( - project_dir=batched_dir, - args=(), - capsys=capsys, - monkeypatch=monkeypatch, - normalization=keep_batched_normalization, - ) - - assert actual[3] == expected[3] - assert actual[1] == expected[1] - assert actual[2] == expected[2] - assert actual[0] == expected[0] - assert actual[0][0] == test_case.expected_exit_code - assert any(COMPACT_RELATION_STUB_PREFIX.encode() in payload for payload in actual[3]) - - -if __name__ == "__main__": - raise SystemExit(pytest.main([__file__, "-vv"])) diff --git a/tests/e2e/src/sqlbuild/cli/commands/main/compile/test_dollar_quoted_project_vars.py b/tests/e2e/src/sqlbuild/cli/commands/main/compile/test_dollar_quoted_project_vars.py index 3919c76bc8..6e25b09ae7 100644 --- a/tests/e2e/src/sqlbuild/cli/commands/main/compile/test_dollar_quoted_project_vars.py +++ b/tests/e2e/src/sqlbuild/cli/commands/main/compile/test_dollar_quoted_project_vars.py @@ -12,7 +12,7 @@ ) from tests.e2e.src.sqlbuild.cli.commands.shared.helpers import prepare_inline_project, run_sqb -_ENGINES: tuple[str, ...] = ("python", "native", "native-preview") +_ENGINES: tuple[str, ...] = ("native", "native-preview") _PROJECT_TOML: str = 'name = "orders"\nadapter = "duckdb"\n\n[vars]\nregion = "north"\n' _MODEL_HEADER: str = "MODEL (description 'Order region labels.', materialized view);\n\n" _COMPILED_MODEL: Path = Path("target/compiled/models/order_labels.sql") diff --git a/tests/e2e/src/sqlbuild/cli/commands/main/compile/test_native_analysis_seams.py b/tests/e2e/src/sqlbuild/cli/commands/main/compile/test_native_analysis_seams.py index a2d9676e5c..56dd2c7a3c 100644 --- a/tests/e2e/src/sqlbuild/cli/commands/main/compile/test_native_analysis_seams.py +++ b/tests/e2e/src/sqlbuild/cli/commands/main/compile/test_native_analysis_seams.py @@ -26,7 +26,7 @@ report_without_engine, ) -_ENGINES: tuple[str, ...] = ("python", "native", "native-preview") +_ENGINES: tuple[str, ...] = ("native", "native-preview") @pytest.mark.parametrize( @@ -70,14 +70,12 @@ def test_given_project_when_compiling_with_each_engine_then_native_seams_answer_ ) for engine in _ENGINES } - python_run, python_seams = outcomes["python"] native_run, native_seams = outcomes["native"] preview_run, preview_seams = outcomes["native-preview"] - assert python_run.returncode == 0, python_run.stderr - assert python_run.compiled - assert (python_seams, native_seams, preview_seams) == ( - {}, + assert native_run.returncode == 0, native_run.stderr + assert native_run.compiled + assert (native_seams, preview_seams) == ( test_case.expected_native_returns, test_case.expected_native_returns, ) @@ -102,11 +100,9 @@ def test_given_project_when_compiling_with_each_engine_then_native_seams_answer_ assert [ len(call.args[0].tests) for call in native_sql_test_planning.call_args_list ] == planned_counts - assert (native_run.returncode, preview_run.returncode) == (0, 0) - assert report_without_engine(native_run) == report_without_engine(python_run) - assert report_without_engine(preview_run) == report_without_engine(python_run) - assert native_run.compiled == python_run.compiled - assert preview_run.compiled == python_run.compiled + assert preview_run.returncode == 0 + assert report_without_engine(preview_run) == report_without_engine(native_run) + assert preview_run.compiled == native_run.compiled if __name__ == "__main__": diff --git a/tests/e2e/src/sqlbuild/cli/commands/main/compile/test_native_config_errors.py b/tests/e2e/src/sqlbuild/cli/commands/main/compile/test_native_config_errors.py index 2bfc85664d..430bb6b4eb 100644 --- a/tests/e2e/src/sqlbuild/cli/commands/main/compile/test_native_config_errors.py +++ b/tests/e2e/src/sqlbuild/cli/commands/main/compile/test_native_config_errors.py @@ -1,4 +1,4 @@ -"""The preview engine reports model config, template and header errors as Python does.""" +"""Both engines report model config, template and header errors alike, without fallbacks.""" from __future__ import annotations @@ -16,14 +16,13 @@ from tests.e2e.src.sqlbuild.cli.commands.main.compile.helpers import ( CompileReuseRun, fallback_free_preview_compile, - python_engine_compile, report_without_engine, run_reuse_compile, stderr_without_durations, write_counted_error_project, ) -_ENGINES: tuple[str, str] = ("python", "native-preview") +_ENGINES: tuple[str, str] = ("native", "native-preview") _CALL_LOG: str = "macro_calls.log" _COUNTED_MACRO: str = ( "from pathlib import Path\n\n\n" @@ -119,7 +118,7 @@ ], ids=lambda case: case.description, ) -def test_given_config_error_when_compiling_with_preview_then_error_matches_python( +def test_given_config_error_when_compiling_with_each_engine_then_errors_match( test_case: NativeConfigErrorTestCase, tmp_path: Path, monkeypatch: pytest.MonkeyPatch, @@ -136,12 +135,8 @@ def test_given_config_error_when_compiling_with_preview_then_error_matches_pytho run_reuse_compile(project_dir=project_dir, global_args=("--compiler-engine", engine)) ) macro_calls.append(len((project_dir / _CALL_LOG).read_text(encoding="utf-8").splitlines())) - for name in ("python", "preview"): - write_counted_error_project( - project_dir=tmp_path / name, files={**_PROJECT_FILES, **test_case.project_files} - ) - python_run: CompileReuseRun = python_engine_compile( - project_dir=tmp_path / "python", monkeypatch=monkeypatch, capsys=capsys + write_counted_error_project( + project_dir=tmp_path / "preview", files={**_PROJECT_FILES, **test_case.project_files} ) preview_run, fallbacks = fallback_free_preview_compile( project_dir=tmp_path / "preview", @@ -158,7 +153,7 @@ def test_given_config_error_when_compiling_with_preview_then_error_matches_pytho test_case.expected_report_text in runs[0].report + runs[0].stderr, macro_calls, preview_run.returncode, - report_without_engine(preview_run).replace("preview", "python"), + report_without_engine(preview_run).replace("preview", "orders"), fallbacks, ) == ( (1, 1), @@ -166,8 +161,8 @@ def test_given_config_error_when_compiling_with_preview_then_error_matches_pytho True, True, test_case.expected_macro_calls, - python_run.returncode, - report_without_engine(python_run).replace("preview", "python"), + 1, + report_without_engine(runs[1]), test_case.expected_python_fallbacks, ), (runs[0].report, runs[1].report, runs[1].stderr) @@ -185,9 +180,9 @@ def test_given_config_error_when_compiling_with_preview_then_error_matches_pytho ), _CALL_LOG: "", }, - engines=("python", "native-preview", "native"), + engines=("native-preview", "native"), expected_report_text="references unknown model 'ghost'", - expected_macro_calls=[1, 1, 1], + expected_macro_calls=[1, 1], ) ], ids=lambda case: case.description, diff --git a/tests/e2e/src/sqlbuild/cli/commands/main/compile/test_native_declaration_errors.py b/tests/e2e/src/sqlbuild/cli/commands/main/compile/test_native_declaration_errors.py index 2edee79840..764a12b7eb 100644 --- a/tests/e2e/src/sqlbuild/cli/commands/main/compile/test_native_declaration_errors.py +++ b/tests/e2e/src/sqlbuild/cli/commands/main/compile/test_native_declaration_errors.py @@ -21,7 +21,7 @@ write_project_file, ) -_ENGINES: tuple[str, ...] = ("python", "native", "native-preview") +_ENGINES: tuple[str, ...] = ("native", "native-preview") _CALL_LOG: str = "macro_calls.log" _COUNTED_MACRO: str = ( "from pathlib import Path\n\n\n" @@ -156,7 +156,7 @@ def test_given_declaration_error_when_compiling_natively_then_error_matches_pyth **_STATUS_ENUM, _STAGING_PATH: _STAGING_PREFIX + 'status = @enum("missing_status").PLACED\n', }, - expected_error_types=("CompileInputError",) * 3, + expected_error_types=("CompileInputError",) * 2, ), DeclarationErrorLifecycleTestCase( description="unclosed_quote_after_a_reference_only_python_scans", @@ -164,7 +164,7 @@ def test_given_declaration_error_when_compiling_natively_then_error_matches_pyth **_STATUS_ENUM, _STAGING_PATH: _STAGING_PREFIX + "status = @enum\u00e9 OR status = 'open\n", }, - expected_error_types=("CompileInputError",) * 3, + expected_error_types=("CompileInputError",) * 2, ), ], ids=lambda case: case.description, @@ -173,7 +173,7 @@ def test_given_declaration_error_when_compiling_with_each_engine_then_lifecycle_ test_case: DeclarationErrorLifecycleTestCase, tmp_path: Path, monkeypatch: pytest.MonkeyPatch ) -> None: error_types: list[str] = [] - for engine in ("python", "native", "native-preview"): + for engine in ("native", "native-preview"): project_dir: Path = tmp_path / engine for relative_path, contents in { **FAILURE_BASE_FILES, diff --git a/tests/e2e/src/sqlbuild/cli/commands/main/compile/test_native_macro_errors.py b/tests/e2e/src/sqlbuild/cli/commands/main/compile/test_native_macro_errors.py index eec6cd6f8e..247cb40057 100644 --- a/tests/e2e/src/sqlbuild/cli/commands/main/compile/test_native_macro_errors.py +++ b/tests/e2e/src/sqlbuild/cli/commands/main/compile/test_native_macro_errors.py @@ -21,7 +21,7 @@ write_project_file, ) -_ENGINES: tuple[str, ...] = ("python", "native", "native-preview") +_ENGINES: tuple[str, ...] = ("native", "native-preview") _CALL_LOG: str = "macro_calls.log" _MACROS: str = ( "from pathlib import Path\n\n\n" @@ -180,12 +180,12 @@ def test_given_macro_error_when_compiling_with_each_engine_then_error_matches_py MacroErrorLifecycleTestCase( description="macro_raises_after_a_side_effect", project_files={_STAGING_PATH: _STAGING_PREFIX + "@explode('amount')" + _STAGING_SUFFIX}, - expected_error_types=("CompileInputError",) * 3, + expected_error_types=("CompileInputError",) * 2, ), MacroErrorLifecycleTestCase( description="unknown_macro", project_files={_STAGING_PATH: _STAGING_PREFIX + "@missing('amount')" + _STAGING_SUFFIX}, - expected_error_types=("CompileInputError",) * 3, + expected_error_types=("CompileInputError",) * 2, ), ], ids=lambda case: case.description, diff --git a/tests/e2e/src/sqlbuild/cli/commands/main/compile/test_native_model_config.py b/tests/e2e/src/sqlbuild/cli/commands/main/compile/test_native_model_config.py deleted file mode 100644 index ba53f0d8dd..0000000000 --- a/tests/e2e/src/sqlbuild/cli/commands/main/compile/test_native_model_config.py +++ /dev/null @@ -1,129 +0,0 @@ -"""Native model config in the default engine compiles exactly as the Python engine does.""" - -from __future__ import annotations - -from pathlib import Path - -import pytest - -from tests.e2e.src.sqlbuild.cli.commands.main.compile._test_types import ( - NativeModelConfigParityTestCase, -) -from tests.e2e.src.sqlbuild.cli.commands.main.compile.helpers import ( - CompileReuseRun, - copy_compile_project, - prepare_compile_reuse_project, - replace_project_text, - report_without_engine, - run_reuse_compile, - stderr_without_durations, - write_project_file, -) - -_ORDER_QUALITY_MODEL: str = """MODEL ( - materialized table, - description "Order quality checks.", - schema "${coalesce(ENV:SQB_ORDER_QUALITY_SCHEMA, 'quality')}_${CTX:run.target}", - tags ["${if(eq(CTX:run.target, 'dev'), 'development', 'release')}"], - audits [ - expression_is_true ( - name "quantity_is_positive", - expression "quantity > 0", - severity error, - ), - ], - columns ( - order_id ( - type INTEGER, - nullable false, - description "Order key", - audits [not_null (severity error, name order_id_present), unique], - ), - status ( - type VARCHAR, - audits [ - accepted_values ( - values ["placed", "preparing", "ready", "completed", "cancelled"], - severity warn, - description "Known statuses", - always_run true, - ), - ], - ), - Quantity (type INTEGER, description "Waffles ordered"), - ), -); - -SELECT order_id, status, quantity AS Quantity -FROM __ref("stg_orders") -""" -_INVALID_SEVERITY_MODEL: str = """MODEL ( - materialized table, - columns ( - order_id (audits [not_null (severity fatal)]), - ), -); - -SELECT order_id FROM __ref("stg_orders") -""" -_TARGET_SCHEMA: tuple[str, str] = ( - 'schema = "dev"', - "schema = \"${coalesce(ENV:SQB_TARGET_SCHEMA, ENV:SQB_MISSING_SCHEMA, 'dev')}\"", -) - - -@pytest.mark.parametrize( - "test_case", - [ - NativeModelConfigParityTestCase( - description="header_metadata_and_templates", - project_files={"models/marts/order_quality.sql": _ORDER_QUALITY_MODEL}, - project_config_replacements=(_TARGET_SCHEMA,), - environment={"SQB_TARGET_SCHEMA": "analytics"}, - engines=("python", "native"), - expected_exit_codes=(0, 0), - expected_report_text="order_quality", - ), - NativeModelConfigParityTestCase( - description="python_error_for_an_invalid_audit_severity", - project_files={"models/marts/order_quality.sql": _INVALID_SEVERITY_MODEL}, - project_config_replacements=(), - environment={}, - engines=("python", "native"), - expected_exit_codes=(1, 1), - expected_report_text="severity", - ), - ], - ids=lambda case: case.description, -) -def test_given_authored_model_config_when_compiling_natively_then_output_matches_python( - test_case: NativeModelConfigParityTestCase, tmp_path: Path -) -> None: - prepared_project: Path = tmp_path / "orders" - prepare_compile_reuse_project(project_dir=prepared_project) - for relative_path, contents in test_case.project_files.items(): - write_project_file(prepared_project, relative_path, contents) - for old, new in test_case.project_config_replacements: - replace_project_text(prepared_project, "sqlbuild_project.toml", old, new) - runs: list[CompileReuseRun] = [ - run_reuse_compile( - project_dir=copy_compile_project( - source=prepared_project, destination=tmp_path / engine - ), - env=test_case.environment, - global_args=("--compiler-engine", engine), - ) - for engine in test_case.engines - ] - - assert tuple(run.returncode for run in runs) == test_case.expected_exit_codes - assert report_without_engine(runs[1]) == report_without_engine(runs[0]) - assert stderr_without_durations(stderr=runs[1].stderr) == stderr_without_durations( - stderr=runs[0].stderr - ) - assert runs[1].compiled == runs[0].compiled - assert test_case.expected_report_text in runs[0].report + runs[0].stderr - - -if __name__ == "__main__": - pytest.main([__file__, "-vv"]) diff --git a/tests/e2e/src/sqlbuild/cli/commands/main/compile/test_native_model_loop.py b/tests/e2e/src/sqlbuild/cli/commands/main/compile/test_native_model_loop.py deleted file mode 100644 index 3cbf097d98..0000000000 --- a/tests/e2e/src/sqlbuild/cli/commands/main/compile/test_native_model_loop.py +++ /dev/null @@ -1,106 +0,0 @@ -"""The default engine's native model loop compiles exactly as the Python engine does.""" - -from __future__ import annotations - -from pathlib import Path - -import pytest - -from tests.e2e.src.sqlbuild.cli.commands.main.compile._test_types import ( - NativeModelLoopParityTestCase, -) -from tests.e2e.src.sqlbuild.cli.commands.main.compile.helpers import ( - CompileReuseRun, - copy_compile_project, - prepare_compile_reuse_project, - report_without_engine, - run_reuse_compile, - stderr_without_durations, - write_project_file, -) - -_DECLARATIONS: dict[str, str] = { - "enums/order_status.sql": "ENUM (name order_status, members [PLACED, SHIPPED]);\n", - "constants/limits.sql": "CONSTANT (name order_cap, value 3);\n", -} -_MARTS_DECLARATIONS: dict[str, str] = { - "models/marts/_sqlbuild/_enums/order_status.sql": ( - "ENUM (name order_status, members [PLACED, SHIPPED]);\n" - ), - "models/marts/_sqlbuild/_constants/limits.sql": "CONSTANT (name order_cap, value 3);\n", -} -_DECLARATION_MODEL: str = """MODEL (materialized view, description "Order flags."); - -SELECT - order_id, - @enum("order_status").PLACED AS placed_status, - @const("order_cap") AS order_cap, - '@const("order_cap")' AS literal_text -FROM __ref("stg_orders") -""" - - -@pytest.mark.parametrize( - "test_case", - [ - NativeModelLoopParityTestCase( - description="folder_private_declaration_references", - project_files={ - **_MARTS_DECLARATIONS, - "models/marts/order_flags.sql": _DECLARATION_MODEL, - }, - engines=("python", "native"), - expected_exit_codes=(0, 0), - expected_report_text="order_flags", - ), - NativeModelLoopParityTestCase( - description="python_identity_error_for_a_folder_containing_a_colon", - project_files={**_DECLARATIONS, "models/a:b/order_flags.sql": _DECLARATION_MODEL}, - engines=("python", "native"), - expected_exit_codes=(1, 1), - expected_report_text="Unknown qualified identity kind", - ), - NativeModelLoopParityTestCase( - description="rejected_reference_call_beside_declaration_references", - project_files={ - **_MARTS_DECLARATIONS, - "models/marts/order_flags.sql": _DECLARATION_MODEL.replace( - '__ref("stg_orders")', "__ref('stg_orders')" - ), - }, - engines=("python", "native"), - expected_exit_codes=(1, 1), - expected_report_text="P012", - ), - ], - ids=lambda case: case.description, -) -def test_given_model_declarations_when_compiling_natively_then_output_matches_python( - test_case: NativeModelLoopParityTestCase, tmp_path: Path -) -> None: - prepared_project: Path = tmp_path / "orders" - prepare_compile_reuse_project(project_dir=prepared_project) - for relative_path, contents in test_case.project_files.items(): - write_project_file(prepared_project, relative_path, contents) - runs: list[CompileReuseRun] = [ - run_reuse_compile( - project_dir=copy_compile_project( - source=prepared_project, destination=tmp_path / engine - ), - env={}, - global_args=("--compiler-engine", engine), - ) - for engine in test_case.engines - ] - - assert tuple(run.returncode for run in runs) == test_case.expected_exit_codes - assert report_without_engine(runs[1]) == report_without_engine(runs[0]) - assert stderr_without_durations(stderr=runs[1].stderr) == stderr_without_durations( - stderr=runs[0].stderr - ) - assert runs[1].compiled == runs[0].compiled - assert test_case.expected_report_text in runs[0].report + runs[0].stderr - - -if __name__ == "__main__": - pytest.main([__file__, "-vv"]) diff --git a/tests/e2e/src/sqlbuild/cli/commands/main/compile/test_native_reference_errors.py b/tests/e2e/src/sqlbuild/cli/commands/main/compile/test_native_reference_errors.py index 97e099d6ec..9904820753 100644 --- a/tests/e2e/src/sqlbuild/cli/commands/main/compile/test_native_reference_errors.py +++ b/tests/e2e/src/sqlbuild/cli/commands/main/compile/test_native_reference_errors.py @@ -24,7 +24,7 @@ write_project_file, ) -_ENGINES: tuple[str, str, str] = ("python", "native", "native-preview") +_ENGINES: tuple[str, ...] = ("native", "native-preview") _CALL_LOG: str = "macro_calls.log" _EMIT_MACRO: str = ( "from pathlib import Path\n\n\n" @@ -53,8 +53,8 @@ expected_message=( f"{FAILURE_MART_PATH}:6:6: SQL reference contains an unclosed parenthesis" ), - expected_macro_calls=(0, 0, 0), - expected_error_types=("CompileInputError",) * 3, + expected_macro_calls=(0, 0), + expected_error_types=("CompileInputError",) * 2, ), ReferenceScanErrorTestCase( description="unclosed_quote_after_a_rejected_call", @@ -66,8 +66,8 @@ expected_message=( f"{FAILURE_MART_PATH}:7:14: SQL reference contains an unclosed quoted string" ), - expected_macro_calls=(0, 0, 0), - expected_error_types=("CompileInputError",) * 3, + expected_macro_calls=(0, 0), + expected_error_types=("CompileInputError",) * 2, ), ReferenceScanErrorTestCase( description="empty_table_function_argument", @@ -78,8 +78,8 @@ expected_message=( f"{FAILURE_MART_PATH}:6:31: SQL reference contains an empty argument" ), - expected_macro_calls=(0, 0, 0), - expected_error_types=("CompileInputError",) * 3, + expected_macro_calls=(0, 0), + expected_error_types=("CompileInputError",) * 2, ), ReferenceScanErrorTestCase( description="header_string_with_an_escaped_quote_and_apostrophe", @@ -90,8 +90,8 @@ expected_message=( f"{FAILURE_MART_PATH}:7:7: SQL reference contains an unclosed quoted string" ), - expected_macro_calls=(0, 0, 0), - expected_error_types=("CompileInputError",) * 3, + expected_macro_calls=(0, 0), + expected_error_types=("CompileInputError",) * 2, ), ReferenceScanErrorTestCase( description="macro_output_fault_before_an_authored_fault_is_unlocated", @@ -104,8 +104,8 @@ expected_message=( f"{FAILURE_MART_PATH}: SQL reference contains an unclosed parenthesis" ), - expected_macro_calls=(1, 1, 1), - expected_error_types=("CompileInputError",) * 3, + expected_macro_calls=(1, 1), + expected_error_types=("CompileInputError",) * 2, ), ReferenceScanErrorTestCase( description="authored_fault_after_a_macro_is_located_natively", @@ -117,8 +117,8 @@ expected_message=( f"{FAILURE_MART_PATH}:6:6: SQL reference contains an unclosed parenthesis" ), - expected_macro_calls=(1, 1, 1), - expected_error_types=("CompileInputError",) * 3, + expected_macro_calls=(1, 1), + expected_error_types=("CompileInputError",) * 2, ), ReferenceScanErrorTestCase( description="test_file_header_names_the_file", @@ -137,8 +137,8 @@ expected_message=( "tests/unit/test_customer_totals.sql: SQL reference contains an empty argument" ), - expected_macro_calls=(0, 0, 0), - expected_error_types=("CompileInputError",) * 3, + expected_macro_calls=(0, 0), + expected_error_types=("CompileInputError",) * 2, ), ReferenceScanErrorTestCase( description="audit_file_header_names_the_file", @@ -155,8 +155,8 @@ expected_message=( "audits/generic/positive_total.sql: SQL reference contains an unclosed quoted string" ), - expected_macro_calls=(0, 0, 0), - expected_error_types=("CompileInputError",) * 3, + expected_macro_calls=(0, 0), + expected_error_types=("CompileInputError",) * 2, ), ReferenceScanErrorTestCase( description="function_file_header_names_the_file", @@ -171,8 +171,8 @@ expected_message=( "functions/sql/orders_for.sql: SQL reference contains an unclosed parenthesis" ), - expected_macro_calls=(0, 0, 0), - expected_error_types=("CompileInputError",) * 3, + expected_macro_calls=(0, 0), + expected_error_types=("CompileInputError",) * 2, ), ], ids=lambda case: case.description, @@ -209,13 +209,13 @@ def test_given_reference_scan_error_when_compiling_with_each_engine_then_located tuple(macro_calls), tuple(error_types), ) == ( - (1, 1, 1), + (1, 1), True, True, True, test_case.expected_macro_calls, test_case.expected_error_types, - ), (runs[0].report, runs[2].report) + ), (runs[0].report, runs[1].report) if __name__ == "__main__": diff --git a/tests/e2e/src/sqlbuild/cli/commands/main/compile/test_native_type_system.py b/tests/e2e/src/sqlbuild/cli/commands/main/compile/test_native_type_system.py index 8ef07ce0b8..cab39a8bab 100644 --- a/tests/e2e/src/sqlbuild/cli/commands/main/compile/test_native_type_system.py +++ b/tests/e2e/src/sqlbuild/cli/commands/main/compile/test_native_type_system.py @@ -1,4 +1,4 @@ -"""Every engine reports contract types and failures alike; native engines compare types natively.""" +"""Both engines report contract types and failures alike and compare types natively.""" from __future__ import annotations @@ -45,9 +45,6 @@ SELECT order_id, amount AS total FROM __ref("orders") """ -_NO_NATIVE_ANSWERS: NativeTypeAnswers = NativeTypeAnswers( - normalized=[], typed_comparisons=0, handbacks=0 -) _IMMEDIATE_PROMOTION_TOML: str = ( _PROJECT_TOML + '\n[settings]\ntable_promotion_mode = "immediate"\n' ) @@ -148,7 +145,7 @@ ], ids=lambda case: case.description, ) -def test_given_contract_types_when_compiling_with_each_engine_then_reports_match_python( +def test_given_contract_types_when_compiling_with_each_engine_then_reports_are_expected( test_case: NativeTypeSystemTestCase, tmp_path: Path, monkeypatch: pytest.MonkeyPatch, @@ -163,22 +160,17 @@ def test_given_contract_types_when_compiling_with_each_engine_then_reports_match monkeypatch=monkeypatch, capsys=capsys, ) - for engine in ("python", "native", "native-preview") + for engine in ("native", "native-preview") } - python_run, python_answers = outcomes["python"] native_run, native_answers = outcomes["native"] preview_run, preview_answers = outcomes["native-preview"] - assert (python_run.returncode, native_run.returncode, preview_run.returncode) == ( - (test_case.expected_exit_code,) * 3 - ) - assert test_case.expected_report_text in python_run.report - assert report_without_engine(native_run) == report_without_engine(python_run) - assert report_without_engine(preview_run) == report_without_engine(python_run) - assert (native_run.compiled, preview_run.compiled) == (python_run.compiled,) * 2 - assert python_answers == _NO_NATIVE_ANSWERS + assert (native_run.returncode, preview_run.returncode) == (test_case.expected_exit_code,) * 2 + assert test_case.expected_report_text in native_run.report + assert report_without_engine(preview_run) == report_without_engine(native_run) + assert preview_run.compiled == native_run.compiled assert native_answers == preview_answers - assert (native_answers.typed_comparisons >= 1, native_answers.handbacks) == (True, 0) + assert native_answers.typed_comparisons >= 1 if __name__ == "__main__": diff --git a/tests/e2e/src/sqlbuild/cli/commands/main/compile/test_reference_call_syntax.py b/tests/e2e/src/sqlbuild/cli/commands/main/compile/test_reference_call_syntax.py index d61d49961a..9e35a28c5d 100644 --- a/tests/e2e/src/sqlbuild/cli/commands/main/compile/test_reference_call_syntax.py +++ b/tests/e2e/src/sqlbuild/cli/commands/main/compile/test_reference_call_syntax.py @@ -26,11 +26,6 @@ @pytest.mark.parametrize( "test_case", [ - ReplaceableReferenceCallTestCase( - description="python engine builds double quoted references", - engine="python", - expected_total_cents="2850", - ), ReplaceableReferenceCallTestCase( description="native engine builds double quoted references", engine="native", @@ -62,78 +57,6 @@ def test_given_double_quoted_reference_calls_when_building_then_relations_resolv @pytest.mark.parametrize( "test_case", [ - RejectedReferenceCallTestCase( - description="python engine rejects unquoted ref name", - engine="python", - staging_from=_CANONICAL_SOURCE, - mart_from="__ref(stg_orders)", - expected_diagnostics=( - ( - "P012", - "__ref(stg_orders) is not a valid __ref() call", - "models/marts/order_totals.sql", - 4, - 6, - '__ref() takes exactly one double-quoted name, with no comments or extra spaces inside the parentheses: __ref("stg_orders")', - ), - ), - ), - RejectedReferenceCallTestCase( - description="python engine rejects comment inside ref call", - engine="python", - staging_from=_CANONICAL_SOURCE, - mart_from="__ref( /* upstream */ 'stg_orders')", - expected_diagnostics=( - ( - "P012", - "__ref( /* upstream */ 'stg_orders') is not a valid __ref() call", - "models/marts/order_totals.sql", - 4, - 6, - '__ref() takes exactly one double-quoted name, with no comments or extra spaces inside the parentheses: __ref("stg_orders")', - ), - ), - ), - RejectedReferenceCallTestCase( - description="python engine rejects single quoted source name", - engine="python", - staging_from="__source('raw_orders')", - mart_from=_CANONICAL_REF, - expected_diagnostics=( - ( - "P012", - "__source('raw_orders') is not a valid __source() call", - "models/staging/stg_orders.sql", - 3, - 36, - '__source() takes exactly one double-quoted name, with no comments or extra spaces inside the parentheses: __source("raw_orders")', - ), - ), - ), - RejectedReferenceCallTestCase( - description="python engine rejects invalid calls in two files", - engine="python", - staging_from="__source('raw_orders')", - mart_from="__ref(stg_orders)", - expected_diagnostics=( - ( - "P012", - "__ref(stg_orders) is not a valid __ref() call", - "models/marts/order_totals.sql", - 4, - 6, - '__ref() takes exactly one double-quoted name, with no comments or extra spaces inside the parentheses: __ref("stg_orders")', - ), - ( - "P012", - "__source('raw_orders') is not a valid __source() call", - "models/staging/stg_orders.sql", - 3, - 36, - '__source() takes exactly one double-quoted name, with no comments or extra spaces inside the parentheses: __source("raw_orders")', - ), - ), - ), RejectedReferenceCallTestCase( description="native engine rejects unquoted ref name", engine="native", diff --git a/tests/e2e/src/sqlbuild/cli/commands/main/test/test_direct_logic_extraction.py b/tests/e2e/src/sqlbuild/cli/commands/main/test/test_direct_logic_extraction.py index 5c2d4f0ccf..1806b513e0 100644 --- a/tests/e2e/src/sqlbuild/cli/commands/main/test/test_direct_logic_extraction.py +++ b/tests/e2e/src/sqlbuild/cli/commands/main/test/test_direct_logic_extraction.py @@ -222,34 +222,6 @@ @pytest.mark.parametrize( "test_case", [ - DirectLogicExtractionE2ETestCase( - description="macro, UDF and table-function tests pass on python", - engine="python", - overrides={}, - expected_exit_code=0, - expected_output_fragments=_PASSING_FRAGMENTS, - ), - DirectLogicExtractionE2ETestCase( - description="a quoted CTE name is a located error on python", - engine="python", - overrides=_QUOTED_NAME, - expected_exit_code=1, - expected_output_fragments=_QUOTED_NAME_FRAGMENTS, - ), - DirectLogicExtractionE2ETestCase( - description="a macro-test helper calling a UDF is rejected on python", - engine="python", - overrides=_HELPER_CALLS_UDF, - expected_exit_code=1, - expected_output_fragments=_HELPER_CALLS_UDF_FRAGMENTS, - ), - DirectLogicExtractionE2ETestCase( - description="a malformed helper reference is P012 at its call on python", - engine="python", - overrides=_MALFORMED_SOURCE, - expected_exit_code=1, - expected_output_fragments=_MALFORMED_SOURCE_FRAGMENTS, - ), DirectLogicExtractionE2ETestCase( description="macro, UDF and table-function tests pass on native", engine="native", @@ -306,27 +278,6 @@ expected_exit_code=1, expected_output_fragments=_MALFORMED_SOURCE_FRAGMENTS, ), - DirectLogicExtractionE2ETestCase( - description="a CTE name in an indented model test is located exactly on python", - engine="python", - overrides=_LOCATED_MODEL_NAME, - expected_exit_code=1, - expected_output_fragments=_LOCATED_MODEL_NAME_FRAGMENTS, - ), - DirectLogicExtractionE2ETestCase( - description="a CTE name in a test with cases is located exactly on python", - engine="python", - overrides=_LOCATED_CASE_NAME, - expected_exit_code=1, - expected_output_fragments=_LOCATED_CASE_NAME_FRAGMENTS, - ), - DirectLogicExtractionE2ETestCase( - description="each repeated malformed reference is P012 at its own call on python", - engine="python", - overrides=_REPEATED_MALFORMED_SOURCE, - expected_exit_code=1, - expected_output_fragments=_REPEATED_MALFORMED_SOURCE_FRAGMENTS, - ), DirectLogicExtractionE2ETestCase( description="a CTE name in an indented model test is located exactly on native", engine="native", @@ -369,20 +320,6 @@ expected_exit_code=1, expected_output_fragments=_REPEATED_MALFORMED_SOURCE_FRAGMENTS, ), - DirectLogicExtractionE2ETestCase( - description="aliased IS [NOT] DISTINCT FROM and list projections pass on python", - engine="python", - overrides=_ALIASED_OPERATORS, - expected_exit_code=0, - expected_output_fragments=_PASSING_FRAGMENTS, - ), - DirectLogicExtractionE2ETestCase( - description="an unaliased IS DISTINCT FROM projection is rejected on python", - engine="python", - overrides=_UNALIASED_DISTINCT_FROM, - expected_exit_code=1, - expected_output_fragments=_UNALIASED_DISTINCT_FROM_FRAGMENTS, - ), DirectLogicExtractionE2ETestCase( description="aliased IS [NOT] DISTINCT FROM and list projections pass on native", engine="native", diff --git a/tests/e2e/src/sqlbuild/cli/commands/main/test/test_helper_references.py b/tests/e2e/src/sqlbuild/cli/commands/main/test/test_helper_references.py index 1e9027c222..09022ef7c6 100644 --- a/tests/e2e/src/sqlbuild/cli/commands/main/test/test_helper_references.py +++ b/tests/e2e/src/sqlbuild/cli/commands/main/test/test_helper_references.py @@ -25,84 +25,6 @@ @pytest.mark.parametrize( "test_case", ( - HelperReferenceE2ETestCase( - description="helper and assertion read the model on the python engine", - tests=("helper_and_assertion_read_model",), - command=("--no-color", "test"), - engine="python", - sql_analysis=True, - expected_output_fragments=("PASS=1 FAIL=0 TOTAL=1", "assertion doubles_amount"), - expected_compiled_fragments=("\n__helper__doubled AS (",), - expected_absent_compiled_fragments=("__ref(",), - ), - HelperReferenceE2ETestCase( - description="only a helper reads the model on the python engine", - tests=("only_helper_reads_model",), - command=("--no-color", "test", "--select", "item_totals"), - engine="python", - sql_analysis=True, - expected_output_fragments=("1 selected", "PASS=1 FAIL=0 TOTAL=1"), - expected_compiled_fragments=("\n__ref__item_totals AS (",), - expected_absent_compiled_fragments=("__ref(",), - ), - HelperReferenceE2ETestCase( - description="helper reads a helper and a mock on the python engine", - tests=("helper_reads_helper_and_mock",), - command=("--no-color", "test"), - engine="python", - sql_analysis=True, - expected_output_fragments=( - "PASS=1 FAIL=0 TOTAL=1", - "assertion doubles_mocked_amount", - ), - expected_compiled_fragments=("\n__helper__joined AS (",), - expected_absent_compiled_fragments=("__ref(",), - ), - HelperReferenceE2ETestCase( - description="inlined helpers read by expected rows and assertions on the python engine", - tests=("helper_reads_helper_and_mock",), - command=("--no-color", "test"), - engine="python", - sql_analysis=False, - expected_output_fragments=( - "PASS=1 FAIL=0 TOTAL=1", - "assertion doubles_mocked_amount", - ), - expected_compiled_fragments=( - "(WITH doubled AS (SELECT item_id, amount_doubled FROM __ref__item_totals)", - ), - expected_absent_compiled_fragments=("__ref(", "__helper__"), - ), - HelperReferenceE2ETestCase( - description="helper and assertion read a mocked model on the python engine", - tests=("mocked_model_read_by_helper_and_assertion",), - command=("--no-color", "test"), - engine="python", - sql_analysis=True, - expected_output_fragments=("PASS=1 FAIL=0 TOTAL=1", "assertion doubles_amount"), - expected_compiled_fragments=("\n__helper__doubled AS (",), - expected_absent_compiled_fragments=("__ref(",), - ), - HelperReferenceE2ETestCase( - description="unread helpers and mocks are ignored on the python engine", - tests=("unread_helpers_and_mocks",), - command=("--no-color", "test"), - engine="python", - sql_analysis=True, - expected_output_fragments=("PASS=1 FAIL=0 TOTAL=1",), - expected_compiled_fragments=(), - expected_absent_compiled_fragments=("archived_rows", "other_rows", "__ref("), - ), - HelperReferenceE2ETestCase( - description="unread helpers add no tested models on the python engine", - tests=("unread_helpers_and_mocks",), - command=("--no-color", "test", "--select", "item_extras"), - engine="python", - sql_analysis=True, - expected_output_fragments=("0 selected",), - expected_compiled_fragments=(), - expected_absent_compiled_fragments=("archived_rows", "other_rows"), - ), HelperReferenceE2ETestCase( description="helper and assertion read the model on the native engine", tests=("helper_and_assertion_read_model",), @@ -181,44 +103,6 @@ expected_compiled_fragments=(), expected_absent_compiled_fragments=("archived_rows", "other_rows"), ), - HelperReferenceE2ETestCase( - description="expected rows and assertion read a mock on the python engine", - tests=("mocked_model_read_by_expected_and_assertion",), - command=("--no-color", "test"), - engine="python", - sql_analysis=True, - expected_output_fragments=( - "PASS=1 FAIL=0 TOTAL=1", - "assertion reads_mocked_items", - ), - expected_compiled_fragments=( - "SELECT item_id, amount * 2 AS amount_doubled FROM __ref__items", - "SELECT item_id FROM __ref__items WHERE item_id <> 7 OR amount <> 5", - ), - expected_absent_compiled_fragments=( - "__ref(", - "SELECT 1 AS item_id, 10 AS amount", - ), - ), - HelperReferenceE2ETestCase( - description="expected rows and assertion read a mock on the python engine without sql analysis", - tests=("mocked_model_read_by_expected_and_assertion",), - command=("--no-color", "test"), - engine="python", - sql_analysis=False, - expected_output_fragments=( - "PASS=1 FAIL=0 TOTAL=1", - "assertion reads_mocked_items", - ), - expected_compiled_fragments=( - "SELECT item_id, amount * 2 AS amount_doubled FROM __ref__items", - "SELECT item_id FROM __ref__items WHERE item_id <> 7 OR amount <> 5", - ), - expected_absent_compiled_fragments=( - "__ref(", - "SELECT 1 AS item_id, 10 AS amount", - ), - ), HelperReferenceE2ETestCase( description="expected rows and assertion read a mock on the native engine", tests=("mocked_model_read_by_expected_and_assertion",), @@ -295,29 +179,6 @@ "SELECT 1 AS item_id, 10 AS amount", ), ), - HelperReferenceE2ETestCase( - description="selecting a mocked model does not select its test on the python engine", - tests=("mocked_model_read_by_expected_and_assertion",), - command=("--no-color", "test", "--select", "items"), - engine="python", - sql_analysis=True, - expected_output_fragments=("0 selected",), - expected_compiled_fragments=(), - expected_absent_compiled_fragments=("__ref(",), - ), - HelperReferenceE2ETestCase( - description="expected rows read an unmocked model the test runs on the python engine", - tests=("expected_reads_unmocked_model",), - command=("--no-color", "test", "--select", "item_extras"), - engine="python", - sql_analysis=True, - expected_output_fragments=( - "1 selected", - "PASS=1 FAIL=0 TOTAL=1", - ), - expected_compiled_fragments=("amount * 2 AS amount_doubled FROM __ref__item_extras",), - expected_absent_compiled_fragments=("__ref(",), - ), HelperReferenceE2ETestCase( description="selecting a mocked model does not select its test on the native engine", tests=("mocked_model_read_by_expected_and_assertion",), @@ -364,36 +225,6 @@ expected_compiled_fragments=("amount * 2 AS amount_doubled FROM __ref__item_extras",), expected_absent_compiled_fragments=("__ref(",), ), - HelperReferenceE2ETestCase( - description="unread helper named like a column reads an unknown model on the python engine", - tests=("helper_named_like_column_reads_unknown_model",), - command=("--no-color", "test"), - engine="python", - sql_analysis=True, - expected_output_fragments=("PASS=1 FAIL=0 TOTAL=1",), - expected_compiled_fragments=(), - expected_absent_compiled_fragments=("__ref(", "item_archive"), - ), - HelperReferenceE2ETestCase( - description="unread helper named like a column reads an unknown model on the python engine without sql analysis", - tests=("helper_named_like_column_reads_unknown_model",), - command=("--no-color", "test"), - engine="python", - sql_analysis=False, - expected_output_fragments=("PASS=1 FAIL=0 TOTAL=1",), - expected_compiled_fragments=(), - expected_absent_compiled_fragments=("__ref(", "item_archive"), - ), - HelperReferenceE2ETestCase( - description="unread helper named like a column selects no model on the python engine", - tests=("helper_named_like_column_reads_model",), - command=("--no-color", "test", "--select", "item_extras"), - engine="python", - sql_analysis=True, - expected_output_fragments=("0 selected",), - expected_compiled_fragments=(), - expected_absent_compiled_fragments=("__ref(", "__ref__item_extras"), - ), HelperReferenceE2ETestCase( description="unread helper named like a column reads an unknown model on the native engine", tests=("helper_named_like_column_reads_unknown_model",), @@ -497,46 +328,6 @@ def test_given_helper_cte_references_when_testing_then_helpers_read_the_tested_m @pytest.mark.parametrize( "test_case", ( - HelperReferenceErrorE2ETestCase( - description="helpers reading each other on the python engine", - test_name="helper_cycle", - engine="python", - expected_code="P013", - expected_message=( - "SQL test CTE 'first_rows' reads itself through 'first_rows' -> " - "'second_rows' -> 'first_rows', so the test query cannot define its CTEs in " - "dependency order" - ), - expected_line=7, - expected_column=1, - expected_help_fragment="shared_rows AS (SELECT ...)", - ), - HelperReferenceErrorE2ETestCase( - description="helper reading an unknown model on the python engine", - test_name="helper_reads_unknown_model", - engine="python", - expected_code="P013", - expected_message=( - "SQL test helper CTE 'missing_rows' references unknown model 'item_archive'" - ), - expected_line=7, - expected_column=38, - expected_help_fragment='__ref("")', - ), - HelperReferenceErrorE2ETestCase( - description="mock reading a helper that reads a model on the python engine", - test_name="mock_reads_referencing_helper", - engine="python", - expected_code="P013", - expected_message=( - "SQL test mock '__ref__items' reads helper CTE 'base_rows', which calls " - '__ref("item_totals"); mocks and fixtures are defined before the models the ' - "test runs, so the helper cannot be resolved for them" - ), - expected_line=7, - expected_column=35, - expected_help_fragment='FROM __ref__item_totals rather than FROM __ref("item_totals")', - ), HelperReferenceErrorE2ETestCase( description="helpers reading each other on the native engine", test_name="helper_cycle", @@ -577,49 +368,6 @@ def test_given_helper_cte_references_when_testing_then_helpers_read_the_tested_m expected_column=35, expected_help_fragment='FROM __ref__item_totals rather than FROM __ref("item_totals")', ), - HelperReferenceErrorE2ETestCase( - description="assertion reading an unmocked source on the python engine", - test_name="assertion_reads_unmocked_source", - engine="python", - expected_code="P013", - expected_message=( - "SQL test assertion CTE '__assert__no_returns' calls " - '__source("item_returns"), which the test does not mock, so the test query ' - "cannot resolve it" - ), - expected_line=11, - expected_column=23, - expected_help_fragment="__source__item_returns AS (SELECT ...)", - ), - HelperReferenceErrorE2ETestCase( - description="test reading only mocks on the python engine", - test_name="assertion_reads_only_mocks", - engine="python", - expected_code="P013", - expected_message=( - "SQL test 'assertion_reads_only_mocks' mocks the model it tests (__ref__items), " - "so the test has no model to run against" - ), - expected_line=8, - expected_column=23, - expected_help_fragment=( - "Mock the model's inputs instead (for example __source__ or " - '__ref__) and keep __ref("items")' - ), - ), - HelperReferenceErrorE2ETestCase( - description="expected rows reading an unknown model on the python engine", - test_name="expected_reads_unknown_model", - engine="python", - expected_code="P013", - expected_message=( - "SQL test expected CTE '__expected__item_totals' references unknown model " - "'item_archive'" - ), - expected_line=8, - expected_column=39, - expected_help_fragment='__ref("")', - ), HelperReferenceErrorE2ETestCase( description="assertion reading an unmocked source on the native engine", test_name="assertion_reads_unmocked_source", @@ -706,60 +454,6 @@ def test_given_helper_cte_references_when_testing_then_helpers_read_the_tested_m expected_column=39, expected_help_fragment='__ref("")', ), - HelperReferenceErrorE2ETestCase( - description="a mock a check calls reading a referencing helper through a middle helper on the python engine", - test_name="mock_called_reads_referencing_helper", - engine="python", - expected_code="P013", - expected_message=( - "SQL test mock '__source__item_returns' reads helper CTE 'extras', which calls " - '__ref("item_extras"); mocks and fixtures are defined before the models the ' - "test runs, so the helper cannot be resolved for them" - ), - expected_line=4, - expected_column=40, - expected_help_fragment='FROM __ref__item_extras rather than FROM __ref("item_extras")', - ), - HelperReferenceErrorE2ETestCase( - description="a mock a check calls reading a referencing helper directly on the python engine", - test_name="mock_called_reads_referencing_helper_directly", - engine="python", - expected_code="P013", - expected_message=( - "SQL test mock '__source__item_returns' reads helper CTE 'extras', which calls " - '__ref("item_extras"); mocks and fixtures are defined before the models the ' - "test runs, so the helper cannot be resolved for them" - ), - expected_line=4, - expected_column=40, - expected_help_fragment='FROM __ref__item_extras rather than FROM __ref("item_extras")', - ), - HelperReferenceErrorE2ETestCase( - description="test reading a mocked source and a mocked model on the python engine", - test_name="assertion_reads_mocked_source_and_model", - engine="python", - expected_code="P013", - expected_message=( - "SQL test 'assertion_reads_mocked_source_and_model' mocks the model it tests " - "(__ref__items), so the test has no model to run against" - ), - expected_line=10, - expected_column=8, - expected_help_fragment='and keep __ref("items") in the __assert__ or __expected__ CTE', - ), - HelperReferenceErrorE2ETestCase( - description="test reading a mocked model by CTE name on the python engine", - test_name="assertion_reads_mock_by_name", - engine="python", - expected_code="P013", - expected_message=( - "SQL test 'assertion_reads_mock_by_name' mocks the model it tests (__ref__items), " - "so the test has no model to run against" - ), - expected_line=8, - expected_column=23, - expected_help_fragment='and call __ref("items") in the __assert__ or __expected__ CTE', - ), HelperReferenceErrorE2ETestCase( description="a mock a check calls reading a referencing helper through a middle helper on the native engine", test_name="mock_called_reads_referencing_helper", @@ -901,12 +595,6 @@ def test_given_unresolvable_helper_references_when_compiling_then_compile_report @pytest.mark.parametrize( "test_case", ( - HelperRedefinitionE2ETestCase( - description="nested CTE redefining a helper on the python engine", - engine="python", - expected_output_fragments=("error[P001]", "which redefines helper CTE 'doubled'"), - expected_absent_output_fragments=("P013",), - ), HelperRedefinitionE2ETestCase( description="nested CTE redefining a helper on the native engine", engine="native", diff --git a/tests/goldens/python_oracle/analysis_cyclic_a_ref_cycle_a_model_reading_itself_and_a_star_consumer_of_the_cycle.json b/tests/goldens/python_oracle/analysis_cyclic_a_ref_cycle_a_model_reading_itself_and_a_star_consumer_of_the_cycle.json new file mode 100644 index 0000000000..84e00f8f26 --- /dev/null +++ b/tests/goldens/python_oracle/analysis_cyclic_a_ref_cycle_a_model_reading_itself_and_a_star_consumer_of_the_cycle.json @@ -0,0 +1,134 @@ +[ +[ +"shapes", +"75c111c4221d031b0df0f644" +], +[ +"models", +{ +"order_audit": "102a144114b4a8a3e464d565", +"order_summary": "ca21b0318683cc6b7506af3d", +"orders": "412acfefd9b029b3a46752c7", +"returns": "0d43c64379f12801c6a42e57" +} +], +[ +"catalog", +"2b8932e9fd162ab0b58d4e8f" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"shapes", +"75c111c4221d031b0df0f644" +], +[ +"models", +{ +"order_audit": "102a144114b4a8a3e464d565", +"order_summary": "ca21b0318683cc6b7506af3d", +"orders": "6a1622e4397f1eef49fe9b3b", +"returns": "0d43c64379f12801c6a42e57" +} +], +[ +"catalog", +"2b8932e9fd162ab0b58d4e8f" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"shapes", +"75c111c4221d031b0df0f644" +], +[ +"models", +{ +"order_audit": "102a144114b4a8a3e464d565", +"order_summary": "ca21b0318683cc6b7506af3d", +"orders": "412acfefd9b029b3a46752c7", +"returns": "0d43c64379f12801c6a42e57" +} +], +[ +"catalog", +"2b8932e9fd162ab0b58d4e8f" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"shapes", +"75c111c4221d031b0df0f644" +], +[ +"models", +{ +"order_audit": "102a144114b4a8a3e464d565", +"order_summary": "ca21b0318683cc6b7506af3d", +"orders": "6a1622e4397f1eef49fe9b3b", +"returns": "50c61ef317c36e693b607753" +} +], +[ +"catalog", +"2b8932e9fd162ab0b58d4e8f" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +] +] diff --git a/tests/goldens/python_oracle/analysis_generated_a_project_local_adapter_s_own_nullability_rules_called_back_natively.json b/tests/goldens/python_oracle/analysis_generated_a_project_local_adapter_s_own_nullability_rules_called_back_natively.json new file mode 100644 index 0000000000..489f0beb0c --- /dev/null +++ b/tests/goldens/python_oracle/analysis_generated_a_project_local_adapter_s_own_nullability_rules_called_back_natively.json @@ -0,0 +1,626 @@ +[ +[ +"shapes", +"78e5cd70ce361d823798634b" +], +[ +"models", +{ +"adapter_rules_cte": "dfd1ab68201bde357955ba7f", +"adapter_rules_staging": "1647edbe8ac61356261cfa76", +"adapter_rules_untyped_cte": "6d7a85f4f3ff37fb43fdc0b4", +"dotless_i_staging": "4c25b6514c8939c1579e7729", +"long_s_cte": "22aa6898e4deee5e707a61c8", +"long_s_staging": "c70692ed48ec89dc344df4e0", +"orders_model_0": "c380ae05f3bd0627628ab6fc", +"orders_model_1": "df6e4a58863118447ccd6a56", +"orders_model_10": "bcbd615c256c35337aed2db2", +"orders_model_11": "47923badaec7c00915e5b4bb", +"orders_model_12": "1cc095a7cdb49d517637e721", +"orders_model_13": "800b7f2cfae2d608b60c7ece", +"orders_model_14": "22c002e97f6de1fe4b9cdccd", +"orders_model_15": "eebd1c2c0322fa13fdc75504", +"orders_model_16": "2717ab2a04d761545073308b", +"orders_model_17": "8255e9b0e9b9fb715e5d1f58", +"orders_model_18": "28541fce67c204773859236c", +"orders_model_19": "9f23b26f2c338b8fc3e3e838", +"orders_model_2": "5a185b79563abbd167d23c9e", +"orders_model_20": "d594752e20c6f55a9ca9a40e", +"orders_model_21": "0b71c12f30a7617191bc2e17", +"orders_model_22": "50215bcfc3981855df918ff1", +"orders_model_23": "2c1c11368b18534a2e433f73", +"orders_model_3": "f530981ae0183c1746020b51", +"orders_model_4": "e29709e8e7acb44cc782304f", +"orders_model_5": "0c6b7057337af7825d4f5905", +"orders_model_6": "4308568a0bb439fb417623b4", +"orders_model_7": "f9be9d8e81fbd30196a2ba14", +"orders_model_8": "be94f9981f346459dd08eb00", +"orders_model_9": "7a96226f82f52625a17f825f", +"payment_totals": "8cf82ad30e9cce84bc8a3529", +"payments_by_customer": "9e1265b9f4134636cb508259", +"pivot_0": "18ecbe5e93fe3ced5cbfd24a", +"pivot_1": "8ffb88803fba96f5e1a0cc14", +"pivot_2": "af151ba34f16c141fdee1ac3", +"pivot_3": "8d7a74ec77a418a6a2641b84", +"status_amounts": "0fbfc8d810e430c5814769d6", +"status_passthrough": "57dbca31518ecf81d68ec4fe", +"umlaut_cte": "a4c1810f1e46ef2200a87309" +} +], +[ +"catalog", +"d360424e65e4f8f287f9a397" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"20e6b6374d63663154468bed" +], +[ +"proof", +"20e6b6374d63663154468bed" +], +[ +"proof", +"b9689124495085d917d65ebf" +], +[ +"proof", +"0d91dfe8eefbbb36998db250" +], +[ +"proof", +"28c524727756a048843237ef" +], +[ +"proof", +"99b1ccea692774bb61737217" +], +[ +"shapes", +"78e5cd70ce361d823798634b" +], +[ +"models", +{ +"adapter_rules_cte": "dfd1ab68201bde357955ba7f", +"adapter_rules_staging": "1647edbe8ac61356261cfa76", +"adapter_rules_untyped_cte": "6d7a85f4f3ff37fb43fdc0b4", +"dotless_i_staging": "4c25b6514c8939c1579e7729", +"long_s_cte": "22aa6898e4deee5e707a61c8", +"long_s_staging": "c70692ed48ec89dc344df4e0", +"orders_model_0": "dc7f3dec778fd7cc3b47de47", +"orders_model_1": "372f6fed52ac7b76d5703db0", +"orders_model_10": "e0d9b7a41394deecb38e3086", +"orders_model_11": "a74efc4485502093e7925022", +"orders_model_12": "159cce49ef0548e95a5b46fe", +"orders_model_13": "03539cfdeb6da7bf1e9fe042", +"orders_model_14": "3fdd19b40a943161f6c6cc9e", +"orders_model_15": "ca04925bf918b53768e0398d", +"orders_model_16": "e29709e8e7acb44cc782304f", +"orders_model_17": "b98505b8785820593e460502", +"orders_model_18": "86967e1e1505ff93a0965cef", +"orders_model_19": "966cc0c652215c4b0d249ec4", +"orders_model_2": "835e887650bbf9b124ae26b1", +"orders_model_20": "84ef045e4fbe323e09d9d96b", +"orders_model_21": "ab446571e5d18dc83a4b3cf5", +"orders_model_22": "f1de8641e65deae07a766a44", +"orders_model_23": "8c59f6a9f31545711675187a", +"orders_model_3": "000b4e41decb10da91684d6e", +"orders_model_4": "bf62990d9480cf71956fd3c9", +"orders_model_5": "0a4ba3dd4c01cce9c3179015", +"orders_model_6": "36c156c5a6601badf8124464", +"orders_model_7": "2cc4699fcfbfc50f29d34e4d", +"orders_model_8": "ebd5177365eb50337f61b39a", +"orders_model_9": "a0b1dba8f656eaa0bfb2c9dd", +"payment_totals": "8cf82ad30e9cce84bc8a3529", +"payments_by_customer": "9e1265b9f4134636cb508259", +"pivot_0": "af151ba34f16c141fdee1ac3", +"pivot_1": "db45532b4aa0746bb6155579", +"pivot_2": "60093df965b22d2f7c809ce4", +"pivot_3": "335dfa47b776524b62ee26e6", +"status_amounts": "0fbfc8d810e430c5814769d6", +"status_passthrough": "57dbca31518ecf81d68ec4fe", +"umlaut_cte": "a4c1810f1e46ef2200a87309" +} +], +[ +"catalog", +"05058c2d6069f67034746afd" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"b9689124495085d917d65ebf" +], +[ +"proof", +"0d91dfe8eefbbb36998db250" +], +[ +"proof", +"4994bb2a572acbed6354a2bb" +], +[ +"proof", +"c3cb3226e55a418829fd059c" +], +[ +"proof", +"28c524727756a048843237ef" +], +[ +"proof", +"99b1ccea692774bb61737217" +], +[ +"shapes", +"78e5cd70ce361d823798634b" +], +[ +"models", +{ +"adapter_rules_cte": "dfd1ab68201bde357955ba7f", +"adapter_rules_staging": "1647edbe8ac61356261cfa76", +"adapter_rules_untyped_cte": "6d7a85f4f3ff37fb43fdc0b4", +"dotless_i_staging": "4c25b6514c8939c1579e7729", +"long_s_cte": "22aa6898e4deee5e707a61c8", +"long_s_staging": "c70692ed48ec89dc344df4e0", +"orders_model_0": "c380ae05f3bd0627628ab6fc", +"orders_model_1": "172c86dd8351e7740e167082", +"orders_model_10": "1348402b074ad555891e4bef", +"orders_model_11": "e0a1bcae33bbfb164c9468f6", +"orders_model_12": "0fbd9a675ff8d8560b0540a4", +"orders_model_13": "c414c20d1ede816d6b319333", +"orders_model_14": "d1550c8ea359faa939c59092", +"orders_model_15": "e0a6f9cf7645c417bdbdb2f3", +"orders_model_16": "6a3eeb4e49931817e15eec3a", +"orders_model_17": "d2f93646b187586cdc2ad5b6", +"orders_model_18": "252b1614ef32811f90405d55", +"orders_model_19": "20835381aab849fd35068525", +"orders_model_2": "541aad8bbf10a165003da4fa", +"orders_model_20": "9bb3b6be8506e6c3e809177f", +"orders_model_21": "c87751fbd20922b30ba3d847", +"orders_model_22": "264e63bb81a8673659bbb9db", +"orders_model_23": "ed8580ec8dc574a2041c68ee", +"orders_model_3": "4b659372639f55ac9ed99d36", +"orders_model_4": "c1496cb11408177cb813ba21", +"orders_model_5": "2d52cab3dcd8a4c198f59410", +"orders_model_6": "5ccadf27b4bf1a37e0f30682", +"orders_model_7": "16fc9c0348ca5eadfd147e95", +"orders_model_8": "1a1778883746da694b7922e3", +"orders_model_9": "7a96226f82f52625a17f825f", +"payment_totals": "8cf82ad30e9cce84bc8a3529", +"payments_by_customer": "9e1265b9f4134636cb508259", +"pivot_0": "d7685388e49eb5b076c776ac", +"pivot_1": "60093df965b22d2f7c809ce4", +"pivot_2": "b4bb4c1927b422d4b8b9ebb9", +"pivot_3": "a3b575dd05964ac460755bbd", +"status_amounts": "0fbfc8d810e430c5814769d6", +"status_passthrough": "57dbca31518ecf81d68ec4fe", +"umlaut_cte": "a4c1810f1e46ef2200a87309" +} +], +[ +"catalog", +"249032d056c80b1ec4ee3cea" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"0d91dfe8eefbbb36998db250" +], +[ +"proof", +"4994bb2a572acbed6354a2bb" +], +[ +"proof", +"28c524727756a048843237ef" +], +[ +"proof", +"15cac1a9d4a0c399d20eec68" +], +[ +"proof", +"28c524727756a048843237ef" +], +[ +"proof", +"99b1ccea692774bb61737217" +] +] diff --git a/tests/goldens/python_oracle/analysis_generated_rich_lineage_over_untyped_inputs_cte_facts_and_contracts.json b/tests/goldens/python_oracle/analysis_generated_rich_lineage_over_untyped_inputs_cte_facts_and_contracts.json new file mode 100644 index 0000000000..4ec7fcb8f0 --- /dev/null +++ b/tests/goldens/python_oracle/analysis_generated_rich_lineage_over_untyped_inputs_cte_facts_and_contracts.json @@ -0,0 +1,3458 @@ +[ +[ +"shapes", +"78e5cd70ce361d823798634b" +], +[ +"models", +{ +"orders_model_0": "7dde13e57109cfb992bc623d", +"orders_model_1": "6f741725ae5781425358bc3b", +"orders_model_10": "c7e95ff7d90362e121ab238f", +"orders_model_11": "05479b1f55d5c854f9729a97", +"orders_model_12": "c380ae05f3bd0627628ab6fc", +"orders_model_13": "15537f706967682b808641f6", +"orders_model_14": "0506ac9813ca91fe571266cd", +"orders_model_15": "4ea093ff48f97c35927ecbbd", +"orders_model_16": "3dbaddb57a2ed5f8db44feda", +"orders_model_17": "ae6be31dbe60a1c0d17b30bc", +"orders_model_18": "6b0c7fdf2bf74107bd96a6ff", +"orders_model_19": "4782036882204544bf9b8cc0", +"orders_model_2": "2e71b399a66b78700dd48317", +"orders_model_20": "00d5932c856360eb282ca536", +"orders_model_21": "7a96226f82f52625a17f825f", +"orders_model_22": "74a4ef50a4b351777410e3ae", +"orders_model_23": "14b86bcb1a8edc065f4c7405", +"orders_model_3": "b1c72c923aea0b59f8745317", +"orders_model_4": "526ce0a1d0a274582f9d35f1", +"orders_model_5": "f9183611419f32c78a12fbc4", +"orders_model_6": "7a0c234309501030bdc80d53", +"orders_model_7": "f9be9d8e81fbd30196a2ba14", +"orders_model_8": "2e035b59097bd4547b20a7ca", +"orders_model_9": "7c6d6c8fb64f5bfb121ebac1", +"payment_totals": "ce8a97426d53e0acd6c49c2b", +"payments_by_customer": "da1968ec91b55f6f584c7ecd", +"pivot_0": "335dfa47b776524b62ee26e6", +"pivot_1": "78dd4b3d90301ccd1e781295", +"pivot_2": "3767f4902ed5f3ab1acc83a1", +"pivot_3": "826e0ad9aec9b04097d58b37", +"status_amounts": "0fbfc8d810e430c5814769d6", +"status_passthrough": "57dbca31518ecf81d68ec4fe" +} +], +[ +"catalog", +"7dae5e8f83fbe068e10fa8a1" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"20e6b6374d63663154468bed" +], +[ +"proof", +"ff4d4f462aae3b9e95d9a5ab" +], +[ +"proof", +"20e6b6374d63663154468bed" +], +[ +"proof", +"e718df74c851405aa9e05532" +], +[ +"proof", +"28c524727756a048843237ef" +], +[ +"proof", +"99b1ccea692774bb61737217" +], +[ +"shapes", +"b40871514fad0707c8cdbee7" +], +[ +"models", +{ +"orders_model_0": "7dde13e57109cfb992bc623d", +"orders_model_1": "6f741725ae5781425358bc3b", +"orders_model_10": "c7e95ff7d90362e121ab238f", +"orders_model_11": "05479b1f55d5c854f9729a97", +"orders_model_12": "c380ae05f3bd0627628ab6fc", +"orders_model_13": "c7fa6f64bedfc1611fad26ba", +"orders_model_14": "0506ac9813ca91fe571266cd", +"orders_model_15": "6fe127037935cdca6ceb3f6e", +"orders_model_16": "3dbaddb57a2ed5f8db44feda", +"orders_model_17": "7cc87d8c32df82057dc6057d", +"orders_model_18": "6b0c7fdf2bf74107bd96a6ff", +"orders_model_19": "2d58b808566d04184cf9ab29", +"orders_model_2": "27b686e0958c19d151cd6319", +"orders_model_20": "13b36d543da620ba9a151138", +"orders_model_21": "7a96226f82f52625a17f825f", +"orders_model_22": "74a4ef50a4b351777410e3ae", +"orders_model_23": "14b86bcb1a8edc065f4c7405", +"orders_model_3": "b1c72c923aea0b59f8745317", +"orders_model_4": "75f6764c319047022968f0b3", +"orders_model_5": "f4c3ccd3c76f843ac4bced8a", +"orders_model_6": "526c167cb476b3553de71042", +"orders_model_7": "f9be9d8e81fbd30196a2ba14", +"orders_model_8": "55ea0527456ec442813d63d5", +"orders_model_9": "7c6d6c8fb64f5bfb121ebac1", +"payment_totals": "e75b3088ecccbf453f472518", +"payments_by_customer": "e406a89772022ea3c32aefef", +"pivot_0": "335dfa47b776524b62ee26e6", +"pivot_1": "78dd4b3d90301ccd1e781295", +"pivot_2": "3767f4902ed5f3ab1acc83a1", +"pivot_3": "826e0ad9aec9b04097d58b37", +"status_amounts": "0fbfc8d810e430c5814769d6", +"status_passthrough": "57dbca31518ecf81d68ec4fe" +} +], +[ +"catalog", +"59adab814e12cc9aaaab308d" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"200eb30f2a045b54792500f6" +], +[ +"proof", +"200eb30f2a045b54792500f6" +], +[ +"proof", +"200eb30f2a045b54792500f6" +], +[ +"proof", +"200eb30f2a045b54792500f6" +], +[ +"proof", +"200eb30f2a045b54792500f6" +], +[ +"proof", +"200eb30f2a045b54792500f6" +], +[ +"shapes", +"78e5cd70ce361d823798634b" +], +[ +"models", +{ +"orders_model_0": "541418fef292ad4a9c6f8dab", +"orders_model_1": "ff37aa9e31c0ddbc7f05cba2", +"orders_model_10": "315f07530cae631f3e373e9d", +"orders_model_11": "05479b1f55d5c854f9729a97", +"orders_model_12": "94f95487333b2561382c2981", +"orders_model_13": "f73e95ff8968d95ed11dc4f3", +"orders_model_14": "0506ac9813ca91fe571266cd", +"orders_model_15": "4ea093ff48f97c35927ecbbd", +"orders_model_16": "1a6c68f8be75e24bf3304cdb", +"orders_model_17": "ae6be31dbe60a1c0d17b30bc", +"orders_model_18": "79cac6cd1f2e605da47e460d", +"orders_model_19": "2d58b808566d04184cf9ab29", +"orders_model_2": "2e71b399a66b78700dd48317", +"orders_model_20": "13b36d543da620ba9a151138", +"orders_model_21": "c669dc21fed757d7809fc424", +"orders_model_22": "066b8f5bf2be63a888045fe7", +"orders_model_23": "14b86bcb1a8edc065f4c7405", +"orders_model_3": "b1c72c923aea0b59f8745317", +"orders_model_4": "1cefa36f28721fe677e6a684", +"orders_model_5": "f9183611419f32c78a12fbc4", +"orders_model_6": "f3d71446fe7a0576e2049a7a", +"orders_model_7": "f9be9d8e81fbd30196a2ba14", +"orders_model_8": "55ea0527456ec442813d63d5", +"orders_model_9": "7c6d6c8fb64f5bfb121ebac1", +"payment_totals": "ddedaaeda0bdb9d9997ac6cd", +"payments_by_customer": "da1968ec91b55f6f584c7ecd", +"pivot_0": "335dfa47b776524b62ee26e6", +"pivot_1": "78dd4b3d90301ccd1e781295", +"pivot_2": "3767f4902ed5f3ab1acc83a1", +"pivot_3": "826e0ad9aec9b04097d58b37", +"status_amounts": "0fbfc8d810e430c5814769d6", +"status_passthrough": "bbd8b7298ce68a222ba84345" +} +], +[ +"catalog", +"9f8ce1f318b9262fd1b830ff" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"20e6b6374d63663154468bed" +], +[ +"proof", +"c67f69d1828d209a58642e36" +], +[ +"proof", +"c67f69d1828d209a58642e36" +], +[ +"proof", +"c67f69d1828d209a58642e36" +], +[ +"proof", +"c67f69d1828d209a58642e36" +], +[ +"proof", +"99b1ccea692774bb61737217" +], +[ +"shapes", +"c0d3bfda902cb95cd1564269" +], +[ +"models", +{ +"orders_model_0": "dc4da2070db56afde4157773", +"orders_model_1": "9b0cc36921b5b8b8a8dea025", +"orders_model_10": "d4f810ff3ba14295385d6fb9", +"orders_model_11": "f7cdb34524d45acad3b71f7d", +"orders_model_12": "c380ae05f3bd0627628ab6fc", +"orders_model_13": "11f35c6f0b5918adfca2c40f", +"orders_model_14": "0506ac9813ca91fe571266cd", +"orders_model_15": "26974efa98703503eb817f97", +"orders_model_16": "c5a645b8cfb02ddc927fc297", +"orders_model_17": "669b30fefd09621ed0f2ad55", +"orders_model_18": "60e19e6908bb5c06d38eeb01", +"orders_model_19": "5318b049f2f651a689fb5e87", +"orders_model_2": "361de61cfd22f09af946862f", +"orders_model_20": "407c766e409ebec28d0c232a", +"orders_model_21": "9c26876fe71c235386932362", +"orders_model_22": "86880e31d61c6c5522256c62", +"orders_model_23": "209048028aa76bf4c2bd28c6", +"orders_model_3": "3ed083bce693c01d151c8081", +"orders_model_4": "4c809f6cf2e946ba98b1ec73", +"orders_model_5": "a89cb10ab6dfef246cc36b07", +"orders_model_6": "a903f36871fea6d8ac818922", +"orders_model_7": "a4c400c5fa2da4107098339e", +"orders_model_8": "5400ca61f1ed2f29d89e2d23", +"orders_model_9": "67dc0f1b5ce04c8989ad1aca", +"payment_totals": "692528d52a5623a0e90d7fb4", +"payments_by_customer": "c29bf4a09e3c8e9cff564a2f", +"pivot_0": "335dfa47b776524b62ee26e6", +"pivot_1": "78dd4b3d90301ccd1e781295", +"pivot_2": "3767f4902ed5f3ab1acc83a1", +"pivot_3": "826e0ad9aec9b04097d58b37", +"status_amounts": "0fbfc8d810e430c5814769d6", +"status_passthrough": "26ba5a13355d37dfa8e67820" +} +], +[ +"catalog", +"c44c8633473bde950e573766" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"shapes", +"78e5cd70ce361d823798634b" +], +[ +"models", +{ +"orders_model_0": "7dde13e57109cfb992bc623d", +"orders_model_1": "73d5e99497d80b919e0d5491", +"orders_model_10": "31ba43d1ed6f0701481c543b", +"orders_model_11": "e68784174562f0ac8afbc614", +"orders_model_12": "7c1f7afa32f56956c9bb5806", +"orders_model_13": "3676088fa7438b6033da7334", +"orders_model_14": "c5aa1f63d80b5d306477c290", +"orders_model_15": "31fb137256076ba0126683aa", +"orders_model_16": "3122402ab671f4438c8209d7", +"orders_model_17": "769e25e737cf7832171d8837", +"orders_model_18": "7ccdde571d7f688040f1f47c", +"orders_model_19": "f9be9d8e81fbd30196a2ba14", +"orders_model_2": "b9162cfbc1ce5044c01cca42", +"orders_model_20": "1bb9c3971b4488e0b7023645", +"orders_model_21": "7c6d6c8fb64f5bfb121ebac1", +"orders_model_22": "5f2c3523ba8300fb944cc577", +"orders_model_23": "b760f8a3ed2b65af8ff70abc", +"orders_model_3": "f0f64c1baf69c4d7f0c75612", +"orders_model_4": "526ce0a1d0a274582f9d35f1", +"orders_model_5": "b0f2950e6d0c6c8ba60db1ca", +"orders_model_6": "38187a959e7cbbef799b5777", +"orders_model_7": "20835381aab849fd35068525", +"orders_model_8": "72717ea55695667a7b7d8b39", +"orders_model_9": "d34e456ade2ced8792534866", +"payment_totals": "ce8a97426d53e0acd6c49c2b", +"payments_by_customer": "da1968ec91b55f6f584c7ecd", +"pivot_0": "db45532b4aa0746bb6155579", +"pivot_1": "826e0ad9aec9b04097d58b37", +"pivot_2": "78dd4b3d90301ccd1e781295", +"pivot_3": "af151ba34f16c141fdee1ac3", +"status_amounts": "0fbfc8d810e430c5814769d6", +"status_passthrough": "57dbca31518ecf81d68ec4fe" +} +], +[ +"catalog", +"c17fe05b252117c41defdc1e" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"0d91dfe8eefbbb36998db250" +], +[ +"proof", +"24ec11d3b54173b8b7b769ff" +], +[ +"proof", +"c3cb3226e55a418829fd059c" +], +[ +"proof", +"b9689124495085d917d65ebf" +], +[ +"proof", +"28c524727756a048843237ef" +], +[ +"proof", +"99b1ccea692774bb61737217" +], +[ +"shapes", +"b40871514fad0707c8cdbee7" +], +[ +"models", +{ +"orders_model_0": "7dde13e57109cfb992bc623d", +"orders_model_1": "73d5e99497d80b919e0d5491", +"orders_model_10": "31ba43d1ed6f0701481c543b", +"orders_model_11": "3efd8cbce60b5adde2346a56", +"orders_model_12": "7c1f7afa32f56956c9bb5806", +"orders_model_13": "cc456ea2e83298c9cd8206fb", +"orders_model_14": "59968e869226ce12e62c6b5e", +"orders_model_15": "31fb137256076ba0126683aa", +"orders_model_16": "a6740f24eddec216a1afc653", +"orders_model_17": "769e25e737cf7832171d8837", +"orders_model_18": "099cb926af524f10d27cc108", +"orders_model_19": "f9be9d8e81fbd30196a2ba14", +"orders_model_2": "3a3bfc6019ae1cf18c714dd0", +"orders_model_20": "1bb9c3971b4488e0b7023645", +"orders_model_21": "7c6d6c8fb64f5bfb121ebac1", +"orders_model_22": "5f2c3523ba8300fb944cc577", +"orders_model_23": "4afbe759a7d6ab796db5ab1c", +"orders_model_3": "f0f64c1baf69c4d7f0c75612", +"orders_model_4": "75f6764c319047022968f0b3", +"orders_model_5": "b0f2950e6d0c6c8ba60db1ca", +"orders_model_6": "38187a959e7cbbef799b5777", +"orders_model_7": "20835381aab849fd35068525", +"orders_model_8": "63ebe9cbc63523f4c4adddb2", +"orders_model_9": "d34e456ade2ced8792534866", +"payment_totals": "e75b3088ecccbf453f472518", +"payments_by_customer": "e406a89772022ea3c32aefef", +"pivot_0": "db45532b4aa0746bb6155579", +"pivot_1": "826e0ad9aec9b04097d58b37", +"pivot_2": "78dd4b3d90301ccd1e781295", +"pivot_3": "e6d82b48a7a5593bd747ea69", +"status_amounts": "0fbfc8d810e430c5814769d6", +"status_passthrough": "57dbca31518ecf81d68ec4fe" +} +], +[ +"catalog", +"71c8c4df1603f87442ce9793" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"200eb30f2a045b54792500f6" +], +[ +"proof", +"200eb30f2a045b54792500f6" +], +[ +"proof", +"200eb30f2a045b54792500f6" +], +[ +"proof", +"200eb30f2a045b54792500f6" +], +[ +"proof", +"200eb30f2a045b54792500f6" +], +[ +"proof", +"200eb30f2a045b54792500f6" +], +[ +"shapes", +"78e5cd70ce361d823798634b" +], +[ +"models", +{ +"orders_model_0": "541418fef292ad4a9c6f8dab", +"orders_model_1": "828d747058993aeefdbae18a", +"orders_model_10": "9aefea09a1d167dbf49a2c69", +"orders_model_11": "e68784174562f0ac8afbc614", +"orders_model_12": "2cbf8e290082ab49db794db4", +"orders_model_13": "3676088fa7438b6033da7334", +"orders_model_14": "59968e869226ce12e62c6b5e", +"orders_model_15": "31fb137256076ba0126683aa", +"orders_model_16": "b67d418ac9424b16909d6a26", +"orders_model_17": "769e25e737cf7832171d8837", +"orders_model_18": "099cb926af524f10d27cc108", +"orders_model_19": "f9be9d8e81fbd30196a2ba14", +"orders_model_2": "b9162cfbc1ce5044c01cca42", +"orders_model_20": "1bb9c3971b4488e0b7023645", +"orders_model_21": "7c6d6c8fb64f5bfb121ebac1", +"orders_model_22": "0b4ee9c2c4584613df0c4f3e", +"orders_model_23": "b760f8a3ed2b65af8ff70abc", +"orders_model_3": "f0f64c1baf69c4d7f0c75612", +"orders_model_4": "1cefa36f28721fe677e6a684", +"orders_model_5": "b0f2950e6d0c6c8ba60db1ca", +"orders_model_6": "38187a959e7cbbef799b5777", +"orders_model_7": "20835381aab849fd35068525", +"orders_model_8": "72717ea55695667a7b7d8b39", +"orders_model_9": "d34e456ade2ced8792534866", +"payment_totals": "ddedaaeda0bdb9d9997ac6cd", +"payments_by_customer": "da1968ec91b55f6f584c7ecd", +"pivot_0": "db45532b4aa0746bb6155579", +"pivot_1": "826e0ad9aec9b04097d58b37", +"pivot_2": "78dd4b3d90301ccd1e781295", +"pivot_3": "b2268fc29a60313e3b8c34ed", +"status_amounts": "0fbfc8d810e430c5814769d6", +"status_passthrough": "bbd8b7298ce68a222ba84345" +} +], +[ +"catalog", +"5f5c09917fe031a630ac277b" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"c67f69d1828d209a58642e36" +], +[ +"proof", +"c67f69d1828d209a58642e36" +], +[ +"proof", +"c67f69d1828d209a58642e36" +], +[ +"proof", +"b9689124495085d917d65ebf" +], +[ +"proof", +"c67f69d1828d209a58642e36" +], +[ +"proof", +"99b1ccea692774bb61737217" +], +[ +"shapes", +"c0d3bfda902cb95cd1564269" +], +[ +"models", +{ +"orders_model_0": "dc4da2070db56afde4157773", +"orders_model_1": "3e1948d706ff1cecf42f7863", +"orders_model_10": "476ca953b1cb041d05ab9663", +"orders_model_11": "78eeedc510efd8cc89dfea31", +"orders_model_12": "b06fcf5168d718f9042eb9f0", +"orders_model_13": "25952bed7c264fceaeec357c", +"orders_model_14": "c5aa1f63d80b5d306477c290", +"orders_model_15": "2a978f96fe42e545ae0e5f8e", +"orders_model_16": "b67d418ac9424b16909d6a26", +"orders_model_17": "769e25e737cf7832171d8837", +"orders_model_18": "8a322bf0beb93c0034bd28d5", +"orders_model_19": "a4c400c5fa2da4107098339e", +"orders_model_2": "2f584b5185d90ee4c66c8339", +"orders_model_20": "1bb9c3971b4488e0b7023645", +"orders_model_21": "67dc0f1b5ce04c8989ad1aca", +"orders_model_22": "c838c05a0db9b7bdb5a1e793", +"orders_model_23": "18c951cb594f929547ec6527", +"orders_model_3": "cdd3d071e7283000e9b176dd", +"orders_model_4": "4c809f6cf2e946ba98b1ec73", +"orders_model_5": "2f2cbf190f07bea2687a7a1e", +"orders_model_6": "b8c7c62baf6528acb751f82c", +"orders_model_7": "0dbccc6cd571bd9ebefb3c2b", +"orders_model_8": "63ebe9cbc63523f4c4adddb2", +"orders_model_9": "9677ddb44ed9870eeb1fdac1", +"payment_totals": "692528d52a5623a0e90d7fb4", +"payments_by_customer": "c29bf4a09e3c8e9cff564a2f", +"pivot_0": "db45532b4aa0746bb6155579", +"pivot_1": "826e0ad9aec9b04097d58b37", +"pivot_2": "78dd4b3d90301ccd1e781295", +"pivot_3": "0b5af099963f99173031a52f", +"status_amounts": "0fbfc8d810e430c5814769d6", +"status_passthrough": "26ba5a13355d37dfa8e67820" +} +], +[ +"catalog", +"f48ca046110efa93dc8e7b54" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"shapes", +"78e5cd70ce361d823798634b" +], +[ +"models", +{ +"orders_model_0": "dc7f3dec778fd7cc3b47de47", +"orders_model_1": "98e73c916923e6ad3dbb4fe8", +"orders_model_10": "bba235f3ba5a071d31c89cfc", +"orders_model_11": "b92be214f33c9cf71eea3bc2", +"orders_model_12": "7dde13e57109cfb992bc623d", +"orders_model_13": "528bfc7a27293f659b6eec35", +"orders_model_14": "6d1049bdcad88b007d5f111c", +"orders_model_15": "f31a90a0505705305536f618", +"orders_model_16": "bf62990d9480cf71956fd3c9", +"orders_model_17": "cb0cef5752047e0f1201dfb4", +"orders_model_18": "288bd78cd1025c86da017d6d", +"orders_model_19": "bc46ad8533a003d33c266a57", +"orders_model_2": "f165784d55122e5e5f859766", +"orders_model_20": "f2329324ed72baeb2911ce6a", +"orders_model_21": "bbb7494cbb82085e1c034f21", +"orders_model_22": "9cc8cf8a102827df55622a21", +"orders_model_23": "ccf2498a5b3526260f88df6f", +"orders_model_3": "2acc6b35910a7b7c1e29d661", +"orders_model_4": "d545cb7b8ca26b55d32439c0", +"orders_model_5": "c21e33abd058c0db4ed1aa0a", +"orders_model_6": "529410c5a69b04b7172c6dda", +"orders_model_7": "a3f7c2aae3ece4d7de21b9ef", +"orders_model_8": "9a483c2d5942e8857be41233", +"orders_model_9": "0b71c12f30a7617191bc2e17", +"payment_totals": "ce8a97426d53e0acd6c49c2b", +"payments_by_customer": "da1968ec91b55f6f584c7ecd", +"pivot_0": "8ef48104ced62eb9ff31c2b8", +"pivot_1": "af151ba34f16c141fdee1ac3", +"pivot_2": "5cf2515c32c9c98b0a9d8315", +"pivot_3": "3767f4902ed5f3ab1acc83a1", +"status_amounts": "0fbfc8d810e430c5814769d6", +"status_passthrough": "57dbca31518ecf81d68ec4fe" +} +], +[ +"catalog", +"b2b2221f2da5d47b86b56575" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"0d91dfe8eefbbb36998db250" +], +[ +"proof", +"b9689124495085d917d65ebf" +], +[ +"proof", +"4994bb2a572acbed6354a2bb" +], +[ +"proof", +"ff4d4f462aae3b9e95d9a5ab" +], +[ +"proof", +"28c524727756a048843237ef" +], +[ +"proof", +"99b1ccea692774bb61737217" +], +[ +"shapes", +"b40871514fad0707c8cdbee7" +], +[ +"models", +{ +"orders_model_0": "34986e60aa464378baaa7f25", +"orders_model_1": "98e73c916923e6ad3dbb4fe8", +"orders_model_10": "9949660e9a41b3a11b1d646a", +"orders_model_11": "b92be214f33c9cf71eea3bc2", +"orders_model_12": "7dde13e57109cfb992bc623d", +"orders_model_13": "528bfc7a27293f659b6eec35", +"orders_model_14": "611ea76d354e7180f2fe0906", +"orders_model_15": "f31a90a0505705305536f618", +"orders_model_16": "e931c288a0cc5a80e1d59ebe", +"orders_model_17": "4cb4a5fe4f98fcb58b9aa0a8", +"orders_model_18": "288bd78cd1025c86da017d6d", +"orders_model_19": "bc46ad8533a003d33c266a57", +"orders_model_2": "2c4a0d5f37d1033435dc44b8", +"orders_model_20": "f2329324ed72baeb2911ce6a", +"orders_model_21": "af5f39f23b7c2b58d3f12930", +"orders_model_22": "9cc8cf8a102827df55622a21", +"orders_model_23": "ccf2498a5b3526260f88df6f", +"orders_model_3": "7faf6388dfebc22483c72417", +"orders_model_4": "d545cb7b8ca26b55d32439c0", +"orders_model_5": "ad3b7e6c56a628aff0799f39", +"orders_model_6": "529410c5a69b04b7172c6dda", +"orders_model_7": "a3f7c2aae3ece4d7de21b9ef", +"orders_model_8": "e0e0e8448cdcfb7bbf411186", +"orders_model_9": "0b71c12f30a7617191bc2e17", +"payment_totals": "e75b3088ecccbf453f472518", +"payments_by_customer": "e406a89772022ea3c32aefef", +"pivot_0": "8ef48104ced62eb9ff31c2b8", +"pivot_1": "e6d82b48a7a5593bd747ea69", +"pivot_2": "5cf2515c32c9c98b0a9d8315", +"pivot_3": "3767f4902ed5f3ab1acc83a1", +"status_amounts": "0fbfc8d810e430c5814769d6", +"status_passthrough": "57dbca31518ecf81d68ec4fe" +} +], +[ +"catalog", +"c5e050848445dd9e188a6f93" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"200eb30f2a045b54792500f6" +], +[ +"proof", +"200eb30f2a045b54792500f6" +], +[ +"proof", +"200eb30f2a045b54792500f6" +], +[ +"proof", +"200eb30f2a045b54792500f6" +], +[ +"proof", +"200eb30f2a045b54792500f6" +], +[ +"proof", +"200eb30f2a045b54792500f6" +], +[ +"shapes", +"78e5cd70ce361d823798634b" +], +[ +"models", +{ +"orders_model_0": "c0a4a49f398790b6968ded9b", +"orders_model_1": "f8df97502ce8987ade2b8ae6", +"orders_model_10": "d9e87a16e347f6f0316452d6", +"orders_model_11": "b92be214f33c9cf71eea3bc2", +"orders_model_12": "541418fef292ad4a9c6f8dab", +"orders_model_13": "528bfc7a27293f659b6eec35", +"orders_model_14": "6d1049bdcad88b007d5f111c", +"orders_model_15": "f31a90a0505705305536f618", +"orders_model_16": "0eca13897e0abb4131837a39", +"orders_model_17": "cb0cef5752047e0f1201dfb4", +"orders_model_18": "fb0385ba59d9d254edc4f53d", +"orders_model_19": "bc46ad8533a003d33c266a57", +"orders_model_2": "f165784d55122e5e5f859766", +"orders_model_20": "f2329324ed72baeb2911ce6a", +"orders_model_21": "bbb7494cbb82085e1c034f21", +"orders_model_22": "83e085c3265373904422aad9", +"orders_model_23": "ccf2498a5b3526260f88df6f", +"orders_model_3": "2acc6b35910a7b7c1e29d661", +"orders_model_4": "a249acc516a880c9fbe25e88", +"orders_model_5": "c21e33abd058c0db4ed1aa0a", +"orders_model_6": "c55e2f85ad9de69066fc965c", +"orders_model_7": "a3f7c2aae3ece4d7de21b9ef", +"orders_model_8": "ec0818249ce5c1a3abdbba12", +"orders_model_9": "0b71c12f30a7617191bc2e17", +"payment_totals": "ddedaaeda0bdb9d9997ac6cd", +"payments_by_customer": "da1968ec91b55f6f584c7ecd", +"pivot_0": "8ef48104ced62eb9ff31c2b8", +"pivot_1": "b2268fc29a60313e3b8c34ed", +"pivot_2": "5cf2515c32c9c98b0a9d8315", +"pivot_3": "3767f4902ed5f3ab1acc83a1", +"status_amounts": "0fbfc8d810e430c5814769d6", +"status_passthrough": "bbd8b7298ce68a222ba84345" +} +], +[ +"catalog", +"0675d0c35333ce73c1709f47" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"c67f69d1828d209a58642e36" +], +[ +"proof", +"b9689124495085d917d65ebf" +], +[ +"proof", +"c67f69d1828d209a58642e36" +], +[ +"proof", +"c67f69d1828d209a58642e36" +], +[ +"proof", +"c67f69d1828d209a58642e36" +], +[ +"proof", +"99b1ccea692774bb61737217" +], +[ +"shapes", +"c0d3bfda902cb95cd1564269" +], +[ +"models", +{ +"orders_model_0": "279aba0c75055164f61b65f8", +"orders_model_1": "45de3ae2081edb1155411120", +"orders_model_10": "ce0bc9f834e9623dddad0b3a", +"orders_model_11": "29c9da29acf1adc409e364df", +"orders_model_12": "dc4da2070db56afde4157773", +"orders_model_13": "87a319b5caf7cc32bc6aa50e", +"orders_model_14": "611ea76d354e7180f2fe0906", +"orders_model_15": "18cc8b92ab2adfb7e7e160a3", +"orders_model_16": "28610c39619a490a015886ec", +"orders_model_17": "664cb83e35a8ecea0758a450", +"orders_model_18": "8cf38d3ff37cd8143561920a", +"orders_model_19": "dcb9d89d4b588b53682fb0b4", +"orders_model_2": "2c4a0d5f37d1033435dc44b8", +"orders_model_20": "f2329324ed72baeb2911ce6a", +"orders_model_21": "af51dc83785211c066cbb51f", +"orders_model_22": "9cc8cf8a102827df55622a21", +"orders_model_23": "857c9a58882bddd68cec3bd5", +"orders_model_3": "d43b073d40eb97e87277c137", +"orders_model_4": "a249acc516a880c9fbe25e88", +"orders_model_5": "ad3b7e6c56a628aff0799f39", +"orders_model_6": "0541825c1a3bbc51c23f3a53", +"orders_model_7": "526a9e7adadbf085a39764b5", +"orders_model_8": "fcc5ac474974dee716908c65", +"orders_model_9": "0b71c12f30a7617191bc2e17", +"payment_totals": "692528d52a5623a0e90d7fb4", +"payments_by_customer": "c29bf4a09e3c8e9cff564a2f", +"pivot_0": "8ef48104ced62eb9ff31c2b8", +"pivot_1": "0b5af099963f99173031a52f", +"pivot_2": "5cf2515c32c9c98b0a9d8315", +"pivot_3": "3767f4902ed5f3ab1acc83a1", +"status_amounts": "0fbfc8d810e430c5814769d6", +"status_passthrough": "26ba5a13355d37dfa8e67820" +} +], +[ +"catalog", +"7f3cc4630798c6d611e9c144" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"shapes", +"78e5cd70ce361d823798634b" +], +[ +"models", +{ +"orders_model_0": "7dde13e57109cfb992bc623d", +"orders_model_1": "d7498e8ac1b0afeb189ff727", +"orders_model_10": "60ab36ff1481d98f182141fc", +"orders_model_11": "b92be214f33c9cf71eea3bc2", +"orders_model_12": "dc7f3dec778fd7cc3b47de47", +"orders_model_13": "35b1097a860faac43e81b044", +"orders_model_14": "28b94fa5aaa6225fd8809740", +"orders_model_15": "1a083ad888e035969bd5f5fe", +"orders_model_16": "061d35dfeab6243e15890c04", +"orders_model_17": "458d9725be39144ca5e0c33d", +"orders_model_18": "6b0c7fdf2bf74107bd96a6ff", +"orders_model_19": "ec3c3ec5fbf35ddc59fd77ca", +"orders_model_2": "959e49dd41f7bcc7e9edde19", +"orders_model_20": "40a0a6e57912d17b00b26274", +"orders_model_21": "fbd144b873208a2bd80a35a4", +"orders_model_22": "4e068f2ba3ce583e4d5b6006", +"orders_model_23": "8942d18a241e8dcd1831addc", +"orders_model_3": "e1986e4dea1c1d381bf078ff", +"orders_model_4": "526ce0a1d0a274582f9d35f1", +"orders_model_5": "458d9725be39144ca5e0c33d", +"orders_model_6": "d236f592f3b7c9328bb402ea", +"orders_model_7": "ef0eb5ded0428f49ac6cb411", +"orders_model_8": "19280031a53ac7db42aa7136", +"orders_model_9": "338aef528aa5f199e2ffa973", +"payment_totals": "ce8a97426d53e0acd6c49c2b", +"payments_by_customer": "da1968ec91b55f6f584c7ecd", +"pivot_0": "bd6145283beb468ce86b460b", +"pivot_1": "8eb04463a7e8015fcc9b8a63", +"pivot_2": "18ecbe5e93fe3ced5cbfd24a", +"pivot_3": "af151ba34f16c141fdee1ac3", +"status_amounts": "0fbfc8d810e430c5814769d6", +"status_passthrough": "57dbca31518ecf81d68ec4fe" +} +], +[ +"catalog", +"a749305bcf58d93756b4c9de" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"1241165b261dcfe84ece9067" +], +[ +"proof", +"c3cb3226e55a418829fd059c" +], +[ +"proof", +"20e6b6374d63663154468bed" +], +[ +"proof", +"b9689124495085d917d65ebf" +], +[ +"proof", +"28c524727756a048843237ef" +], +[ +"proof", +"99b1ccea692774bb61737217" +], +[ +"shapes", +"b40871514fad0707c8cdbee7" +], +[ +"models", +{ +"orders_model_0": "7dde13e57109cfb992bc623d", +"orders_model_1": "d7498e8ac1b0afeb189ff727", +"orders_model_10": "60ab36ff1481d98f182141fc", +"orders_model_11": "b92be214f33c9cf71eea3bc2", +"orders_model_12": "34986e60aa464378baaa7f25", +"orders_model_13": "35b1097a860faac43e81b044", +"orders_model_14": "28b94fa5aaa6225fd8809740", +"orders_model_15": "1a083ad888e035969bd5f5fe", +"orders_model_16": "061d35dfeab6243e15890c04", +"orders_model_17": "458d9725be39144ca5e0c33d", +"orders_model_18": "6b0c7fdf2bf74107bd96a6ff", +"orders_model_19": "ec3c3ec5fbf35ddc59fd77ca", +"orders_model_2": "3c07dff3140b081ee33fd13e", +"orders_model_20": "40a0a6e57912d17b00b26274", +"orders_model_21": "fbd144b873208a2bd80a35a4", +"orders_model_22": "4e068f2ba3ce583e4d5b6006", +"orders_model_23": "8942d18a241e8dcd1831addc", +"orders_model_3": "e1986e4dea1c1d381bf078ff", +"orders_model_4": "75f6764c319047022968f0b3", +"orders_model_5": "458d9725be39144ca5e0c33d", +"orders_model_6": "36c156c5a6601badf8124464", +"orders_model_7": "80a1f1b7b38c1afa802d7625", +"orders_model_8": "19280031a53ac7db42aa7136", +"orders_model_9": "338aef528aa5f199e2ffa973", +"payment_totals": "e75b3088ecccbf453f472518", +"payments_by_customer": "e406a89772022ea3c32aefef", +"pivot_0": "bd6145283beb468ce86b460b", +"pivot_1": "8eb04463a7e8015fcc9b8a63", +"pivot_2": "18ecbe5e93fe3ced5cbfd24a", +"pivot_3": "e6d82b48a7a5593bd747ea69", +"status_amounts": "0fbfc8d810e430c5814769d6", +"status_passthrough": "57dbca31518ecf81d68ec4fe" +} +], +[ +"catalog", +"f0d8ca9bf661a94ff2124cfb" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"200eb30f2a045b54792500f6" +], +[ +"proof", +"200eb30f2a045b54792500f6" +], +[ +"proof", +"200eb30f2a045b54792500f6" +], +[ +"proof", +"200eb30f2a045b54792500f6" +], +[ +"proof", +"200eb30f2a045b54792500f6" +], +[ +"proof", +"200eb30f2a045b54792500f6" +], +[ +"shapes", +"78e5cd70ce361d823798634b" +], +[ +"models", +{ +"orders_model_0": "541418fef292ad4a9c6f8dab", +"orders_model_1": "673e75c341c3f2437091de09", +"orders_model_10": "8314d3a80b3a31f5a7b3b87c", +"orders_model_11": "b92be214f33c9cf71eea3bc2", +"orders_model_12": "c0a4a49f398790b6968ded9b", +"orders_model_13": "bc666dca3ca9016f640dfe68", +"orders_model_14": "7c3ab71786810446d45e97a3", +"orders_model_15": "1a083ad888e035969bd5f5fe", +"orders_model_16": "39b572633eb377051c189c82", +"orders_model_17": "7a9fabf5b3d3ab9e1fc63a99", +"orders_model_18": "79cac6cd1f2e605da47e460d", +"orders_model_19": "ec3c3ec5fbf35ddc59fd77ca", +"orders_model_2": "959e49dd41f7bcc7e9edde19", +"orders_model_20": "40a0a6e57912d17b00b26274", +"orders_model_21": "59228560ec9692b57930d8b5", +"orders_model_22": "b8238ed1e26320d8f8912882", +"orders_model_23": "8942d18a241e8dcd1831addc", +"orders_model_3": "e1986e4dea1c1d381bf078ff", +"orders_model_4": "1cefa36f28721fe677e6a684", +"orders_model_5": "7a9fabf5b3d3ab9e1fc63a99", +"orders_model_6": "748592fef86e52c625afd1e0", +"orders_model_7": "ef0eb5ded0428f49ac6cb411", +"orders_model_8": "19280031a53ac7db42aa7136", +"orders_model_9": "338aef528aa5f199e2ffa973", +"payment_totals": "ddedaaeda0bdb9d9997ac6cd", +"payments_by_customer": "da1968ec91b55f6f584c7ecd", +"pivot_0": "bd6145283beb468ce86b460b", +"pivot_1": "8eb04463a7e8015fcc9b8a63", +"pivot_2": "18ecbe5e93fe3ced5cbfd24a", +"pivot_3": "b2268fc29a60313e3b8c34ed", +"status_amounts": "0fbfc8d810e430c5814769d6", +"status_passthrough": "bbd8b7298ce68a222ba84345" +} +], +[ +"catalog", +"988cc4307f8cdbfd7c4e95f9" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"c67f69d1828d209a58642e36" +], +[ +"proof", +"c67f69d1828d209a58642e36" +], +[ +"proof", +"c67f69d1828d209a58642e36" +], +[ +"proof", +"b9689124495085d917d65ebf" +], +[ +"proof", +"c67f69d1828d209a58642e36" +], +[ +"proof", +"99b1ccea692774bb61737217" +], +[ +"shapes", +"c0d3bfda902cb95cd1564269" +], +[ +"models", +{ +"orders_model_0": "dc4da2070db56afde4157773", +"orders_model_1": "b6345243b4bb0009ec2dfb5d", +"orders_model_10": "408cbd03f775698d2714eb62", +"orders_model_11": "29c9da29acf1adc409e364df", +"orders_model_12": "279aba0c75055164f61b65f8", +"orders_model_13": "87a1dbf609e37b67c90e35b2", +"orders_model_14": "544d358c786985653996181d", +"orders_model_15": "e643f7ef7c9f860822ad8ba7", +"orders_model_16": "2ee8d0a917d274c8d55f4370", +"orders_model_17": "bac0193c7d43a68153ce544e", +"orders_model_18": "60e19e6908bb5c06d38eeb01", +"orders_model_19": "ab249088d32d341a013be687", +"orders_model_2": "3c07dff3140b081ee33fd13e", +"orders_model_20": "40a0a6e57912d17b00b26274", +"orders_model_21": "176a688a47e60b55e1ce0673", +"orders_model_22": "c6255585e2f5156964d8f8f8", +"orders_model_23": "e0ec1521e19c47996421ec94", +"orders_model_3": "f22120166b4143e8fd193e3d", +"orders_model_4": "4c809f6cf2e946ba98b1ec73", +"orders_model_5": "bac0193c7d43a68153ce544e", +"orders_model_6": "c2b91215ea727d9313a22740", +"orders_model_7": "afb5b3102eaac7fa202355c0", +"orders_model_8": "19280031a53ac7db42aa7136", +"orders_model_9": "283c165f2da9102ffec377c4", +"payment_totals": "692528d52a5623a0e90d7fb4", +"payments_by_customer": "c29bf4a09e3c8e9cff564a2f", +"pivot_0": "bd6145283beb468ce86b460b", +"pivot_1": "8eb04463a7e8015fcc9b8a63", +"pivot_2": "18ecbe5e93fe3ced5cbfd24a", +"pivot_3": "0b5af099963f99173031a52f", +"status_amounts": "0fbfc8d810e430c5814769d6", +"status_passthrough": "26ba5a13355d37dfa8e67820" +} +], +[ +"catalog", +"767dbad2dc0bb5d013f7a196" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"shapes", +"78e5cd70ce361d823798634b" +], +[ +"models", +{ +"orders_model_0": "c380ae05f3bd0627628ab6fc", +"orders_model_1": "abadf69a0572399b6536a2c1", +"orders_model_10": "c46ffece29c5df800b8f74df", +"orders_model_11": "be02726b764e7cc94f5df56c", +"orders_model_12": "edf57c58d750226a747455ba", +"orders_model_13": "278d4fd453aea2eca14894ea", +"orders_model_14": "0759e673a754006cbe1427de", +"orders_model_15": "5e266036ddde9cb398819134", +"orders_model_16": "eeaefdbd50fdc13681d8653a", +"orders_model_17": "3515712bb3c936c534706554", +"orders_model_18": "dd2512e1e685426785444ae5", +"orders_model_19": "5ab5711e085cc014f3e44950", +"orders_model_2": "b1cffebb5797fe684c20e885", +"orders_model_20": "9b30de5669877213eebaf0e5", +"orders_model_21": "0b71c12f30a7617191bc2e17", +"orders_model_22": "91d92b539582dec7737d1704", +"orders_model_23": "c8ff9a2130c4a7a57073fb6d", +"orders_model_3": "a5927681bfbf9d44f4723990", +"orders_model_4": "e29709e8e7acb44cc782304f", +"orders_model_5": "afd6d68f0a0a6689404e0260", +"orders_model_6": "7ccdde571d7f688040f1f47c", +"orders_model_7": "a36493d57a16c1f79a91afd6", +"orders_model_8": "2307138f76b5c3d80ec84a7a", +"orders_model_9": "d34e456ade2ced8792534866", +"payment_totals": "ce8a97426d53e0acd6c49c2b", +"payments_by_customer": "da1968ec91b55f6f584c7ecd", +"pivot_0": "8ef48104ced62eb9ff31c2b8", +"pivot_1": "af151ba34f16c141fdee1ac3", +"pivot_2": "5adb7a56c3dfd3d1c3cf58c1", +"pivot_3": "00a890bbfc402b53ea021e5a", +"status_amounts": "0fbfc8d810e430c5814769d6", +"status_passthrough": "57dbca31518ecf81d68ec4fe" +} +], +[ +"catalog", +"893ba59566e53ebc6aaa2cdc" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"0d91dfe8eefbbb36998db250" +], +[ +"proof", +"b9689124495085d917d65ebf" +], +[ +"proof", +"1241165b261dcfe84ece9067" +], +[ +"proof", +"20e6b6374d63663154468bed" +], +[ +"proof", +"28c524727756a048843237ef" +], +[ +"proof", +"99b1ccea692774bb61737217" +], +[ +"shapes", +"b40871514fad0707c8cdbee7" +], +[ +"models", +{ +"orders_model_0": "c380ae05f3bd0627628ab6fc", +"orders_model_1": "7f4d684fd731d8fd8e517a52", +"orders_model_10": "c46ffece29c5df800b8f74df", +"orders_model_11": "8003e1680dc046032ceea404", +"orders_model_12": "a030043d592af380cf44cb9f", +"orders_model_13": "56d09679844a976541cce33c", +"orders_model_14": "e51070f44666248f5b7764b3", +"orders_model_15": "5e266036ddde9cb398819134", +"orders_model_16": "eeaefdbd50fdc13681d8653a", +"orders_model_17": "3515712bb3c936c534706554", +"orders_model_18": "f73c7edc9f35cb7956a40b52", +"orders_model_19": "5ab5711e085cc014f3e44950", +"orders_model_2": "835e887650bbf9b124ae26b1", +"orders_model_20": "9b30de5669877213eebaf0e5", +"orders_model_21": "0b71c12f30a7617191bc2e17", +"orders_model_22": "e780cb2018f0f8f501e8d2fe", +"orders_model_23": "c8ff9a2130c4a7a57073fb6d", +"orders_model_3": "e03d256f9a62a63d98fad738", +"orders_model_4": "9a1f8dc30a3cfc10bba60a45", +"orders_model_5": "afd6d68f0a0a6689404e0260", +"orders_model_6": "099cb926af524f10d27cc108", +"orders_model_7": "a36493d57a16c1f79a91afd6", +"orders_model_8": "e7532f3dad5c3e5750265e5b", +"orders_model_9": "d34e456ade2ced8792534866", +"payment_totals": "e75b3088ecccbf453f472518", +"payments_by_customer": "e406a89772022ea3c32aefef", +"pivot_0": "8ef48104ced62eb9ff31c2b8", +"pivot_1": "e6d82b48a7a5593bd747ea69", +"pivot_2": "5adb7a56c3dfd3d1c3cf58c1", +"pivot_3": "00a890bbfc402b53ea021e5a", +"status_amounts": "0fbfc8d810e430c5814769d6", +"status_passthrough": "57dbca31518ecf81d68ec4fe" +} +], +[ +"catalog", +"5d66ad3e2dacd496eb2b4872" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"200eb30f2a045b54792500f6" +], +[ +"proof", +"200eb30f2a045b54792500f6" +], +[ +"proof", +"200eb30f2a045b54792500f6" +], +[ +"proof", +"200eb30f2a045b54792500f6" +], +[ +"proof", +"200eb30f2a045b54792500f6" +], +[ +"proof", +"200eb30f2a045b54792500f6" +], +[ +"shapes", +"78e5cd70ce361d823798634b" +], +[ +"models", +{ +"orders_model_0": "94f95487333b2561382c2981", +"orders_model_1": "1ad8f3013a29b4f16f037b39", +"orders_model_10": "3aec7a059badfa0e968d5216", +"orders_model_11": "be02726b764e7cc94f5df56c", +"orders_model_12": "cb6d3e8487b533349a2bad04", +"orders_model_13": "d55e6b7bb6533cea41bcfeda", +"orders_model_14": "0759e673a754006cbe1427de", +"orders_model_15": "5e266036ddde9cb398819134", +"orders_model_16": "97e322d50d70c30c61fb7a15", +"orders_model_17": "3515712bb3c936c534706554", +"orders_model_18": "326d8bbf3c85b38aafb08a98", +"orders_model_19": "5ab5711e085cc014f3e44950", +"orders_model_2": "b1cffebb5797fe684c20e885", +"orders_model_20": "9b30de5669877213eebaf0e5", +"orders_model_21": "0b71c12f30a7617191bc2e17", +"orders_model_22": "368c97dc5eea624b492ce042", +"orders_model_23": "c8ff9a2130c4a7a57073fb6d", +"orders_model_3": "a5927681bfbf9d44f4723990", +"orders_model_4": "3af96276ee92b913506618b2", +"orders_model_5": "ee556ea5f790f1d885cee84a", +"orders_model_6": "099cb926af524f10d27cc108", +"orders_model_7": "a36493d57a16c1f79a91afd6", +"orders_model_8": "ed49fa288ea02d542c88ec94", +"orders_model_9": "d34e456ade2ced8792534866", +"payment_totals": "ddedaaeda0bdb9d9997ac6cd", +"payments_by_customer": "da1968ec91b55f6f584c7ecd", +"pivot_0": "8ef48104ced62eb9ff31c2b8", +"pivot_1": "b2268fc29a60313e3b8c34ed", +"pivot_2": "5adb7a56c3dfd3d1c3cf58c1", +"pivot_3": "00a890bbfc402b53ea021e5a", +"status_amounts": "0fbfc8d810e430c5814769d6", +"status_passthrough": "bbd8b7298ce68a222ba84345" +} +], +[ +"catalog", +"bb15ca51be7f1375a5b43886" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"c67f69d1828d209a58642e36" +], +[ +"proof", +"b9689124495085d917d65ebf" +], +[ +"proof", +"c67f69d1828d209a58642e36" +], +[ +"proof", +"c67f69d1828d209a58642e36" +], +[ +"proof", +"c67f69d1828d209a58642e36" +], +[ +"proof", +"99b1ccea692774bb61737217" +], +[ +"shapes", +"c0d3bfda902cb95cd1564269" +], +[ +"models", +{ +"orders_model_0": "c380ae05f3bd0627628ab6fc", +"orders_model_1": "1070e59d687e0fed0e44b651", +"orders_model_10": "fa26ab8510354dd670525ac2", +"orders_model_11": "eb7d097be111399bcd2f940f", +"orders_model_12": "4054517533ad5199a1077065", +"orders_model_13": "ab1f9c5b6ef07ffa40eeadaf", +"orders_model_14": "273c339ab90e9a64a7c8f8a5", +"orders_model_15": "90310178ea5674f6669a72f4", +"orders_model_16": "e018db5f6e3eaf8888bd8eff", +"orders_model_17": "fe03c6a89b870943b6dd5922", +"orders_model_18": "fd5138ac4af02cd168a423e6", +"orders_model_19": "e24f113150b49c7e955cf81b", +"orders_model_2": "daca571af4a4d1cb1afbce74", +"orders_model_20": "9b30de5669877213eebaf0e5", +"orders_model_21": "0b71c12f30a7617191bc2e17", +"orders_model_22": "56f27ec8513b46291154e8cd", +"orders_model_23": "e94cdbeab01617cd05a55f82", +"orders_model_3": "72f0c384f9c169084cf65392", +"orders_model_4": "39a96779a764101f7d1dbae2", +"orders_model_5": "7af136b7e522ccf14f427e1e", +"orders_model_6": "8a322bf0beb93c0034bd28d5", +"orders_model_7": "4983a5e9302c8b9e28e75202", +"orders_model_8": "e7532f3dad5c3e5750265e5b", +"orders_model_9": "9677ddb44ed9870eeb1fdac1", +"payment_totals": "692528d52a5623a0e90d7fb4", +"payments_by_customer": "c29bf4a09e3c8e9cff564a2f", +"pivot_0": "8ef48104ced62eb9ff31c2b8", +"pivot_1": "0b5af099963f99173031a52f", +"pivot_2": "5adb7a56c3dfd3d1c3cf58c1", +"pivot_3": "00a890bbfc402b53ea021e5a", +"status_amounts": "0fbfc8d810e430c5814769d6", +"status_passthrough": "26ba5a13355d37dfa8e67820" +} +], +[ +"catalog", +"165df7e540546e89f76b0819" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"shapes", +"78e5cd70ce361d823798634b" +], +[ +"models", +{ +"orders_model_0": "c380ae05f3bd0627628ab6fc", +"orders_model_1": "c909142a40bfa94a0849e672", +"orders_model_10": "99f0746f249fd25788f1348a", +"orders_model_11": "5f4d57a90f61f48a39c3f45c", +"orders_model_12": "159cce49ef0548e95a5b46fe", +"orders_model_13": "ba7bafc812a816c0c0770d82", +"orders_model_14": "69a4a23c4590c4354bff5dbf", +"orders_model_15": "e83a2c02763b0f51b49dbfe1", +"orders_model_16": "e29709e8e7acb44cc782304f", +"orders_model_17": "40ca546bd222f4bd18e62461", +"orders_model_18": "2bcb5417ea2e03971c367fbd", +"orders_model_19": "16fc9c0348ca5eadfd147e95", +"orders_model_2": "be51e7ded79e692b0f86ad8e", +"orders_model_20": "0c798fa3e6d807bf94e96eee", +"orders_model_21": "32e2f46b53e4361d34fb2f95", +"orders_model_22": "ca95b1a1313ab6e0c86f22d0", +"orders_model_23": "6423a33f3457191fa1b24540", +"orders_model_3": "52f7f68c35fc1813f86aee3b", +"orders_model_4": "40daca9947aaa0922736d9ca", +"orders_model_5": "efc04632c3bd90f5ca705b61", +"orders_model_6": "6b0c7fdf2bf74107bd96a6ff", +"orders_model_7": "f1d838e10071f9b219bf07c6", +"orders_model_8": "653dbee5db7422883147ecf8", +"orders_model_9": "e2d21c84b2b62dea98a1d185", +"payment_totals": "ce8a97426d53e0acd6c49c2b", +"payments_by_customer": "da1968ec91b55f6f584c7ecd", +"pivot_0": "af151ba34f16c141fdee1ac3", +"pivot_1": "bd6145283beb468ce86b460b", +"pivot_2": "db45532b4aa0746bb6155579", +"pivot_3": "5cf2515c32c9c98b0a9d8315", +"status_amounts": "0fbfc8d810e430c5814769d6", +"status_passthrough": "57dbca31518ecf81d68ec4fe" +} +], +[ +"catalog", +"f877c81e569d46b2f31adb8a" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"b9689124495085d917d65ebf" +], +[ +"proof", +"1241165b261dcfe84ece9067" +], +[ +"proof", +"0d91dfe8eefbbb36998db250" +], +[ +"proof", +"4994bb2a572acbed6354a2bb" +], +[ +"proof", +"28c524727756a048843237ef" +], +[ +"proof", +"99b1ccea692774bb61737217" +], +[ +"shapes", +"b40871514fad0707c8cdbee7" +], +[ +"models", +{ +"orders_model_0": "c380ae05f3bd0627628ab6fc", +"orders_model_1": "c909142a40bfa94a0849e672", +"orders_model_10": "99f0746f249fd25788f1348a", +"orders_model_11": "5f4d57a90f61f48a39c3f45c", +"orders_model_12": "159cce49ef0548e95a5b46fe", +"orders_model_13": "b929a7472b014a9b5b757127", +"orders_model_14": "69a4a23c4590c4354bff5dbf", +"orders_model_15": "fcf8d3dfd18bb30aef04a7e0", +"orders_model_16": "9a1f8dc30a3cfc10bba60a45", +"orders_model_17": "40ca546bd222f4bd18e62461", +"orders_model_18": "f913dcd698fd61a9df4580a9", +"orders_model_19": "16fc9c0348ca5eadfd147e95", +"orders_model_2": "be51e7ded79e692b0f86ad8e", +"orders_model_20": "0c798fa3e6d807bf94e96eee", +"orders_model_21": "32e2f46b53e4361d34fb2f95", +"orders_model_22": "ca95b1a1313ab6e0c86f22d0", +"orders_model_23": "6423a33f3457191fa1b24540", +"orders_model_3": "52f7f68c35fc1813f86aee3b", +"orders_model_4": "40daca9947aaa0922736d9ca", +"orders_model_5": "efc04632c3bd90f5ca705b61", +"orders_model_6": "6b0c7fdf2bf74107bd96a6ff", +"orders_model_7": "f1d838e10071f9b219bf07c6", +"orders_model_8": "588e1b85c85669d7d2f2874a", +"orders_model_9": "e2d21c84b2b62dea98a1d185", +"payment_totals": "e75b3088ecccbf453f472518", +"payments_by_customer": "e406a89772022ea3c32aefef", +"pivot_0": "e6d82b48a7a5593bd747ea69", +"pivot_1": "bd6145283beb468ce86b460b", +"pivot_2": "db45532b4aa0746bb6155579", +"pivot_3": "5cf2515c32c9c98b0a9d8315", +"status_amounts": "0fbfc8d810e430c5814769d6", +"status_passthrough": "57dbca31518ecf81d68ec4fe" +} +], +[ +"catalog", +"f877c81e569d46b2f31adb8a" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"200eb30f2a045b54792500f6" +], +[ +"proof", +"200eb30f2a045b54792500f6" +], +[ +"proof", +"200eb30f2a045b54792500f6" +], +[ +"proof", +"200eb30f2a045b54792500f6" +], +[ +"proof", +"200eb30f2a045b54792500f6" +], +[ +"proof", +"200eb30f2a045b54792500f6" +], +[ +"shapes", +"78e5cd70ce361d823798634b" +], +[ +"models", +{ +"orders_model_0": "94f95487333b2561382c2981", +"orders_model_1": "7ebef6bac8d0a4ff15fca702", +"orders_model_10": "07a1b43e2e1aec3a941c7463", +"orders_model_11": "5f4d57a90f61f48a39c3f45c", +"orders_model_12": "f28ca9cbe4f0b82139ce42ff", +"orders_model_13": "8bfac0eb02357c4ef7316ba0", +"orders_model_14": "69a4a23c4590c4354bff5dbf", +"orders_model_15": "e83a2c02763b0f51b49dbfe1", +"orders_model_16": "3af96276ee92b913506618b2", +"orders_model_17": "185a865c8cf0d67b3027a313", +"orders_model_18": "f913dcd698fd61a9df4580a9", +"orders_model_19": "16fc9c0348ca5eadfd147e95", +"orders_model_2": "be51e7ded79e692b0f86ad8e", +"orders_model_20": "0c798fa3e6d807bf94e96eee", +"orders_model_21": "88425997d70bb43627dba42c", +"orders_model_22": "083e6ee404f8943487416adb", +"orders_model_23": "6423a33f3457191fa1b24540", +"orders_model_3": "52f7f68c35fc1813f86aee3b", +"orders_model_4": "2cfd6426be9711fc3a185538", +"orders_model_5": "1e772c63e569addeecf15a27", +"orders_model_6": "79cac6cd1f2e605da47e460d", +"orders_model_7": "f1d838e10071f9b219bf07c6", +"orders_model_8": "653dbee5db7422883147ecf8", +"orders_model_9": "982d87b5a15b54ee70c70755", +"payment_totals": "ddedaaeda0bdb9d9997ac6cd", +"payments_by_customer": "da1968ec91b55f6f584c7ecd", +"pivot_0": "b2268fc29a60313e3b8c34ed", +"pivot_1": "bd6145283beb468ce86b460b", +"pivot_2": "db45532b4aa0746bb6155579", +"pivot_3": "5cf2515c32c9c98b0a9d8315", +"status_amounts": "0fbfc8d810e430c5814769d6", +"status_passthrough": "bbd8b7298ce68a222ba84345" +} +], +[ +"catalog", +"3eb464018675acfdd12a461f" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"b9689124495085d917d65ebf" +], +[ +"proof", +"c67f69d1828d209a58642e36" +], +[ +"proof", +"c67f69d1828d209a58642e36" +], +[ +"proof", +"c67f69d1828d209a58642e36" +], +[ +"proof", +"c67f69d1828d209a58642e36" +], +[ +"proof", +"99b1ccea692774bb61737217" +], +[ +"shapes", +"c0d3bfda902cb95cd1564269" +], +[ +"models", +{ +"orders_model_0": "c380ae05f3bd0627628ab6fc", +"orders_model_1": "18de106324e6bd649e9a0662", +"orders_model_10": "99f0746f249fd25788f1348a", +"orders_model_11": "68b962a61fcbd39f299bf7b9", +"orders_model_12": "31d217ac4f1c012c19d14c40", +"orders_model_13": "1d827eced23366a37ddba6b8", +"orders_model_14": "69a4a23c4590c4354bff5dbf", +"orders_model_15": "d1fb37ffa36108edc2a01aba", +"orders_model_16": "39a96779a764101f7d1dbae2", +"orders_model_17": "185a865c8cf0d67b3027a313", +"orders_model_18": "02d5138c4e7513182fc7cd52", +"orders_model_19": "3f36107952adc3d06995d9db", +"orders_model_2": "be51e7ded79e692b0f86ad8e", +"orders_model_20": "0c798fa3e6d807bf94e96eee", +"orders_model_21": "08e7a885c1d9662b2678c3ea", +"orders_model_22": "1b893dcaf72edc288a3b9710", +"orders_model_23": "f35475b4e5e4ae85ae46e91d", +"orders_model_3": "85fda65b19f7375e90342fa9", +"orders_model_4": "2cfd6426be9711fc3a185538", +"orders_model_5": "949207159f621de6e270aed5", +"orders_model_6": "60e19e6908bb5c06d38eeb01", +"orders_model_7": "07289e08df177aa672b5da80", +"orders_model_8": "c18f5ec77f58bbb47cc78168", +"orders_model_9": "05bfc38d1bf1cc771029edec", +"payment_totals": "692528d52a5623a0e90d7fb4", +"payments_by_customer": "c29bf4a09e3c8e9cff564a2f", +"pivot_0": "0b5af099963f99173031a52f", +"pivot_1": "bd6145283beb468ce86b460b", +"pivot_2": "db45532b4aa0746bb6155579", +"pivot_3": "5cf2515c32c9c98b0a9d8315", +"status_amounts": "0fbfc8d810e430c5814769d6", +"status_passthrough": "26ba5a13355d37dfa8e67820" +} +], +[ +"catalog", +"8808b0d353112b97c19536d1" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +] +] diff --git a/tests/goldens/python_oracle/analysis_generated_snowflake_and_duckdb_adapter_rules_fast_lineage.json b/tests/goldens/python_oracle/analysis_generated_snowflake_and_duckdb_adapter_rules_fast_lineage.json new file mode 100644 index 0000000000..58e8e5e046 --- /dev/null +++ b/tests/goldens/python_oracle/analysis_generated_snowflake_and_duckdb_adapter_rules_fast_lineage.json @@ -0,0 +1,1250 @@ +[ +[ +"shapes", +"78e5cd70ce361d823798634b" +], +[ +"models", +{ +"adapter_rules_cte": "01c88e0760e09990ec7e7f27", +"adapter_rules_staging": "d244bb9fd736be2a83c1c25f", +"adapter_rules_untyped_cte": "443d6a471f368f61895e97b7", +"dotless_i_staging": "0414cf2aabffee9324ca1152", +"long_s_cte": "22aa6898e4deee5e707a61c8", +"long_s_staging": "0ffc9fd6d1c6d34c2db07849", +"orders_model_0": "94f95487333b2561382c2981", +"orders_model_1": "b1970df938e25e00faeed015", +"orders_model_10": "6a9dd6631afe2aecba420032", +"orders_model_11": "e0a1bcae33bbfb164c9468f6", +"orders_model_12": "926f7b801edc86d0d0ecbac0", +"orders_model_13": "8af6ca52fb84b5b173b2326d", +"orders_model_14": "c1ec6ecf89992261001a255f", +"orders_model_15": "cc32a1a5e07802f1512706b9", +"orders_model_16": "16ae4650da78bf9861f65553", +"orders_model_17": "ee556ea5f790f1d885cee84a", +"orders_model_18": "241cc7616b413ea893ca6829", +"orders_model_19": "92a8e66d811c1497a2216783", +"orders_model_2": "345f166deff852e9116d8801", +"orders_model_20": "97c09ef764382c456089a08f", +"orders_model_21": "29e669ac95b4e44f7d8ea530", +"orders_model_22": "8d9a8370c5bb21b381f42208", +"orders_model_23": "fe73a080f7f7a3e1df6c305c", +"orders_model_3": "a5927681bfbf9d44f4723990", +"orders_model_4": "10c324ddebd8f360f30b0a6b", +"orders_model_5": "0209faf6600f5936ca0209a7", +"orders_model_6": "6d3a0df899304a5fff38b3f0", +"orders_model_7": "2cc4699fcfbfc50f29d34e4d", +"orders_model_8": "82c19ad1bdebebf9b9e99f2c", +"orders_model_9": "0b71c12f30a7617191bc2e17", +"payment_totals": "80bd8eb5eab6ed918ec31949", +"payments_by_customer": "9e1265b9f4134636cb508259", +"pivot_0": "8ffb88803fba96f5e1a0cc14", +"pivot_1": "5adb7a56c3dfd3d1c3cf58c1", +"pivot_2": "78dd4b3d90301ccd1e781295", +"pivot_3": "b2268fc29a60313e3b8c34ed", +"status_amounts": "0fbfc8d810e430c5814769d6", +"status_passthrough": "bbd8b7298ce68a222ba84345", +"umlaut_cte": "52e72621ebb88c5fc2a9fe35" +} +], +[ +"catalog", +"3f652f722b3dc3980f07f59d" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"20e6b6374d63663154468bed" +], +[ +"proof", +"c67f69d1828d209a58642e36" +], +[ +"proof", +"c67f69d1828d209a58642e36" +], +[ +"proof", +"b9689124495085d917d65ebf" +], +[ +"proof", +"c67f69d1828d209a58642e36" +], +[ +"proof", +"99b1ccea692774bb61737217" +], +[ +"shapes", +"78e5cd70ce361d823798634b" +], +[ +"models", +{ +"adapter_rules_cte": "dfd1ab68201bde357955ba7f", +"adapter_rules_staging": "1647edbe8ac61356261cfa76", +"adapter_rules_untyped_cte": "6d7a85f4f3ff37fb43fdc0b4", +"dotless_i_staging": "4c25b6514c8939c1579e7729", +"long_s_cte": "22aa6898e4deee5e707a61c8", +"long_s_staging": "c70692ed48ec89dc344df4e0", +"orders_model_0": "c380ae05f3bd0627628ab6fc", +"orders_model_1": "0897bc61ca6a0042539889cd", +"orders_model_10": "6a9dd6631afe2aecba420032", +"orders_model_11": "e0a1bcae33bbfb164c9468f6", +"orders_model_12": "fd707ea6f93871b0dc83c579", +"orders_model_13": "74b30199b5f8cc665f133e68", +"orders_model_14": "c1ec6ecf89992261001a255f", +"orders_model_15": "18719f2a40e9a0d55dce1f6d", +"orders_model_16": "5464f219a5381063a5cf2965", +"orders_model_17": "afd6d68f0a0a6689404e0260", +"orders_model_18": "ff71888baeb777eb8b0d274d", +"orders_model_19": "92a8e66d811c1497a2216783", +"orders_model_2": "835e887650bbf9b124ae26b1", +"orders_model_20": "97c09ef764382c456089a08f", +"orders_model_21": "af5f39f23b7c2b58d3f12930", +"orders_model_22": "3abd2e6a08df2cf8322bf309", +"orders_model_23": "fe73a080f7f7a3e1df6c305c", +"orders_model_3": "a5927681bfbf9d44f4723990", +"orders_model_4": "c868aee07ab0f13c50fadca2", +"orders_model_5": "8ca37d6ebd3f7cafc5b226da", +"orders_model_6": "7431806bd67f9e0c952a98ab", +"orders_model_7": "2cc4699fcfbfc50f29d34e4d", +"orders_model_8": "82c19ad1bdebebf9b9e99f2c", +"orders_model_9": "0b71c12f30a7617191bc2e17", +"payment_totals": "8cf82ad30e9cce84bc8a3529", +"payments_by_customer": "9e1265b9f4134636cb508259", +"pivot_0": "8ffb88803fba96f5e1a0cc14", +"pivot_1": "5adb7a56c3dfd3d1c3cf58c1", +"pivot_2": "78dd4b3d90301ccd1e781295", +"pivot_3": "af151ba34f16c141fdee1ac3", +"status_amounts": "0fbfc8d810e430c5814769d6", +"status_passthrough": "57dbca31518ecf81d68ec4fe", +"umlaut_cte": "a4c1810f1e46ef2200a87309" +} +], +[ +"catalog", +"4b773261b99e3dd24d7e41a5" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"20e6b6374d63663154468bed" +], +[ +"proof", +"9e3cc9a00de191a2a3a3a27f" +], +[ +"proof", +"28c524727756a048843237ef" +], +[ +"proof", +"b9689124495085d917d65ebf" +], +[ +"proof", +"28c524727756a048843237ef" +], +[ +"proof", +"99b1ccea692774bb61737217" +], +[ +"shapes", +"78e5cd70ce361d823798634b" +], +[ +"models", +{ +"adapter_rules_cte": "01c88e0760e09990ec7e7f27", +"adapter_rules_staging": "d244bb9fd736be2a83c1c25f", +"adapter_rules_untyped_cte": "443d6a471f368f61895e97b7", +"dotless_i_staging": "0414cf2aabffee9324ca1152", +"long_s_cte": "22aa6898e4deee5e707a61c8", +"long_s_staging": "0ffc9fd6d1c6d34c2db07849", +"orders_model_0": "b09efd1e7181db7773253200", +"orders_model_1": "8f27fcd3be57b9a85a5ade04", +"orders_model_10": "b57ee1c35cbaadb688298310", +"orders_model_11": "1c545871d01b68d8cc5270d4", +"orders_model_12": "a2d666e8a32f9f36556fefca", +"orders_model_13": "356f32e628d61db27bf4a4f3", +"orders_model_14": "5770c08feedcc514f8cdea74", +"orders_model_15": "511a913bdc473948a1d98b00", +"orders_model_16": "7a40989a4e6cf23c222525f6", +"orders_model_17": "74820176e511b43c55d5dcb7", +"orders_model_18": "6162b5c431b89f8917de6793", +"orders_model_19": "2d58b808566d04184cf9ab29", +"orders_model_2": "3d131ea2ed9d90f4404800c4", +"orders_model_20": "24da7733eb4155182f26f868", +"orders_model_21": "afdbc811f2683769c6065622", +"orders_model_22": "1ecee061003eefdd8e7b3e1d", +"orders_model_23": "ebf7fe799455ca0ef8c2a02e", +"orders_model_3": "c3a07511c03df1968f2c5ff9", +"orders_model_4": "0eca13897e0abb4131837a39", +"orders_model_5": "60e141a5769c44084f76723b", +"orders_model_6": "8ed658a7454aba1b437c36b2", +"orders_model_7": "f9be9d8e81fbd30196a2ba14", +"orders_model_8": "a0fc71fac4e12ec905ae953c", +"orders_model_9": "f6f4f76cf2077ee259b60302", +"payment_totals": "80bd8eb5eab6ed918ec31949", +"payments_by_customer": "9e1265b9f4134636cb508259", +"pivot_0": "78dd4b3d90301ccd1e781295", +"pivot_1": "b2268fc29a60313e3b8c34ed", +"pivot_2": "5cf2515c32c9c98b0a9d8315", +"pivot_3": "ae6c2278feec076b8e8bc0d9", +"status_amounts": "0fbfc8d810e430c5814769d6", +"status_passthrough": "bbd8b7298ce68a222ba84345", +"umlaut_cte": "52e72621ebb88c5fc2a9fe35" +} +], +[ +"catalog", +"e9da95982504131dc773c046" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"c67f69d1828d209a58642e36" +], +[ +"proof", +"b9689124495085d917d65ebf" +], +[ +"proof", +"c67f69d1828d209a58642e36" +], +[ +"proof", +"c67f69d1828d209a58642e36" +], +[ +"proof", +"c67f69d1828d209a58642e36" +], +[ +"proof", +"99b1ccea692774bb61737217" +], +[ +"shapes", +"78e5cd70ce361d823798634b" +], +[ +"models", +{ +"adapter_rules_cte": "dfd1ab68201bde357955ba7f", +"adapter_rules_staging": "1647edbe8ac61356261cfa76", +"adapter_rules_untyped_cte": "6d7a85f4f3ff37fb43fdc0b4", +"dotless_i_staging": "4c25b6514c8939c1579e7729", +"long_s_cte": "22aa6898e4deee5e707a61c8", +"long_s_staging": "c70692ed48ec89dc344df4e0", +"orders_model_0": "dc7f3dec778fd7cc3b47de47", +"orders_model_1": "881ca8c2aa83a640eb0c27ab", +"orders_model_10": "0498564b827ff224871c5c16", +"orders_model_11": "1c545871d01b68d8cc5270d4", +"orders_model_12": "a9609afdd975480f9b30d313", +"orders_model_13": "e9a825f1c611bead0b731f83", +"orders_model_14": "5770c08feedcc514f8cdea74", +"orders_model_15": "511a913bdc473948a1d98b00", +"orders_model_16": "00e981e5c6d50e8e603b21d1", +"orders_model_17": "3397814b3d1156e0e851a303", +"orders_model_18": "81452dd48c4fac8e75395e03", +"orders_model_19": "4782036882204544bf9b8cc0", +"orders_model_2": "3d131ea2ed9d90f4404800c4", +"orders_model_20": "d5ad421755fa576851cd7eea", +"orders_model_21": "afdbc811f2683769c6065622", +"orders_model_22": "82ea73f8ec2b48e09123b28a", +"orders_model_23": "ebf7fe799455ca0ef8c2a02e", +"orders_model_3": "c3a07511c03df1968f2c5ff9", +"orders_model_4": "bf62990d9480cf71956fd3c9", +"orders_model_5": "60e141a5769c44084f76723b", +"orders_model_6": "2694202ab29ccd1ad221d427", +"orders_model_7": "f9be9d8e81fbd30196a2ba14", +"orders_model_8": "a0fc71fac4e12ec905ae953c", +"orders_model_9": "dadc55d42681e2d084d2c52b", +"payment_totals": "8cf82ad30e9cce84bc8a3529", +"payments_by_customer": "9e1265b9f4134636cb508259", +"pivot_0": "78dd4b3d90301ccd1e781295", +"pivot_1": "af151ba34f16c141fdee1ac3", +"pivot_2": "5cf2515c32c9c98b0a9d8315", +"pivot_3": "ae6c2278feec076b8e8bc0d9", +"status_amounts": "0fbfc8d810e430c5814769d6", +"status_passthrough": "57dbca31518ecf81d68ec4fe", +"umlaut_cte": "a4c1810f1e46ef2200a87309" +} +], +[ +"catalog", +"d9d2cf58d167ce9056b86b8b" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"c3cb3226e55a418829fd059c" +], +[ +"proof", +"b9689124495085d917d65ebf" +], +[ +"proof", +"4994bb2a572acbed6354a2bb" +], +[ +"proof", +"c3cb3226e55a418829fd059c" +], +[ +"proof", +"28c524727756a048843237ef" +], +[ +"proof", +"99b1ccea692774bb61737217" +], +[ +"shapes", +"78e5cd70ce361d823798634b" +], +[ +"models", +{ +"adapter_rules_cte": "01c88e0760e09990ec7e7f27", +"adapter_rules_staging": "d244bb9fd736be2a83c1c25f", +"adapter_rules_untyped_cte": "443d6a471f368f61895e97b7", +"dotless_i_staging": "0414cf2aabffee9324ca1152", +"long_s_cte": "22aa6898e4deee5e707a61c8", +"long_s_staging": "0ffc9fd6d1c6d34c2db07849", +"orders_model_0": "94f95487333b2561382c2981", +"orders_model_1": "1cbed5d338fb3ae061486bf7", +"orders_model_10": "5319ece7f82596acc6513f91", +"orders_model_11": "ccf2498a5b3526260f88df6f", +"orders_model_12": "cb6d3e8487b533349a2bad04", +"orders_model_13": "6c48a8656e02aa11445643e2", +"orders_model_14": "3c574035ecba3d30a27e46ce", +"orders_model_15": "530fb4a941e847207cba2410", +"orders_model_16": "a249acc516a880c9fbe25e88", +"orders_model_17": "7c698d2731cea40e031c9052", +"orders_model_18": "6d3a0df899304a5fff38b3f0", +"orders_model_19": "2cc4699fcfbfc50f29d34e4d", +"orders_model_2": "59a5d7fd62d3554715ee8ef0", +"orders_model_20": "1475a844903645d3154efcef", +"orders_model_21": "1d0e1910cfa54e2cf1cdf738", +"orders_model_22": "e1c0902ddf75d8f0324e3aeb", +"orders_model_23": "ccf2498a5b3526260f88df6f", +"orders_model_3": "7db0fac3e405cbc04ce12b67", +"orders_model_4": "3cebd1bd3941ee9edc8ae06e", +"orders_model_5": "0e62e59d1dbc1c842380f957", +"orders_model_6": "6d3a0df899304a5fff38b3f0", +"orders_model_7": "dfa55753fe76745de6964097", +"orders_model_8": "bdc843833774d4e2ce081a50", +"orders_model_9": "f6f4f76cf2077ee259b60302", +"payment_totals": "80bd8eb5eab6ed918ec31949", +"payments_by_customer": "9e1265b9f4134636cb508259", +"pivot_0": "8d7a74ec77a418a6a2641b84", +"pivot_1": "78dd4b3d90301ccd1e781295", +"pivot_2": "b2268fc29a60313e3b8c34ed", +"pivot_3": "5adb7a56c3dfd3d1c3cf58c1", +"status_amounts": "0fbfc8d810e430c5814769d6", +"status_passthrough": "bbd8b7298ce68a222ba84345", +"umlaut_cte": "52e72621ebb88c5fc2a9fe35" +} +], +[ +"catalog", +"a72c104311c712bf9eada7e3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"c67f69d1828d209a58642e36" +], +[ +"proof", +"c67f69d1828d209a58642e36" +], +[ +"proof", +"b9689124495085d917d65ebf" +], +[ +"proof", +"c67f69d1828d209a58642e36" +], +[ +"proof", +"c67f69d1828d209a58642e36" +], +[ +"proof", +"99b1ccea692774bb61737217" +], +[ +"shapes", +"78e5cd70ce361d823798634b" +], +[ +"models", +{ +"adapter_rules_cte": "dfd1ab68201bde357955ba7f", +"adapter_rules_staging": "1647edbe8ac61356261cfa76", +"adapter_rules_untyped_cte": "6d7a85f4f3ff37fb43fdc0b4", +"dotless_i_staging": "4c25b6514c8939c1579e7729", +"long_s_cte": "22aa6898e4deee5e707a61c8", +"long_s_staging": "c70692ed48ec89dc344df4e0", +"orders_model_0": "c380ae05f3bd0627628ab6fc", +"orders_model_1": "1cbed5d338fb3ae061486bf7", +"orders_model_10": "d02e5f6991f3149f83f298e7", +"orders_model_11": "ccf2498a5b3526260f88df6f", +"orders_model_12": "edf57c58d750226a747455ba", +"orders_model_13": "c6fe9d63cebac8a82557647b", +"orders_model_14": "3c574035ecba3d30a27e46ce", +"orders_model_15": "530fb4a941e847207cba2410", +"orders_model_16": "d545cb7b8ca26b55d32439c0", +"orders_model_17": "7c698d2731cea40e031c9052", +"orders_model_18": "7431806bd67f9e0c952a98ab", +"orders_model_19": "2cc4699fcfbfc50f29d34e4d", +"orders_model_2": "808d76e03e1b6ed06eb32fe2", +"orders_model_20": "cb78e3704fcaf1883d3f635d", +"orders_model_21": "1d0e1910cfa54e2cf1cdf738", +"orders_model_22": "a431a1c7e46ac0fd16f20095", +"orders_model_23": "ccf2498a5b3526260f88df6f", +"orders_model_3": "7db0fac3e405cbc04ce12b67", +"orders_model_4": "3d86c54cb0dcd3d2cb0b7792", +"orders_model_5": "9a08a024fd692ca500ba98be", +"orders_model_6": "7431806bd67f9e0c952a98ab", +"orders_model_7": "35db1baf4dd2d3ddfefa9829", +"orders_model_8": "bdc843833774d4e2ce081a50", +"orders_model_9": "5748db46e2a60c5fb4056bfc", +"payment_totals": "8cf82ad30e9cce84bc8a3529", +"payments_by_customer": "9e1265b9f4134636cb508259", +"pivot_0": "8d7a74ec77a418a6a2641b84", +"pivot_1": "78dd4b3d90301ccd1e781295", +"pivot_2": "af151ba34f16c141fdee1ac3", +"pivot_3": "5adb7a56c3dfd3d1c3cf58c1", +"status_amounts": "0fbfc8d810e430c5814769d6", +"status_passthrough": "57dbca31518ecf81d68ec4fe", +"umlaut_cte": "a4c1810f1e46ef2200a87309" +} +], +[ +"catalog", +"9d696237ea0f619ed4dee48f" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"0d91dfe8eefbbb36998db250" +], +[ +"proof", +"28c524727756a048843237ef" +], +[ +"proof", +"b9689124495085d917d65ebf" +], +[ +"proof", +"1241165b261dcfe84ece9067" +], +[ +"proof", +"28c524727756a048843237ef" +], +[ +"proof", +"99b1ccea692774bb61737217" +] +] diff --git a/tests/goldens/python_oracle/analysis_generated_snowflake_and_duckdb_adapter_rules_rich_lineage.json b/tests/goldens/python_oracle/analysis_generated_snowflake_and_duckdb_adapter_rules_rich_lineage.json new file mode 100644 index 0000000000..a2f20ee860 --- /dev/null +++ b/tests/goldens/python_oracle/analysis_generated_snowflake_and_duckdb_adapter_rules_rich_lineage.json @@ -0,0 +1,1250 @@ +[ +[ +"shapes", +"78e5cd70ce361d823798634b" +], +[ +"models", +{ +"adapter_rules_cte": "dfd1ab68201bde357955ba7f", +"adapter_rules_staging": "d244bb9fd736be2a83c1c25f", +"adapter_rules_untyped_cte": "443d6a471f368f61895e97b7", +"dotless_i_staging": "4c25b6514c8939c1579e7729", +"long_s_cte": "22aa6898e4deee5e707a61c8", +"long_s_staging": "c70692ed48ec89dc344df4e0", +"orders_model_0": "94f95487333b2561382c2981", +"orders_model_1": "0c505e7c91961ed939fa9101", +"orders_model_10": "6a9dd6631afe2aecba420032", +"orders_model_11": "e0a1bcae33bbfb164c9468f6", +"orders_model_12": "926f7b801edc86d0d0ecbac0", +"orders_model_13": "8af6ca52fb84b5b173b2326d", +"orders_model_14": "c1ec6ecf89992261001a255f", +"orders_model_15": "b381e86843932813f7ad5b91", +"orders_model_16": "16ae4650da78bf9861f65553", +"orders_model_17": "ee556ea5f790f1d885cee84a", +"orders_model_18": "ff71888baeb777eb8b0d274d", +"orders_model_19": "92a8e66d811c1497a2216783", +"orders_model_2": "b1cffebb5797fe684c20e885", +"orders_model_20": "839fac6b32ebf58d515e9451", +"orders_model_21": "29e669ac95b4e44f7d8ea530", +"orders_model_22": "8d9a8370c5bb21b381f42208", +"orders_model_23": "fe73a080f7f7a3e1df6c305c", +"orders_model_3": "a5927681bfbf9d44f4723990", +"orders_model_4": "10c324ddebd8f360f30b0a6b", +"orders_model_5": "3fc282000bb67e74433ffd40", +"orders_model_6": "e813ee34de06d5cae82ac8c2", +"orders_model_7": "2cc4699fcfbfc50f29d34e4d", +"orders_model_8": "82c19ad1bdebebf9b9e99f2c", +"orders_model_9": "0b71c12f30a7617191bc2e17", +"payment_totals": "ddedaaeda0bdb9d9997ac6cd", +"payments_by_customer": "da1968ec91b55f6f584c7ecd", +"pivot_0": "8ffb88803fba96f5e1a0cc14", +"pivot_1": "5adb7a56c3dfd3d1c3cf58c1", +"pivot_2": "78dd4b3d90301ccd1e781295", +"pivot_3": "b2268fc29a60313e3b8c34ed", +"status_amounts": "0fbfc8d810e430c5814769d6", +"status_passthrough": "bbd8b7298ce68a222ba84345", +"umlaut_cte": "52e72621ebb88c5fc2a9fe35" +} +], +[ +"catalog", +"e2fa30056701edaf7a347f5b" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"20e6b6374d63663154468bed" +], +[ +"proof", +"c67f69d1828d209a58642e36" +], +[ +"proof", +"c67f69d1828d209a58642e36" +], +[ +"proof", +"b9689124495085d917d65ebf" +], +[ +"proof", +"c67f69d1828d209a58642e36" +], +[ +"proof", +"99b1ccea692774bb61737217" +], +[ +"shapes", +"78e5cd70ce361d823798634b" +], +[ +"models", +{ +"adapter_rules_cte": "dfd1ab68201bde357955ba7f", +"adapter_rules_staging": "1647edbe8ac61356261cfa76", +"adapter_rules_untyped_cte": "6d7a85f4f3ff37fb43fdc0b4", +"dotless_i_staging": "4c25b6514c8939c1579e7729", +"long_s_cte": "22aa6898e4deee5e707a61c8", +"long_s_staging": "c70692ed48ec89dc344df4e0", +"orders_model_0": "c380ae05f3bd0627628ab6fc", +"orders_model_1": "0897bc61ca6a0042539889cd", +"orders_model_10": "6a9dd6631afe2aecba420032", +"orders_model_11": "e0a1bcae33bbfb164c9468f6", +"orders_model_12": "fd707ea6f93871b0dc83c579", +"orders_model_13": "74b30199b5f8cc665f133e68", +"orders_model_14": "c1ec6ecf89992261001a255f", +"orders_model_15": "7f3924ba267d897cc875a294", +"orders_model_16": "5464f219a5381063a5cf2965", +"orders_model_17": "afd6d68f0a0a6689404e0260", +"orders_model_18": "ff71888baeb777eb8b0d274d", +"orders_model_19": "92a8e66d811c1497a2216783", +"orders_model_2": "b1cffebb5797fe684c20e885", +"orders_model_20": "839fac6b32ebf58d515e9451", +"orders_model_21": "af5f39f23b7c2b58d3f12930", +"orders_model_22": "3abd2e6a08df2cf8322bf309", +"orders_model_23": "fe73a080f7f7a3e1df6c305c", +"orders_model_3": "a5927681bfbf9d44f4723990", +"orders_model_4": "c868aee07ab0f13c50fadca2", +"orders_model_5": "3fc282000bb67e74433ffd40", +"orders_model_6": "7431806bd67f9e0c952a98ab", +"orders_model_7": "2cc4699fcfbfc50f29d34e4d", +"orders_model_8": "82c19ad1bdebebf9b9e99f2c", +"orders_model_9": "0b71c12f30a7617191bc2e17", +"payment_totals": "ce8a97426d53e0acd6c49c2b", +"payments_by_customer": "da1968ec91b55f6f584c7ecd", +"pivot_0": "8ffb88803fba96f5e1a0cc14", +"pivot_1": "5adb7a56c3dfd3d1c3cf58c1", +"pivot_2": "78dd4b3d90301ccd1e781295", +"pivot_3": "af151ba34f16c141fdee1ac3", +"status_amounts": "0fbfc8d810e430c5814769d6", +"status_passthrough": "57dbca31518ecf81d68ec4fe", +"umlaut_cte": "a4c1810f1e46ef2200a87309" +} +], +[ +"catalog", +"73e2d7913705a099c6c0de21" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"20e6b6374d63663154468bed" +], +[ +"proof", +"9e3cc9a00de191a2a3a3a27f" +], +[ +"proof", +"28c524727756a048843237ef" +], +[ +"proof", +"b9689124495085d917d65ebf" +], +[ +"proof", +"28c524727756a048843237ef" +], +[ +"proof", +"99b1ccea692774bb61737217" +], +[ +"shapes", +"78e5cd70ce361d823798634b" +], +[ +"models", +{ +"adapter_rules_cte": "dfd1ab68201bde357955ba7f", +"adapter_rules_staging": "d244bb9fd736be2a83c1c25f", +"adapter_rules_untyped_cte": "443d6a471f368f61895e97b7", +"dotless_i_staging": "4c25b6514c8939c1579e7729", +"long_s_cte": "22aa6898e4deee5e707a61c8", +"long_s_staging": "c70692ed48ec89dc344df4e0", +"orders_model_0": "c0a4a49f398790b6968ded9b", +"orders_model_1": "8f27fcd3be57b9a85a5ade04", +"orders_model_10": "b57ee1c35cbaadb688298310", +"orders_model_11": "1c545871d01b68d8cc5270d4", +"orders_model_12": "a7868c059b8f4ff1fe264c2a", +"orders_model_13": "356f32e628d61db27bf4a4f3", +"orders_model_14": "5770c08feedcc514f8cdea74", +"orders_model_15": "6d334b184def14c92a91f6fe", +"orders_model_16": "7a40989a4e6cf23c222525f6", +"orders_model_17": "74820176e511b43c55d5dcb7", +"orders_model_18": "864293c567900a908d92f817", +"orders_model_19": "2d58b808566d04184cf9ab29", +"orders_model_2": "3d131ea2ed9d90f4404800c4", +"orders_model_20": "9ea231ae7342ed67e393353e", +"orders_model_21": "afdbc811f2683769c6065622", +"orders_model_22": "1ecee061003eefdd8e7b3e1d", +"orders_model_23": "ebf7fe799455ca0ef8c2a02e", +"orders_model_3": "2136d13b1291a5e9dd31e887", +"orders_model_4": "0eca13897e0abb4131837a39", +"orders_model_5": "7a9fabf5b3d3ab9e1fc63a99", +"orders_model_6": "ea32e1b4eb22b26be9f440ed", +"orders_model_7": "f9be9d8e81fbd30196a2ba14", +"orders_model_8": "a0fc71fac4e12ec905ae953c", +"orders_model_9": "f6f4f76cf2077ee259b60302", +"payment_totals": "ddedaaeda0bdb9d9997ac6cd", +"payments_by_customer": "da1968ec91b55f6f584c7ecd", +"pivot_0": "78dd4b3d90301ccd1e781295", +"pivot_1": "b2268fc29a60313e3b8c34ed", +"pivot_2": "5cf2515c32c9c98b0a9d8315", +"pivot_3": "ae6c2278feec076b8e8bc0d9", +"status_amounts": "0fbfc8d810e430c5814769d6", +"status_passthrough": "bbd8b7298ce68a222ba84345", +"umlaut_cte": "52e72621ebb88c5fc2a9fe35" +} +], +[ +"catalog", +"5566f9b034670ebc7d57c741" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"c67f69d1828d209a58642e36" +], +[ +"proof", +"b9689124495085d917d65ebf" +], +[ +"proof", +"c67f69d1828d209a58642e36" +], +[ +"proof", +"c67f69d1828d209a58642e36" +], +[ +"proof", +"c67f69d1828d209a58642e36" +], +[ +"proof", +"99b1ccea692774bb61737217" +], +[ +"shapes", +"78e5cd70ce361d823798634b" +], +[ +"models", +{ +"adapter_rules_cte": "dfd1ab68201bde357955ba7f", +"adapter_rules_staging": "1647edbe8ac61356261cfa76", +"adapter_rules_untyped_cte": "6d7a85f4f3ff37fb43fdc0b4", +"dotless_i_staging": "4c25b6514c8939c1579e7729", +"long_s_cte": "22aa6898e4deee5e707a61c8", +"long_s_staging": "c70692ed48ec89dc344df4e0", +"orders_model_0": "dc7f3dec778fd7cc3b47de47", +"orders_model_1": "881ca8c2aa83a640eb0c27ab", +"orders_model_10": "0498564b827ff224871c5c16", +"orders_model_11": "1c545871d01b68d8cc5270d4", +"orders_model_12": "1b5b1859d336c6311e9827f1", +"orders_model_13": "e9a825f1c611bead0b731f83", +"orders_model_14": "5770c08feedcc514f8cdea74", +"orders_model_15": "6d334b184def14c92a91f6fe", +"orders_model_16": "00e981e5c6d50e8e603b21d1", +"orders_model_17": "3397814b3d1156e0e851a303", +"orders_model_18": "81452dd48c4fac8e75395e03", +"orders_model_19": "4782036882204544bf9b8cc0", +"orders_model_2": "3d131ea2ed9d90f4404800c4", +"orders_model_20": "b69caa0299e13825ed690cb8", +"orders_model_21": "afdbc811f2683769c6065622", +"orders_model_22": "82ea73f8ec2b48e09123b28a", +"orders_model_23": "ebf7fe799455ca0ef8c2a02e", +"orders_model_3": "2136d13b1291a5e9dd31e887", +"orders_model_4": "bf62990d9480cf71956fd3c9", +"orders_model_5": "458d9725be39144ca5e0c33d", +"orders_model_6": "4359abfef23a7b1e646d2aee", +"orders_model_7": "f9be9d8e81fbd30196a2ba14", +"orders_model_8": "a0fc71fac4e12ec905ae953c", +"orders_model_9": "dadc55d42681e2d084d2c52b", +"payment_totals": "ce8a97426d53e0acd6c49c2b", +"payments_by_customer": "da1968ec91b55f6f584c7ecd", +"pivot_0": "78dd4b3d90301ccd1e781295", +"pivot_1": "af151ba34f16c141fdee1ac3", +"pivot_2": "5cf2515c32c9c98b0a9d8315", +"pivot_3": "ae6c2278feec076b8e8bc0d9", +"status_amounts": "0fbfc8d810e430c5814769d6", +"status_passthrough": "57dbca31518ecf81d68ec4fe", +"umlaut_cte": "a4c1810f1e46ef2200a87309" +} +], +[ +"catalog", +"eff03c0ebcf2c6323671b7ee" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"c3cb3226e55a418829fd059c" +], +[ +"proof", +"b9689124495085d917d65ebf" +], +[ +"proof", +"4994bb2a572acbed6354a2bb" +], +[ +"proof", +"c3cb3226e55a418829fd059c" +], +[ +"proof", +"28c524727756a048843237ef" +], +[ +"proof", +"99b1ccea692774bb61737217" +], +[ +"shapes", +"78e5cd70ce361d823798634b" +], +[ +"models", +{ +"adapter_rules_cte": "dfd1ab68201bde357955ba7f", +"adapter_rules_staging": "d244bb9fd736be2a83c1c25f", +"adapter_rules_untyped_cte": "443d6a471f368f61895e97b7", +"dotless_i_staging": "4c25b6514c8939c1579e7729", +"long_s_cte": "22aa6898e4deee5e707a61c8", +"long_s_staging": "c70692ed48ec89dc344df4e0", +"orders_model_0": "94f95487333b2561382c2981", +"orders_model_1": "1cbed5d338fb3ae061486bf7", +"orders_model_10": "5a31508076b33a63eb5f6f5a", +"orders_model_11": "ccf2498a5b3526260f88df6f", +"orders_model_12": "2d47664882f4e1df073137de", +"orders_model_13": "6c48a8656e02aa11445643e2", +"orders_model_14": "5324123258199836670bd610", +"orders_model_15": "27153ec6b977ca8e32094d2f", +"orders_model_16": "a249acc516a880c9fbe25e88", +"orders_model_17": "b29a2c85abeb6ad80d6890c3", +"orders_model_18": "e813ee34de06d5cae82ac8c2", +"orders_model_19": "2cc4699fcfbfc50f29d34e4d", +"orders_model_2": "3302ce3fd2e8a684f2be9632", +"orders_model_20": "e4ff6e5c3b52a9c5568a3ff1", +"orders_model_21": "1d0e1910cfa54e2cf1cdf738", +"orders_model_22": "e1c0902ddf75d8f0324e3aeb", +"orders_model_23": "ccf2498a5b3526260f88df6f", +"orders_model_3": "80151fc977ccd29484c79a45", +"orders_model_4": "1fe47e48e7adf0e94261cf1d", +"orders_model_5": "f9183611419f32c78a12fbc4", +"orders_model_6": "e813ee34de06d5cae82ac8c2", +"orders_model_7": "dfa55753fe76745de6964097", +"orders_model_8": "bdc843833774d4e2ce081a50", +"orders_model_9": "f6f4f76cf2077ee259b60302", +"payment_totals": "ddedaaeda0bdb9d9997ac6cd", +"payments_by_customer": "da1968ec91b55f6f584c7ecd", +"pivot_0": "8d7a74ec77a418a6a2641b84", +"pivot_1": "78dd4b3d90301ccd1e781295", +"pivot_2": "b2268fc29a60313e3b8c34ed", +"pivot_3": "5adb7a56c3dfd3d1c3cf58c1", +"status_amounts": "0fbfc8d810e430c5814769d6", +"status_passthrough": "bbd8b7298ce68a222ba84345", +"umlaut_cte": "52e72621ebb88c5fc2a9fe35" +} +], +[ +"catalog", +"495c0f20724d3290a1990d2d" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"c67f69d1828d209a58642e36" +], +[ +"proof", +"c67f69d1828d209a58642e36" +], +[ +"proof", +"b9689124495085d917d65ebf" +], +[ +"proof", +"c67f69d1828d209a58642e36" +], +[ +"proof", +"c67f69d1828d209a58642e36" +], +[ +"proof", +"99b1ccea692774bb61737217" +], +[ +"shapes", +"78e5cd70ce361d823798634b" +], +[ +"models", +{ +"adapter_rules_cte": "dfd1ab68201bde357955ba7f", +"adapter_rules_staging": "1647edbe8ac61356261cfa76", +"adapter_rules_untyped_cte": "6d7a85f4f3ff37fb43fdc0b4", +"dotless_i_staging": "4c25b6514c8939c1579e7729", +"long_s_cte": "22aa6898e4deee5e707a61c8", +"long_s_staging": "c70692ed48ec89dc344df4e0", +"orders_model_0": "c380ae05f3bd0627628ab6fc", +"orders_model_1": "1cbed5d338fb3ae061486bf7", +"orders_model_10": "d02e5f6991f3149f83f298e7", +"orders_model_11": "ccf2498a5b3526260f88df6f", +"orders_model_12": "a030043d592af380cf44cb9f", +"orders_model_13": "c6fe9d63cebac8a82557647b", +"orders_model_14": "5324123258199836670bd610", +"orders_model_15": "27153ec6b977ca8e32094d2f", +"orders_model_16": "d545cb7b8ca26b55d32439c0", +"orders_model_17": "b29a2c85abeb6ad80d6890c3", +"orders_model_18": "7431806bd67f9e0c952a98ab", +"orders_model_19": "2cc4699fcfbfc50f29d34e4d", +"orders_model_2": "3302ce3fd2e8a684f2be9632", +"orders_model_20": "e4ff6e5c3b52a9c5568a3ff1", +"orders_model_21": "1d0e1910cfa54e2cf1cdf738", +"orders_model_22": "a431a1c7e46ac0fd16f20095", +"orders_model_23": "ccf2498a5b3526260f88df6f", +"orders_model_3": "80151fc977ccd29484c79a45", +"orders_model_4": "3d86c54cb0dcd3d2cb0b7792", +"orders_model_5": "f9183611419f32c78a12fbc4", +"orders_model_6": "7431806bd67f9e0c952a98ab", +"orders_model_7": "35db1baf4dd2d3ddfefa9829", +"orders_model_8": "bdc843833774d4e2ce081a50", +"orders_model_9": "5748db46e2a60c5fb4056bfc", +"payment_totals": "ce8a97426d53e0acd6c49c2b", +"payments_by_customer": "da1968ec91b55f6f584c7ecd", +"pivot_0": "8d7a74ec77a418a6a2641b84", +"pivot_1": "78dd4b3d90301ccd1e781295", +"pivot_2": "af151ba34f16c141fdee1ac3", +"pivot_3": "5adb7a56c3dfd3d1c3cf58c1", +"status_amounts": "0fbfc8d810e430c5814769d6", +"status_passthrough": "57dbca31518ecf81d68ec4fe", +"umlaut_cte": "a4c1810f1e46ef2200a87309" +} +], +[ +"catalog", +"d2a0f4ec04fb9eac758c1993" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"0d91dfe8eefbbb36998db250" +], +[ +"proof", +"28c524727756a048843237ef" +], +[ +"proof", +"b9689124495085d917d65ebf" +], +[ +"proof", +"1241165b261dcfe84ece9067" +], +[ +"proof", +"28c524727756a048843237ef" +], +[ +"proof", +"99b1ccea692774bb61737217" +] +] diff --git a/tests/goldens/python_oracle/analysis_generated_stars_ctes_cte_facts_set_operations_untyped_inputs_contracts_pivots.json b/tests/goldens/python_oracle/analysis_generated_stars_ctes_cte_facts_set_operations_untyped_inputs_contracts_pivots.json new file mode 100644 index 0000000000..b3c3149315 --- /dev/null +++ b/tests/goldens/python_oracle/analysis_generated_stars_ctes_cte_facts_set_operations_untyped_inputs_contracts_pivots.json @@ -0,0 +1,3458 @@ +[ +[ +"shapes", +"78e5cd70ce361d823798634b" +], +[ +"models", +{ +"orders_model_0": "7dde13e57109cfb992bc623d", +"orders_model_1": "6f741725ae5781425358bc3b", +"orders_model_10": "c7e95ff7d90362e121ab238f", +"orders_model_11": "05479b1f55d5c854f9729a97", +"orders_model_12": "c380ae05f3bd0627628ab6fc", +"orders_model_13": "15537f706967682b808641f6", +"orders_model_14": "0506ac9813ca91fe571266cd", +"orders_model_15": "4ea093ff48f97c35927ecbbd", +"orders_model_16": "3dbaddb57a2ed5f8db44feda", +"orders_model_17": "7cc87d8c32df82057dc6057d", +"orders_model_18": "6b0c7fdf2bf74107bd96a6ff", +"orders_model_19": "4782036882204544bf9b8cc0", +"orders_model_2": "27b686e0958c19d151cd6319", +"orders_model_20": "12e4c14a088d64a94a267025", +"orders_model_21": "7a96226f82f52625a17f825f", +"orders_model_22": "74a4ef50a4b351777410e3ae", +"orders_model_23": "14b86bcb1a8edc065f4c7405", +"orders_model_3": "482e641536f8899b756807cf", +"orders_model_4": "526ce0a1d0a274582f9d35f1", +"orders_model_5": "9a08a024fd692ca500ba98be", +"orders_model_6": "526c167cb476b3553de71042", +"orders_model_7": "f9be9d8e81fbd30196a2ba14", +"orders_model_8": "800e86b4e6a207eda6a59688", +"orders_model_9": "7c6d6c8fb64f5bfb121ebac1", +"payment_totals": "8cf82ad30e9cce84bc8a3529", +"payments_by_customer": "9e1265b9f4134636cb508259", +"pivot_0": "335dfa47b776524b62ee26e6", +"pivot_1": "78dd4b3d90301ccd1e781295", +"pivot_2": "3767f4902ed5f3ab1acc83a1", +"pivot_3": "826e0ad9aec9b04097d58b37", +"status_amounts": "0fbfc8d810e430c5814769d6", +"status_passthrough": "57dbca31518ecf81d68ec4fe" +} +], +[ +"catalog", +"6232f045280d66a7b86567e9" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"20e6b6374d63663154468bed" +], +[ +"proof", +"ff4d4f462aae3b9e95d9a5ab" +], +[ +"proof", +"20e6b6374d63663154468bed" +], +[ +"proof", +"e718df74c851405aa9e05532" +], +[ +"proof", +"28c524727756a048843237ef" +], +[ +"proof", +"99b1ccea692774bb61737217" +], +[ +"shapes", +"b40871514fad0707c8cdbee7" +], +[ +"models", +{ +"orders_model_0": "7dde13e57109cfb992bc623d", +"orders_model_1": "6f741725ae5781425358bc3b", +"orders_model_10": "c7e95ff7d90362e121ab238f", +"orders_model_11": "05479b1f55d5c854f9729a97", +"orders_model_12": "c380ae05f3bd0627628ab6fc", +"orders_model_13": "462bf85d3521fa64063b2e26", +"orders_model_14": "0506ac9813ca91fe571266cd", +"orders_model_15": "4ea093ff48f97c35927ecbbd", +"orders_model_16": "3dbaddb57a2ed5f8db44feda", +"orders_model_17": "7cc87d8c32df82057dc6057d", +"orders_model_18": "6b0c7fdf2bf74107bd96a6ff", +"orders_model_19": "2d58b808566d04184cf9ab29", +"orders_model_2": "27b686e0958c19d151cd6319", +"orders_model_20": "83395d349a292162557b74ba", +"orders_model_21": "7a96226f82f52625a17f825f", +"orders_model_22": "74a4ef50a4b351777410e3ae", +"orders_model_23": "14b86bcb1a8edc065f4c7405", +"orders_model_3": "482e641536f8899b756807cf", +"orders_model_4": "75f6764c319047022968f0b3", +"orders_model_5": "07dc61a646b8222df8eccb85", +"orders_model_6": "526c167cb476b3553de71042", +"orders_model_7": "f9be9d8e81fbd30196a2ba14", +"orders_model_8": "e88481648db54aa4b3e3b0d6", +"orders_model_9": "7c6d6c8fb64f5bfb121ebac1", +"payment_totals": "10740c01d3d11a1de6799033", +"payments_by_customer": "e406a89772022ea3c32aefef", +"pivot_0": "335dfa47b776524b62ee26e6", +"pivot_1": "78dd4b3d90301ccd1e781295", +"pivot_2": "3767f4902ed5f3ab1acc83a1", +"pivot_3": "826e0ad9aec9b04097d58b37", +"status_amounts": "0fbfc8d810e430c5814769d6", +"status_passthrough": "57dbca31518ecf81d68ec4fe" +} +], +[ +"catalog", +"b316f125f0e7703dd9e37065" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"200eb30f2a045b54792500f6" +], +[ +"proof", +"200eb30f2a045b54792500f6" +], +[ +"proof", +"200eb30f2a045b54792500f6" +], +[ +"proof", +"200eb30f2a045b54792500f6" +], +[ +"proof", +"200eb30f2a045b54792500f6" +], +[ +"proof", +"200eb30f2a045b54792500f6" +], +[ +"shapes", +"78e5cd70ce361d823798634b" +], +[ +"models", +{ +"orders_model_0": "1c5f7e1a73535a5617fb070a", +"orders_model_1": "ff37aa9e31c0ddbc7f05cba2", +"orders_model_10": "315f07530cae631f3e373e9d", +"orders_model_11": "05479b1f55d5c854f9729a97", +"orders_model_12": "94f95487333b2561382c2981", +"orders_model_13": "f73e95ff8968d95ed11dc4f3", +"orders_model_14": "0506ac9813ca91fe571266cd", +"orders_model_15": "4ea093ff48f97c35927ecbbd", +"orders_model_16": "1a6c68f8be75e24bf3304cdb", +"orders_model_17": "2b9d7cab1383a6532589c1ae", +"orders_model_18": "b1a0e72c622ac940a7b5fb00", +"orders_model_19": "2d58b808566d04184cf9ab29", +"orders_model_2": "27b686e0958c19d151cd6319", +"orders_model_20": "207a0ee79521c1a9b4effb31", +"orders_model_21": "c669dc21fed757d7809fc424", +"orders_model_22": "066b8f5bf2be63a888045fe7", +"orders_model_23": "14b86bcb1a8edc065f4c7405", +"orders_model_3": "482e641536f8899b756807cf", +"orders_model_4": "1cefa36f28721fe677e6a684", +"orders_model_5": "0e62e59d1dbc1c842380f957", +"orders_model_6": "c72d1a9250666a5ac7e54369", +"orders_model_7": "f9be9d8e81fbd30196a2ba14", +"orders_model_8": "8454628161253c1b281bb22f", +"orders_model_9": "7c6d6c8fb64f5bfb121ebac1", +"payment_totals": "80bd8eb5eab6ed918ec31949", +"payments_by_customer": "9e1265b9f4134636cb508259", +"pivot_0": "335dfa47b776524b62ee26e6", +"pivot_1": "78dd4b3d90301ccd1e781295", +"pivot_2": "3767f4902ed5f3ab1acc83a1", +"pivot_3": "826e0ad9aec9b04097d58b37", +"status_amounts": "0fbfc8d810e430c5814769d6", +"status_passthrough": "bbd8b7298ce68a222ba84345" +} +], +[ +"catalog", +"b749d066f2cc882b93817838" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"20e6b6374d63663154468bed" +], +[ +"proof", +"c67f69d1828d209a58642e36" +], +[ +"proof", +"c67f69d1828d209a58642e36" +], +[ +"proof", +"c67f69d1828d209a58642e36" +], +[ +"proof", +"c67f69d1828d209a58642e36" +], +[ +"proof", +"99b1ccea692774bb61737217" +], +[ +"shapes", +"c0d3bfda902cb95cd1564269" +], +[ +"models", +{ +"orders_model_0": "dc4da2070db56afde4157773", +"orders_model_1": "9b0cc36921b5b8b8a8dea025", +"orders_model_10": "d4f810ff3ba14295385d6fb9", +"orders_model_11": "f7cdb34524d45acad3b71f7d", +"orders_model_12": "c380ae05f3bd0627628ab6fc", +"orders_model_13": "9f0321d97fb59396dfa496d9", +"orders_model_14": "0506ac9813ca91fe571266cd", +"orders_model_15": "4ea093ff48f97c35927ecbbd", +"orders_model_16": "c5a645b8cfb02ddc927fc297", +"orders_model_17": "669b30fefd09621ed0f2ad55", +"orders_model_18": "60e19e6908bb5c06d38eeb01", +"orders_model_19": "5318b049f2f651a689fb5e87", +"orders_model_2": "361de61cfd22f09af946862f", +"orders_model_20": "032990c645506e1e133c4cd0", +"orders_model_21": "9c26876fe71c235386932362", +"orders_model_22": "86880e31d61c6c5522256c62", +"orders_model_23": "209048028aa76bf4c2bd28c6", +"orders_model_3": "482e641536f8899b756807cf", +"orders_model_4": "4c809f6cf2e946ba98b1ec73", +"orders_model_5": "e672120be8dbea0cda9c4f28", +"orders_model_6": "a903f36871fea6d8ac818922", +"orders_model_7": "a4c400c5fa2da4107098339e", +"orders_model_8": "aba445941b1d72b9d3d5acb6", +"orders_model_9": "67dc0f1b5ce04c8989ad1aca", +"payment_totals": "10740c01d3d11a1de6799033", +"payments_by_customer": "c29bf4a09e3c8e9cff564a2f", +"pivot_0": "335dfa47b776524b62ee26e6", +"pivot_1": "78dd4b3d90301ccd1e781295", +"pivot_2": "3767f4902ed5f3ab1acc83a1", +"pivot_3": "826e0ad9aec9b04097d58b37", +"status_amounts": "0fbfc8d810e430c5814769d6", +"status_passthrough": "26ba5a13355d37dfa8e67820" +} +], +[ +"catalog", +"9c7db1355dd2394241b43e81" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"shapes", +"78e5cd70ce361d823798634b" +], +[ +"models", +{ +"orders_model_0": "7dde13e57109cfb992bc623d", +"orders_model_1": "73d5e99497d80b919e0d5491", +"orders_model_10": "31ba43d1ed6f0701481c543b", +"orders_model_11": "ac182afebaeb1ab5a7b50a67", +"orders_model_12": "7c1f7afa32f56956c9bb5806", +"orders_model_13": "3676088fa7438b6033da7334", +"orders_model_14": "c5aa1f63d80b5d306477c290", +"orders_model_15": "a533a3838eb00372891616ed", +"orders_model_16": "3122402ab671f4438c8209d7", +"orders_model_17": "769e25e737cf7832171d8837", +"orders_model_18": "099cb926af524f10d27cc108", +"orders_model_19": "f9be9d8e81fbd30196a2ba14", +"orders_model_2": "3a3bfc6019ae1cf18c714dd0", +"orders_model_20": "c2da59cc5e833d3421094ea9", +"orders_model_21": "7c6d6c8fb64f5bfb121ebac1", +"orders_model_22": "866b4de40862e3cc32f54936", +"orders_model_23": "79c750e0d8bd9a28f05f6337", +"orders_model_3": "f922a0153bfa71727dd6241a", +"orders_model_4": "526ce0a1d0a274582f9d35f1", +"orders_model_5": "b0f2950e6d0c6c8ba60db1ca", +"orders_model_6": "38187a959e7cbbef799b5777", +"orders_model_7": "20835381aab849fd35068525", +"orders_model_8": "72717ea55695667a7b7d8b39", +"orders_model_9": "d34e456ade2ced8792534866", +"payment_totals": "8cf82ad30e9cce84bc8a3529", +"payments_by_customer": "9e1265b9f4134636cb508259", +"pivot_0": "db45532b4aa0746bb6155579", +"pivot_1": "826e0ad9aec9b04097d58b37", +"pivot_2": "78dd4b3d90301ccd1e781295", +"pivot_3": "af151ba34f16c141fdee1ac3", +"status_amounts": "0fbfc8d810e430c5814769d6", +"status_passthrough": "57dbca31518ecf81d68ec4fe" +} +], +[ +"catalog", +"a27824cf887c032c6fee964b" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"0d91dfe8eefbbb36998db250" +], +[ +"proof", +"24ec11d3b54173b8b7b769ff" +], +[ +"proof", +"c3cb3226e55a418829fd059c" +], +[ +"proof", +"b9689124495085d917d65ebf" +], +[ +"proof", +"28c524727756a048843237ef" +], +[ +"proof", +"99b1ccea692774bb61737217" +], +[ +"shapes", +"b40871514fad0707c8cdbee7" +], +[ +"models", +{ +"orders_model_0": "7dde13e57109cfb992bc623d", +"orders_model_1": "73d5e99497d80b919e0d5491", +"orders_model_10": "8ef67d7c6546651d2f2e0b45", +"orders_model_11": "ac182afebaeb1ab5a7b50a67", +"orders_model_12": "7c1f7afa32f56956c9bb5806", +"orders_model_13": "cc456ea2e83298c9cd8206fb", +"orders_model_14": "59968e869226ce12e62c6b5e", +"orders_model_15": "a533a3838eb00372891616ed", +"orders_model_16": "a6740f24eddec216a1afc653", +"orders_model_17": "769e25e737cf7832171d8837", +"orders_model_18": "099cb926af524f10d27cc108", +"orders_model_19": "f9be9d8e81fbd30196a2ba14", +"orders_model_2": "3a3bfc6019ae1cf18c714dd0", +"orders_model_20": "c2da59cc5e833d3421094ea9", +"orders_model_21": "7c6d6c8fb64f5bfb121ebac1", +"orders_model_22": "866b4de40862e3cc32f54936", +"orders_model_23": "79c750e0d8bd9a28f05f6337", +"orders_model_3": "f922a0153bfa71727dd6241a", +"orders_model_4": "75f6764c319047022968f0b3", +"orders_model_5": "b0f2950e6d0c6c8ba60db1ca", +"orders_model_6": "38187a959e7cbbef799b5777", +"orders_model_7": "20835381aab849fd35068525", +"orders_model_8": "5e48e2da1954c3893344d4a8", +"orders_model_9": "d34e456ade2ced8792534866", +"payment_totals": "10740c01d3d11a1de6799033", +"payments_by_customer": "e406a89772022ea3c32aefef", +"pivot_0": "db45532b4aa0746bb6155579", +"pivot_1": "826e0ad9aec9b04097d58b37", +"pivot_2": "78dd4b3d90301ccd1e781295", +"pivot_3": "e6d82b48a7a5593bd747ea69", +"status_amounts": "0fbfc8d810e430c5814769d6", +"status_passthrough": "57dbca31518ecf81d68ec4fe" +} +], +[ +"catalog", +"4362f040d5943b99ffdc354f" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"200eb30f2a045b54792500f6" +], +[ +"proof", +"200eb30f2a045b54792500f6" +], +[ +"proof", +"200eb30f2a045b54792500f6" +], +[ +"proof", +"200eb30f2a045b54792500f6" +], +[ +"proof", +"200eb30f2a045b54792500f6" +], +[ +"proof", +"200eb30f2a045b54792500f6" +], +[ +"shapes", +"78e5cd70ce361d823798634b" +], +[ +"models", +{ +"orders_model_0": "1c5f7e1a73535a5617fb070a", +"orders_model_1": "828d747058993aeefdbae18a", +"orders_model_10": "83266a86a028c32724e8cd26", +"orders_model_11": "ac182afebaeb1ab5a7b50a67", +"orders_model_12": "2cbf8e290082ab49db794db4", +"orders_model_13": "3676088fa7438b6033da7334", +"orders_model_14": "59968e869226ce12e62c6b5e", +"orders_model_15": "a533a3838eb00372891616ed", +"orders_model_16": "b67d418ac9424b16909d6a26", +"orders_model_17": "769e25e737cf7832171d8837", +"orders_model_18": "5d2a8162e9742273846f69e3", +"orders_model_19": "f9be9d8e81fbd30196a2ba14", +"orders_model_2": "3a3bfc6019ae1cf18c714dd0", +"orders_model_20": "c2da59cc5e833d3421094ea9", +"orders_model_21": "7c6d6c8fb64f5bfb121ebac1", +"orders_model_22": "6e4d8e3c08d5ad97e417c6f7", +"orders_model_23": "79c750e0d8bd9a28f05f6337", +"orders_model_3": "f922a0153bfa71727dd6241a", +"orders_model_4": "1cefa36f28721fe677e6a684", +"orders_model_5": "b0f2950e6d0c6c8ba60db1ca", +"orders_model_6": "ade3350d63ecf8b7583ca5cb", +"orders_model_7": "20835381aab849fd35068525", +"orders_model_8": "e25266f92d285b11b68983a6", +"orders_model_9": "d34e456ade2ced8792534866", +"payment_totals": "80bd8eb5eab6ed918ec31949", +"payments_by_customer": "9e1265b9f4134636cb508259", +"pivot_0": "db45532b4aa0746bb6155579", +"pivot_1": "826e0ad9aec9b04097d58b37", +"pivot_2": "78dd4b3d90301ccd1e781295", +"pivot_3": "b2268fc29a60313e3b8c34ed", +"status_amounts": "0fbfc8d810e430c5814769d6", +"status_passthrough": "bbd8b7298ce68a222ba84345" +} +], +[ +"catalog", +"db139e73f95bffd34e7a6de5" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"c67f69d1828d209a58642e36" +], +[ +"proof", +"c67f69d1828d209a58642e36" +], +[ +"proof", +"c67f69d1828d209a58642e36" +], +[ +"proof", +"b9689124495085d917d65ebf" +], +[ +"proof", +"c67f69d1828d209a58642e36" +], +[ +"proof", +"99b1ccea692774bb61737217" +], +[ +"shapes", +"c0d3bfda902cb95cd1564269" +], +[ +"models", +{ +"orders_model_0": "dc4da2070db56afde4157773", +"orders_model_1": "3e1948d706ff1cecf42f7863", +"orders_model_10": "fbdacfcd4b561abe157cdfda", +"orders_model_11": "17515e5f7babd19ac587b1d3", +"orders_model_12": "b06fcf5168d718f9042eb9f0", +"orders_model_13": "25952bed7c264fceaeec357c", +"orders_model_14": "c5aa1f63d80b5d306477c290", +"orders_model_15": "a533a3838eb00372891616ed", +"orders_model_16": "b67d418ac9424b16909d6a26", +"orders_model_17": "769e25e737cf7832171d8837", +"orders_model_18": "8a322bf0beb93c0034bd28d5", +"orders_model_19": "a4c400c5fa2da4107098339e", +"orders_model_2": "2f584b5185d90ee4c66c8339", +"orders_model_20": "c2da59cc5e833d3421094ea9", +"orders_model_21": "67dc0f1b5ce04c8989ad1aca", +"orders_model_22": "866b4de40862e3cc32f54936", +"orders_model_23": "1c16922430c6790814d0a7df", +"orders_model_3": "f922a0153bfa71727dd6241a", +"orders_model_4": "4c809f6cf2e946ba98b1ec73", +"orders_model_5": "2f2cbf190f07bea2687a7a1e", +"orders_model_6": "b8c7c62baf6528acb751f82c", +"orders_model_7": "0dbccc6cd571bd9ebefb3c2b", +"orders_model_8": "70f77b7d63c1bbe6e602e9bb", +"orders_model_9": "9677ddb44ed9870eeb1fdac1", +"payment_totals": "10740c01d3d11a1de6799033", +"payments_by_customer": "c29bf4a09e3c8e9cff564a2f", +"pivot_0": "db45532b4aa0746bb6155579", +"pivot_1": "826e0ad9aec9b04097d58b37", +"pivot_2": "78dd4b3d90301ccd1e781295", +"pivot_3": "0b5af099963f99173031a52f", +"status_amounts": "0fbfc8d810e430c5814769d6", +"status_passthrough": "26ba5a13355d37dfa8e67820" +} +], +[ +"catalog", +"b83e75232474640290815c9d" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"shapes", +"78e5cd70ce361d823798634b" +], +[ +"models", +{ +"orders_model_0": "dc7f3dec778fd7cc3b47de47", +"orders_model_1": "98e73c916923e6ad3dbb4fe8", +"orders_model_10": "bba235f3ba5a071d31c89cfc", +"orders_model_11": "b92be214f33c9cf71eea3bc2", +"orders_model_12": "7dde13e57109cfb992bc623d", +"orders_model_13": "528bfc7a27293f659b6eec35", +"orders_model_14": "2ab277361bc756f8553cd4fc", +"orders_model_15": "37833d5d1b748c8811d3704a", +"orders_model_16": "bf62990d9480cf71956fd3c9", +"orders_model_17": "cb0cef5752047e0f1201dfb4", +"orders_model_18": "288bd78cd1025c86da017d6d", +"orders_model_19": "bc46ad8533a003d33c266a57", +"orders_model_2": "c4c391b60a4436e3a6a9105e", +"orders_model_20": "5660541da0116a33de85cf37", +"orders_model_21": "bbb7494cbb82085e1c034f21", +"orders_model_22": "9cc8cf8a102827df55622a21", +"orders_model_23": "ccf2498a5b3526260f88df6f", +"orders_model_3": "2acc6b35910a7b7c1e29d661", +"orders_model_4": "d545cb7b8ca26b55d32439c0", +"orders_model_5": "ad3b7e6c56a628aff0799f39", +"orders_model_6": "529410c5a69b04b7172c6dda", +"orders_model_7": "a3f7c2aae3ece4d7de21b9ef", +"orders_model_8": "9a483c2d5942e8857be41233", +"orders_model_9": "0b71c12f30a7617191bc2e17", +"payment_totals": "8cf82ad30e9cce84bc8a3529", +"payments_by_customer": "9e1265b9f4134636cb508259", +"pivot_0": "8ef48104ced62eb9ff31c2b8", +"pivot_1": "af151ba34f16c141fdee1ac3", +"pivot_2": "5cf2515c32c9c98b0a9d8315", +"pivot_3": "3767f4902ed5f3ab1acc83a1", +"status_amounts": "0fbfc8d810e430c5814769d6", +"status_passthrough": "57dbca31518ecf81d68ec4fe" +} +], +[ +"catalog", +"b2b2221f2da5d47b86b56575" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"0d91dfe8eefbbb36998db250" +], +[ +"proof", +"b9689124495085d917d65ebf" +], +[ +"proof", +"4994bb2a572acbed6354a2bb" +], +[ +"proof", +"ff4d4f462aae3b9e95d9a5ab" +], +[ +"proof", +"28c524727756a048843237ef" +], +[ +"proof", +"99b1ccea692774bb61737217" +], +[ +"shapes", +"b40871514fad0707c8cdbee7" +], +[ +"models", +{ +"orders_model_0": "b21bb72c9b7652fb99f52bf8", +"orders_model_1": "98e73c916923e6ad3dbb4fe8", +"orders_model_10": "bba235f3ba5a071d31c89cfc", +"orders_model_11": "b92be214f33c9cf71eea3bc2", +"orders_model_12": "7dde13e57109cfb992bc623d", +"orders_model_13": "528bfc7a27293f659b6eec35", +"orders_model_14": "611ea76d354e7180f2fe0906", +"orders_model_15": "37833d5d1b748c8811d3704a", +"orders_model_16": "24d75028ccc9de7633328c96", +"orders_model_17": "cb0cef5752047e0f1201dfb4", +"orders_model_18": "288bd78cd1025c86da017d6d", +"orders_model_19": "bc46ad8533a003d33c266a57", +"orders_model_2": "2c4a0d5f37d1033435dc44b8", +"orders_model_20": "5660541da0116a33de85cf37", +"orders_model_21": "bbb7494cbb82085e1c034f21", +"orders_model_22": "9cc8cf8a102827df55622a21", +"orders_model_23": "ccf2498a5b3526260f88df6f", +"orders_model_3": "2acc6b35910a7b7c1e29d661", +"orders_model_4": "d545cb7b8ca26b55d32439c0", +"orders_model_5": "ad3b7e6c56a628aff0799f39", +"orders_model_6": "529410c5a69b04b7172c6dda", +"orders_model_7": "a3f7c2aae3ece4d7de21b9ef", +"orders_model_8": "692f18d932cd76c441a79e81", +"orders_model_9": "0b71c12f30a7617191bc2e17", +"payment_totals": "10740c01d3d11a1de6799033", +"payments_by_customer": "e406a89772022ea3c32aefef", +"pivot_0": "8ef48104ced62eb9ff31c2b8", +"pivot_1": "e6d82b48a7a5593bd747ea69", +"pivot_2": "5cf2515c32c9c98b0a9d8315", +"pivot_3": "3767f4902ed5f3ab1acc83a1", +"status_amounts": "0fbfc8d810e430c5814769d6", +"status_passthrough": "57dbca31518ecf81d68ec4fe" +} +], +[ +"catalog", +"3a861a8c7cc6422ec893ea77" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"200eb30f2a045b54792500f6" +], +[ +"proof", +"200eb30f2a045b54792500f6" +], +[ +"proof", +"200eb30f2a045b54792500f6" +], +[ +"proof", +"200eb30f2a045b54792500f6" +], +[ +"proof", +"200eb30f2a045b54792500f6" +], +[ +"proof", +"200eb30f2a045b54792500f6" +], +[ +"shapes", +"78e5cd70ce361d823798634b" +], +[ +"models", +{ +"orders_model_0": "b09efd1e7181db7773253200", +"orders_model_1": "f8df97502ce8987ade2b8ae6", +"orders_model_10": "d9e87a16e347f6f0316452d6", +"orders_model_11": "b92be214f33c9cf71eea3bc2", +"orders_model_12": "1c5f7e1a73535a5617fb070a", +"orders_model_13": "528bfc7a27293f659b6eec35", +"orders_model_14": "611ea76d354e7180f2fe0906", +"orders_model_15": "37833d5d1b748c8811d3704a", +"orders_model_16": "0eca13897e0abb4131837a39", +"orders_model_17": "cb0cef5752047e0f1201dfb4", +"orders_model_18": "74eb746be2a4278dae684968", +"orders_model_19": "bc46ad8533a003d33c266a57", +"orders_model_2": "2c4a0d5f37d1033435dc44b8", +"orders_model_20": "5660541da0116a33de85cf37", +"orders_model_21": "bbb7494cbb82085e1c034f21", +"orders_model_22": "83e085c3265373904422aad9", +"orders_model_23": "ccf2498a5b3526260f88df6f", +"orders_model_3": "2acc6b35910a7b7c1e29d661", +"orders_model_4": "a249acc516a880c9fbe25e88", +"orders_model_5": "ad3b7e6c56a628aff0799f39", +"orders_model_6": "c88625738d77bd28714c4086", +"orders_model_7": "a3f7c2aae3ece4d7de21b9ef", +"orders_model_8": "ec0818249ce5c1a3abdbba12", +"orders_model_9": "0b71c12f30a7617191bc2e17", +"payment_totals": "80bd8eb5eab6ed918ec31949", +"payments_by_customer": "9e1265b9f4134636cb508259", +"pivot_0": "8ef48104ced62eb9ff31c2b8", +"pivot_1": "b2268fc29a60313e3b8c34ed", +"pivot_2": "5cf2515c32c9c98b0a9d8315", +"pivot_3": "3767f4902ed5f3ab1acc83a1", +"status_amounts": "0fbfc8d810e430c5814769d6", +"status_passthrough": "bbd8b7298ce68a222ba84345" +} +], +[ +"catalog", +"01ad0f760ce6f305ea550857" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"c67f69d1828d209a58642e36" +], +[ +"proof", +"b9689124495085d917d65ebf" +], +[ +"proof", +"c67f69d1828d209a58642e36" +], +[ +"proof", +"c67f69d1828d209a58642e36" +], +[ +"proof", +"c67f69d1828d209a58642e36" +], +[ +"proof", +"99b1ccea692774bb61737217" +], +[ +"shapes", +"c0d3bfda902cb95cd1564269" +], +[ +"models", +{ +"orders_model_0": "36669f325385a145cfe71921", +"orders_model_1": "45de3ae2081edb1155411120", +"orders_model_10": "bba235f3ba5a071d31c89cfc", +"orders_model_11": "29c9da29acf1adc409e364df", +"orders_model_12": "dc4da2070db56afde4157773", +"orders_model_13": "87a319b5caf7cc32bc6aa50e", +"orders_model_14": "611ea76d354e7180f2fe0906", +"orders_model_15": "37833d5d1b748c8811d3704a", +"orders_model_16": "8ef4aea858f63561f24ec68b", +"orders_model_17": "cb0cef5752047e0f1201dfb4", +"orders_model_18": "8cf38d3ff37cd8143561920a", +"orders_model_19": "dcb9d89d4b588b53682fb0b4", +"orders_model_2": "2c4a0d5f37d1033435dc44b8", +"orders_model_20": "5660541da0116a33de85cf37", +"orders_model_21": "bbb7494cbb82085e1c034f21", +"orders_model_22": "9cc8cf8a102827df55622a21", +"orders_model_23": "857c9a58882bddd68cec3bd5", +"orders_model_3": "2acc6b35910a7b7c1e29d661", +"orders_model_4": "a249acc516a880c9fbe25e88", +"orders_model_5": "ad3b7e6c56a628aff0799f39", +"orders_model_6": "0541825c1a3bbc51c23f3a53", +"orders_model_7": "526a9e7adadbf085a39764b5", +"orders_model_8": "3bf1aff8cb84ab7999a0b5fd", +"orders_model_9": "0b71c12f30a7617191bc2e17", +"payment_totals": "10740c01d3d11a1de6799033", +"payments_by_customer": "c29bf4a09e3c8e9cff564a2f", +"pivot_0": "8ef48104ced62eb9ff31c2b8", +"pivot_1": "0b5af099963f99173031a52f", +"pivot_2": "5cf2515c32c9c98b0a9d8315", +"pivot_3": "3767f4902ed5f3ab1acc83a1", +"status_amounts": "0fbfc8d810e430c5814769d6", +"status_passthrough": "26ba5a13355d37dfa8e67820" +} +], +[ +"catalog", +"032717ee1f3f581899d54bf7" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"shapes", +"78e5cd70ce361d823798634b" +], +[ +"models", +{ +"orders_model_0": "7dde13e57109cfb992bc623d", +"orders_model_1": "d7498e8ac1b0afeb189ff727", +"orders_model_10": "264e63bb81a8673659bbb9db", +"orders_model_11": "b92be214f33c9cf71eea3bc2", +"orders_model_12": "dc7f3dec778fd7cc3b47de47", +"orders_model_13": "35b1097a860faac43e81b044", +"orders_model_14": "28b94fa5aaa6225fd8809740", +"orders_model_15": "a2c41a95e7f2097d2e9b9bd1", +"orders_model_16": "f386cc5235b54c550f4924f8", +"orders_model_17": "60e141a5769c44084f76723b", +"orders_model_18": "6b0c7fdf2bf74107bd96a6ff", +"orders_model_19": "ec3c3ec5fbf35ddc59fd77ca", +"orders_model_2": "3c07dff3140b081ee33fd13e", +"orders_model_20": "85ea595b45b20d75c0d8df80", +"orders_model_21": "fbd144b873208a2bd80a35a4", +"orders_model_22": "4e068f2ba3ce583e4d5b6006", +"orders_model_23": "8942d18a241e8dcd1831addc", +"orders_model_3": "527338f30a7ba57175c3a525", +"orders_model_4": "526ce0a1d0a274582f9d35f1", +"orders_model_5": "60e141a5769c44084f76723b", +"orders_model_6": "36c156c5a6601badf8124464", +"orders_model_7": "ef0eb5ded0428f49ac6cb411", +"orders_model_8": "1d2ab23b591c4ca7f5e6359b", +"orders_model_9": "338aef528aa5f199e2ffa973", +"payment_totals": "8cf82ad30e9cce84bc8a3529", +"payments_by_customer": "9e1265b9f4134636cb508259", +"pivot_0": "bd6145283beb468ce86b460b", +"pivot_1": "8eb04463a7e8015fcc9b8a63", +"pivot_2": "18ecbe5e93fe3ced5cbfd24a", +"pivot_3": "af151ba34f16c141fdee1ac3", +"status_amounts": "0fbfc8d810e430c5814769d6", +"status_passthrough": "57dbca31518ecf81d68ec4fe" +} +], +[ +"catalog", +"4f98b4e1b4999a33ba1ff099" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"1241165b261dcfe84ece9067" +], +[ +"proof", +"c3cb3226e55a418829fd059c" +], +[ +"proof", +"20e6b6374d63663154468bed" +], +[ +"proof", +"b9689124495085d917d65ebf" +], +[ +"proof", +"28c524727756a048843237ef" +], +[ +"proof", +"99b1ccea692774bb61737217" +], +[ +"shapes", +"b40871514fad0707c8cdbee7" +], +[ +"models", +{ +"orders_model_0": "7dde13e57109cfb992bc623d", +"orders_model_1": "d7498e8ac1b0afeb189ff727", +"orders_model_10": "264e63bb81a8673659bbb9db", +"orders_model_11": "b92be214f33c9cf71eea3bc2", +"orders_model_12": "b21bb72c9b7652fb99f52bf8", +"orders_model_13": "35b1097a860faac43e81b044", +"orders_model_14": "28b94fa5aaa6225fd8809740", +"orders_model_15": "a2c41a95e7f2097d2e9b9bd1", +"orders_model_16": "f386cc5235b54c550f4924f8", +"orders_model_17": "60e141a5769c44084f76723b", +"orders_model_18": "6b0c7fdf2bf74107bd96a6ff", +"orders_model_19": "ec3c3ec5fbf35ddc59fd77ca", +"orders_model_2": "3c07dff3140b081ee33fd13e", +"orders_model_20": "85ea595b45b20d75c0d8df80", +"orders_model_21": "fbd144b873208a2bd80a35a4", +"orders_model_22": "4e068f2ba3ce583e4d5b6006", +"orders_model_23": "8942d18a241e8dcd1831addc", +"orders_model_3": "527338f30a7ba57175c3a525", +"orders_model_4": "75f6764c319047022968f0b3", +"orders_model_5": "60e141a5769c44084f76723b", +"orders_model_6": "777e18bfdcc2423b67211d39", +"orders_model_7": "80a1f1b7b38c1afa802d7625", +"orders_model_8": "1d2ab23b591c4ca7f5e6359b", +"orders_model_9": "338aef528aa5f199e2ffa973", +"payment_totals": "10740c01d3d11a1de6799033", +"payments_by_customer": "e406a89772022ea3c32aefef", +"pivot_0": "bd6145283beb468ce86b460b", +"pivot_1": "8eb04463a7e8015fcc9b8a63", +"pivot_2": "18ecbe5e93fe3ced5cbfd24a", +"pivot_3": "e6d82b48a7a5593bd747ea69", +"status_amounts": "0fbfc8d810e430c5814769d6", +"status_passthrough": "57dbca31518ecf81d68ec4fe" +} +], +[ +"catalog", +"055d801ba49e61e8a1e414b2" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"200eb30f2a045b54792500f6" +], +[ +"proof", +"200eb30f2a045b54792500f6" +], +[ +"proof", +"200eb30f2a045b54792500f6" +], +[ +"proof", +"200eb30f2a045b54792500f6" +], +[ +"proof", +"200eb30f2a045b54792500f6" +], +[ +"proof", +"200eb30f2a045b54792500f6" +], +[ +"shapes", +"78e5cd70ce361d823798634b" +], +[ +"models", +{ +"orders_model_0": "1c5f7e1a73535a5617fb070a", +"orders_model_1": "673e75c341c3f2437091de09", +"orders_model_10": "0df969272aa19a78a705bc92", +"orders_model_11": "b92be214f33c9cf71eea3bc2", +"orders_model_12": "b09efd1e7181db7773253200", +"orders_model_13": "bc666dca3ca9016f640dfe68", +"orders_model_14": "7c3ab71786810446d45e97a3", +"orders_model_15": "a2c41a95e7f2097d2e9b9bd1", +"orders_model_16": "cf4db989e60b4ff2ee7b8b90", +"orders_model_17": "60e141a5769c44084f76723b", +"orders_model_18": "b1a0e72c622ac940a7b5fb00", +"orders_model_19": "ec3c3ec5fbf35ddc59fd77ca", +"orders_model_2": "3c07dff3140b081ee33fd13e", +"orders_model_20": "85ea595b45b20d75c0d8df80", +"orders_model_21": "59228560ec9692b57930d8b5", +"orders_model_22": "b8238ed1e26320d8f8912882", +"orders_model_23": "8942d18a241e8dcd1831addc", +"orders_model_3": "527338f30a7ba57175c3a525", +"orders_model_4": "1cefa36f28721fe677e6a684", +"orders_model_5": "60e141a5769c44084f76723b", +"orders_model_6": "3197497d139b9241f4b6e04c", +"orders_model_7": "44dc5de3912695d88a818a03", +"orders_model_8": "1d2ab23b591c4ca7f5e6359b", +"orders_model_9": "338aef528aa5f199e2ffa973", +"payment_totals": "80bd8eb5eab6ed918ec31949", +"payments_by_customer": "9e1265b9f4134636cb508259", +"pivot_0": "bd6145283beb468ce86b460b", +"pivot_1": "8eb04463a7e8015fcc9b8a63", +"pivot_2": "18ecbe5e93fe3ced5cbfd24a", +"pivot_3": "b2268fc29a60313e3b8c34ed", +"status_amounts": "0fbfc8d810e430c5814769d6", +"status_passthrough": "bbd8b7298ce68a222ba84345" +} +], +[ +"catalog", +"74156f1f4b47943ba3b769dd" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"c67f69d1828d209a58642e36" +], +[ +"proof", +"c67f69d1828d209a58642e36" +], +[ +"proof", +"c67f69d1828d209a58642e36" +], +[ +"proof", +"b9689124495085d917d65ebf" +], +[ +"proof", +"c67f69d1828d209a58642e36" +], +[ +"proof", +"99b1ccea692774bb61737217" +], +[ +"shapes", +"c0d3bfda902cb95cd1564269" +], +[ +"models", +{ +"orders_model_0": "dc4da2070db56afde4157773", +"orders_model_1": "b6345243b4bb0009ec2dfb5d", +"orders_model_10": "264e63bb81a8673659bbb9db", +"orders_model_11": "29c9da29acf1adc409e364df", +"orders_model_12": "36669f325385a145cfe71921", +"orders_model_13": "87a1dbf609e37b67c90e35b2", +"orders_model_14": "544d358c786985653996181d", +"orders_model_15": "a2c41a95e7f2097d2e9b9bd1", +"orders_model_16": "cf4db989e60b4ff2ee7b8b90", +"orders_model_17": "60e141a5769c44084f76723b", +"orders_model_18": "60e19e6908bb5c06d38eeb01", +"orders_model_19": "ab249088d32d341a013be687", +"orders_model_2": "3c07dff3140b081ee33fd13e", +"orders_model_20": "85ea595b45b20d75c0d8df80", +"orders_model_21": "176a688a47e60b55e1ce0673", +"orders_model_22": "c6255585e2f5156964d8f8f8", +"orders_model_23": "e0ec1521e19c47996421ec94", +"orders_model_3": "527338f30a7ba57175c3a525", +"orders_model_4": "4c809f6cf2e946ba98b1ec73", +"orders_model_5": "60e141a5769c44084f76723b", +"orders_model_6": "c2b91215ea727d9313a22740", +"orders_model_7": "afb5b3102eaac7fa202355c0", +"orders_model_8": "1d2ab23b591c4ca7f5e6359b", +"orders_model_9": "283c165f2da9102ffec377c4", +"payment_totals": "10740c01d3d11a1de6799033", +"payments_by_customer": "c29bf4a09e3c8e9cff564a2f", +"pivot_0": "bd6145283beb468ce86b460b", +"pivot_1": "8eb04463a7e8015fcc9b8a63", +"pivot_2": "18ecbe5e93fe3ced5cbfd24a", +"pivot_3": "0b5af099963f99173031a52f", +"status_amounts": "0fbfc8d810e430c5814769d6", +"status_passthrough": "26ba5a13355d37dfa8e67820" +} +], +[ +"catalog", +"3d1560ed382e916606e5f85f" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"shapes", +"78e5cd70ce361d823798634b" +], +[ +"models", +{ +"orders_model_0": "c380ae05f3bd0627628ab6fc", +"orders_model_1": "abadf69a0572399b6536a2c1", +"orders_model_10": "c46ffece29c5df800b8f74df", +"orders_model_11": "8003e1680dc046032ceea404", +"orders_model_12": "edf57c58d750226a747455ba", +"orders_model_13": "278d4fd453aea2eca14894ea", +"orders_model_14": "e51070f44666248f5b7764b3", +"orders_model_15": "88ec6fdf0edc3ff0a0acb78c", +"orders_model_16": "eeaefdbd50fdc13681d8653a", +"orders_model_17": "3515712bb3c936c534706554", +"orders_model_18": "5ccadf27b4bf1a37e0f30682", +"orders_model_19": "5ab5711e085cc014f3e44950", +"orders_model_2": "835e887650bbf9b124ae26b1", +"orders_model_20": "12b73be6a6b5985f71de1ca5", +"orders_model_21": "0b71c12f30a7617191bc2e17", +"orders_model_22": "91d92b539582dec7737d1704", +"orders_model_23": "c8ff9a2130c4a7a57073fb6d", +"orders_model_3": "a5927681bfbf9d44f4723990", +"orders_model_4": "e29709e8e7acb44cc782304f", +"orders_model_5": "afd6d68f0a0a6689404e0260", +"orders_model_6": "099cb926af524f10d27cc108", +"orders_model_7": "a36493d57a16c1f79a91afd6", +"orders_model_8": "6be36f8074a475ab3f5bce6c", +"orders_model_9": "d34e456ade2ced8792534866", +"payment_totals": "8cf82ad30e9cce84bc8a3529", +"payments_by_customer": "9e1265b9f4134636cb508259", +"pivot_0": "8ef48104ced62eb9ff31c2b8", +"pivot_1": "af151ba34f16c141fdee1ac3", +"pivot_2": "5adb7a56c3dfd3d1c3cf58c1", +"pivot_3": "00a890bbfc402b53ea021e5a", +"status_amounts": "0fbfc8d810e430c5814769d6", +"status_passthrough": "57dbca31518ecf81d68ec4fe" +} +], +[ +"catalog", +"c7b70a4fc469694d9d64eff8" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"0d91dfe8eefbbb36998db250" +], +[ +"proof", +"b9689124495085d917d65ebf" +], +[ +"proof", +"1241165b261dcfe84ece9067" +], +[ +"proof", +"20e6b6374d63663154468bed" +], +[ +"proof", +"28c524727756a048843237ef" +], +[ +"proof", +"99b1ccea692774bb61737217" +], +[ +"shapes", +"b40871514fad0707c8cdbee7" +], +[ +"models", +{ +"orders_model_0": "c380ae05f3bd0627628ab6fc", +"orders_model_1": "a23763739c27a47ae12ebed2", +"orders_model_10": "c46ffece29c5df800b8f74df", +"orders_model_11": "8003e1680dc046032ceea404", +"orders_model_12": "edf57c58d750226a747455ba", +"orders_model_13": "56d09679844a976541cce33c", +"orders_model_14": "e51070f44666248f5b7764b3", +"orders_model_15": "88ec6fdf0edc3ff0a0acb78c", +"orders_model_16": "eeaefdbd50fdc13681d8653a", +"orders_model_17": "3515712bb3c936c534706554", +"orders_model_18": "f73c7edc9f35cb7956a40b52", +"orders_model_19": "5ab5711e085cc014f3e44950", +"orders_model_2": "835e887650bbf9b124ae26b1", +"orders_model_20": "12b73be6a6b5985f71de1ca5", +"orders_model_21": "0b71c12f30a7617191bc2e17", +"orders_model_22": "2853fca6c5782a3d8f7f3229", +"orders_model_23": "c8ff9a2130c4a7a57073fb6d", +"orders_model_3": "a5927681bfbf9d44f4723990", +"orders_model_4": "c8c4091a11671ad7035944d6", +"orders_model_5": "afd6d68f0a0a6689404e0260", +"orders_model_6": "099cb926af524f10d27cc108", +"orders_model_7": "a36493d57a16c1f79a91afd6", +"orders_model_8": "8a583d5a0fe333e4583746b2", +"orders_model_9": "d34e456ade2ced8792534866", +"payment_totals": "10740c01d3d11a1de6799033", +"payments_by_customer": "e406a89772022ea3c32aefef", +"pivot_0": "8ef48104ced62eb9ff31c2b8", +"pivot_1": "e6d82b48a7a5593bd747ea69", +"pivot_2": "5adb7a56c3dfd3d1c3cf58c1", +"pivot_3": "00a890bbfc402b53ea021e5a", +"status_amounts": "0fbfc8d810e430c5814769d6", +"status_passthrough": "57dbca31518ecf81d68ec4fe" +} +], +[ +"catalog", +"8cc95852afc3fab17c43340c" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"200eb30f2a045b54792500f6" +], +[ +"proof", +"200eb30f2a045b54792500f6" +], +[ +"proof", +"200eb30f2a045b54792500f6" +], +[ +"proof", +"200eb30f2a045b54792500f6" +], +[ +"proof", +"200eb30f2a045b54792500f6" +], +[ +"proof", +"200eb30f2a045b54792500f6" +], +[ +"shapes", +"78e5cd70ce361d823798634b" +], +[ +"models", +{ +"orders_model_0": "94f95487333b2561382c2981", +"orders_model_1": "ab25f3ba101f081f8a3f936c", +"orders_model_10": "3aec7a059badfa0e968d5216", +"orders_model_11": "8003e1680dc046032ceea404", +"orders_model_12": "cb6d3e8487b533349a2bad04", +"orders_model_13": "d55e6b7bb6533cea41bcfeda", +"orders_model_14": "e51070f44666248f5b7764b3", +"orders_model_15": "88ec6fdf0edc3ff0a0acb78c", +"orders_model_16": "97e322d50d70c30c61fb7a15", +"orders_model_17": "3515712bb3c936c534706554", +"orders_model_18": "32b8af78b243949e0198fda6", +"orders_model_19": "5ab5711e085cc014f3e44950", +"orders_model_2": "345f166deff852e9116d8801", +"orders_model_20": "12b73be6a6b5985f71de1ca5", +"orders_model_21": "0b71c12f30a7617191bc2e17", +"orders_model_22": "368c97dc5eea624b492ce042", +"orders_model_23": "c8ff9a2130c4a7a57073fb6d", +"orders_model_3": "a5927681bfbf9d44f4723990", +"orders_model_4": "7565624f8000d1c0566d8ed3", +"orders_model_5": "ee556ea5f790f1d885cee84a", +"orders_model_6": "5d2a8162e9742273846f69e3", +"orders_model_7": "a36493d57a16c1f79a91afd6", +"orders_model_8": "c7d3f9e5025dad577c958a44", +"orders_model_9": "d34e456ade2ced8792534866", +"payment_totals": "80bd8eb5eab6ed918ec31949", +"payments_by_customer": "9e1265b9f4134636cb508259", +"pivot_0": "8ef48104ced62eb9ff31c2b8", +"pivot_1": "b2268fc29a60313e3b8c34ed", +"pivot_2": "5adb7a56c3dfd3d1c3cf58c1", +"pivot_3": "00a890bbfc402b53ea021e5a", +"status_amounts": "0fbfc8d810e430c5814769d6", +"status_passthrough": "bbd8b7298ce68a222ba84345" +} +], +[ +"catalog", +"08a4d5d6c6bf5e75b2e23d81" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"c67f69d1828d209a58642e36" +], +[ +"proof", +"b9689124495085d917d65ebf" +], +[ +"proof", +"c67f69d1828d209a58642e36" +], +[ +"proof", +"c67f69d1828d209a58642e36" +], +[ +"proof", +"c67f69d1828d209a58642e36" +], +[ +"proof", +"99b1ccea692774bb61737217" +], +[ +"shapes", +"c0d3bfda902cb95cd1564269" +], +[ +"models", +{ +"orders_model_0": "c380ae05f3bd0627628ab6fc", +"orders_model_1": "c7630eba442c12475a304749", +"orders_model_10": "fa26ab8510354dd670525ac2", +"orders_model_11": "eb7d097be111399bcd2f940f", +"orders_model_12": "edf57c58d750226a747455ba", +"orders_model_13": "ab1f9c5b6ef07ffa40eeadaf", +"orders_model_14": "273c339ab90e9a64a7c8f8a5", +"orders_model_15": "88ec6fdf0edc3ff0a0acb78c", +"orders_model_16": "e018db5f6e3eaf8888bd8eff", +"orders_model_17": "fe03c6a89b870943b6dd5922", +"orders_model_18": "fd5138ac4af02cd168a423e6", +"orders_model_19": "e24f113150b49c7e955cf81b", +"orders_model_2": "daca571af4a4d1cb1afbce74", +"orders_model_20": "12b73be6a6b5985f71de1ca5", +"orders_model_21": "0b71c12f30a7617191bc2e17", +"orders_model_22": "24bdd574c66fd2f692429cfb", +"orders_model_23": "e94cdbeab01617cd05a55f82", +"orders_model_3": "a5927681bfbf9d44f4723990", +"orders_model_4": "a908ebc07c10d1423a970a49", +"orders_model_5": "7af136b7e522ccf14f427e1e", +"orders_model_6": "8a322bf0beb93c0034bd28d5", +"orders_model_7": "4983a5e9302c8b9e28e75202", +"orders_model_8": "8a583d5a0fe333e4583746b2", +"orders_model_9": "9677ddb44ed9870eeb1fdac1", +"payment_totals": "10740c01d3d11a1de6799033", +"payments_by_customer": "c29bf4a09e3c8e9cff564a2f", +"pivot_0": "8ef48104ced62eb9ff31c2b8", +"pivot_1": "0b5af099963f99173031a52f", +"pivot_2": "5adb7a56c3dfd3d1c3cf58c1", +"pivot_3": "00a890bbfc402b53ea021e5a", +"status_amounts": "0fbfc8d810e430c5814769d6", +"status_passthrough": "26ba5a13355d37dfa8e67820" +} +], +[ +"catalog", +"f19e292dff42d4c08b5da8ad" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"shapes", +"78e5cd70ce361d823798634b" +], +[ +"models", +{ +"orders_model_0": "c380ae05f3bd0627628ab6fc", +"orders_model_1": "c909142a40bfa94a0849e672", +"orders_model_10": "99f0746f249fd25788f1348a", +"orders_model_11": "5f4d57a90f61f48a39c3f45c", +"orders_model_12": "159cce49ef0548e95a5b46fe", +"orders_model_13": "ba7bafc812a816c0c0770d82", +"orders_model_14": "69a4a23c4590c4354bff5dbf", +"orders_model_15": "e83a2c02763b0f51b49dbfe1", +"orders_model_16": "e29709e8e7acb44cc782304f", +"orders_model_17": "40ca546bd222f4bd18e62461", +"orders_model_18": "f913dcd698fd61a9df4580a9", +"orders_model_19": "16fc9c0348ca5eadfd147e95", +"orders_model_2": "be51e7ded79e692b0f86ad8e", +"orders_model_20": "4a708ce5c2d7f50400bef81e", +"orders_model_21": "32e2f46b53e4361d34fb2f95", +"orders_model_22": "ca95b1a1313ab6e0c86f22d0", +"orders_model_23": "6423a33f3457191fa1b24540", +"orders_model_3": "fd09d2408d6ef7eceb04f8e3", +"orders_model_4": "40daca9947aaa0922736d9ca", +"orders_model_5": "efc04632c3bd90f5ca705b61", +"orders_model_6": "6b0c7fdf2bf74107bd96a6ff", +"orders_model_7": "f1d838e10071f9b219bf07c6", +"orders_model_8": "653dbee5db7422883147ecf8", +"orders_model_9": "e2d21c84b2b62dea98a1d185", +"payment_totals": "8cf82ad30e9cce84bc8a3529", +"payments_by_customer": "9e1265b9f4134636cb508259", +"pivot_0": "af151ba34f16c141fdee1ac3", +"pivot_1": "bd6145283beb468ce86b460b", +"pivot_2": "db45532b4aa0746bb6155579", +"pivot_3": "5cf2515c32c9c98b0a9d8315", +"status_amounts": "0fbfc8d810e430c5814769d6", +"status_passthrough": "57dbca31518ecf81d68ec4fe" +} +], +[ +"catalog", +"f877c81e569d46b2f31adb8a" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"b9689124495085d917d65ebf" +], +[ +"proof", +"1241165b261dcfe84ece9067" +], +[ +"proof", +"0d91dfe8eefbbb36998db250" +], +[ +"proof", +"4994bb2a572acbed6354a2bb" +], +[ +"proof", +"28c524727756a048843237ef" +], +[ +"proof", +"99b1ccea692774bb61737217" +], +[ +"shapes", +"b40871514fad0707c8cdbee7" +], +[ +"models", +{ +"orders_model_0": "c380ae05f3bd0627628ab6fc", +"orders_model_1": "c909142a40bfa94a0849e672", +"orders_model_10": "99f0746f249fd25788f1348a", +"orders_model_11": "5f4d57a90f61f48a39c3f45c", +"orders_model_12": "eb36534deed90e9e2fb062de", +"orders_model_13": "b929a7472b014a9b5b757127", +"orders_model_14": "69a4a23c4590c4354bff5dbf", +"orders_model_15": "e83a2c02763b0f51b49dbfe1", +"orders_model_16": "c8c4091a11671ad7035944d6", +"orders_model_17": "40ca546bd222f4bd18e62461", +"orders_model_18": "f913dcd698fd61a9df4580a9", +"orders_model_19": "16fc9c0348ca5eadfd147e95", +"orders_model_2": "be51e7ded79e692b0f86ad8e", +"orders_model_20": "4a708ce5c2d7f50400bef81e", +"orders_model_21": "32e2f46b53e4361d34fb2f95", +"orders_model_22": "ca95b1a1313ab6e0c86f22d0", +"orders_model_23": "6423a33f3457191fa1b24540", +"orders_model_3": "fd09d2408d6ef7eceb04f8e3", +"orders_model_4": "40daca9947aaa0922736d9ca", +"orders_model_5": "efc04632c3bd90f5ca705b61", +"orders_model_6": "6b0c7fdf2bf74107bd96a6ff", +"orders_model_7": "f1d838e10071f9b219bf07c6", +"orders_model_8": "85993844a344d5d4408276d0", +"orders_model_9": "e2d21c84b2b62dea98a1d185", +"payment_totals": "10740c01d3d11a1de6799033", +"payments_by_customer": "e406a89772022ea3c32aefef", +"pivot_0": "e6d82b48a7a5593bd747ea69", +"pivot_1": "bd6145283beb468ce86b460b", +"pivot_2": "db45532b4aa0746bb6155579", +"pivot_3": "5cf2515c32c9c98b0a9d8315", +"status_amounts": "0fbfc8d810e430c5814769d6", +"status_passthrough": "57dbca31518ecf81d68ec4fe" +} +], +[ +"catalog", +"f877c81e569d46b2f31adb8a" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"200eb30f2a045b54792500f6" +], +[ +"proof", +"200eb30f2a045b54792500f6" +], +[ +"proof", +"200eb30f2a045b54792500f6" +], +[ +"proof", +"200eb30f2a045b54792500f6" +], +[ +"proof", +"200eb30f2a045b54792500f6" +], +[ +"proof", +"200eb30f2a045b54792500f6" +], +[ +"shapes", +"78e5cd70ce361d823798634b" +], +[ +"models", +{ +"orders_model_0": "94f95487333b2561382c2981", +"orders_model_1": "d69e281f2ec58a1c2cfc8e75", +"orders_model_10": "07a1b43e2e1aec3a941c7463", +"orders_model_11": "5f4d57a90f61f48a39c3f45c", +"orders_model_12": "e3d5141e99608c2ca5d0df9b", +"orders_model_13": "8bfac0eb02357c4ef7316ba0", +"orders_model_14": "69a4a23c4590c4354bff5dbf", +"orders_model_15": "e83a2c02763b0f51b49dbfe1", +"orders_model_16": "7565624f8000d1c0566d8ed3", +"orders_model_17": "185a865c8cf0d67b3027a313", +"orders_model_18": "4ed6b441d50e250d458a67ec", +"orders_model_19": "16fc9c0348ca5eadfd147e95", +"orders_model_2": "be51e7ded79e692b0f86ad8e", +"orders_model_20": "59129bc02b2fd6f6f8bfb348", +"orders_model_21": "88425997d70bb43627dba42c", +"orders_model_22": "14091564e5091161047f133c", +"orders_model_23": "6423a33f3457191fa1b24540", +"orders_model_3": "fd09d2408d6ef7eceb04f8e3", +"orders_model_4": "2cfd6426be9711fc3a185538", +"orders_model_5": "1e772c63e569addeecf15a27", +"orders_model_6": "b1a0e72c622ac940a7b5fb00", +"orders_model_7": "f1d838e10071f9b219bf07c6", +"orders_model_8": "653dbee5db7422883147ecf8", +"orders_model_9": "982d87b5a15b54ee70c70755", +"payment_totals": "80bd8eb5eab6ed918ec31949", +"payments_by_customer": "9e1265b9f4134636cb508259", +"pivot_0": "b2268fc29a60313e3b8c34ed", +"pivot_1": "bd6145283beb468ce86b460b", +"pivot_2": "db45532b4aa0746bb6155579", +"pivot_3": "5cf2515c32c9c98b0a9d8315", +"status_amounts": "0fbfc8d810e430c5814769d6", +"status_passthrough": "bbd8b7298ce68a222ba84345" +} +], +[ +"catalog", +"3eb464018675acfdd12a461f" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"b9689124495085d917d65ebf" +], +[ +"proof", +"c67f69d1828d209a58642e36" +], +[ +"proof", +"c67f69d1828d209a58642e36" +], +[ +"proof", +"c67f69d1828d209a58642e36" +], +[ +"proof", +"c67f69d1828d209a58642e36" +], +[ +"proof", +"99b1ccea692774bb61737217" +], +[ +"shapes", +"c0d3bfda902cb95cd1564269" +], +[ +"models", +{ +"orders_model_0": "c380ae05f3bd0627628ab6fc", +"orders_model_1": "18de106324e6bd649e9a0662", +"orders_model_10": "99f0746f249fd25788f1348a", +"orders_model_11": "68b962a61fcbd39f299bf7b9", +"orders_model_12": "bd31b96a3fa2e1bb80699d6e", +"orders_model_13": "1d827eced23366a37ddba6b8", +"orders_model_14": "69a4a23c4590c4354bff5dbf", +"orders_model_15": "e83a2c02763b0f51b49dbfe1", +"orders_model_16": "a908ebc07c10d1423a970a49", +"orders_model_17": "185a865c8cf0d67b3027a313", +"orders_model_18": "02d5138c4e7513182fc7cd52", +"orders_model_19": "3f36107952adc3d06995d9db", +"orders_model_2": "be51e7ded79e692b0f86ad8e", +"orders_model_20": "59129bc02b2fd6f6f8bfb348", +"orders_model_21": "08e7a885c1d9662b2678c3ea", +"orders_model_22": "1b893dcaf72edc288a3b9710", +"orders_model_23": "f35475b4e5e4ae85ae46e91d", +"orders_model_3": "fd09d2408d6ef7eceb04f8e3", +"orders_model_4": "2cfd6426be9711fc3a185538", +"orders_model_5": "949207159f621de6e270aed5", +"orders_model_6": "60e19e6908bb5c06d38eeb01", +"orders_model_7": "07289e08df177aa672b5da80", +"orders_model_8": "4fe24f5b9f54838716b41386", +"orders_model_9": "05bfc38d1bf1cc771029edec", +"payment_totals": "10740c01d3d11a1de6799033", +"payments_by_customer": "c29bf4a09e3c8e9cff564a2f", +"pivot_0": "0b5af099963f99173031a52f", +"pivot_1": "bd6145283beb468ce86b460b", +"pivot_2": "db45532b4aa0746bb6155579", +"pivot_3": "5cf2515c32c9c98b0a9d8315", +"status_amounts": "0fbfc8d810e430c5814769d6", +"status_passthrough": "26ba5a13355d37dfa8e67820" +} +], +[ +"catalog", +"23b5038345131be7d003ad7b" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +] +] diff --git a/tests/goldens/python_oracle/analysis_shared_equal_regional_queries_missing_column_readers_and_a_unique_summary.json b/tests/goldens/python_oracle/analysis_shared_equal_regional_queries_missing_column_readers_and_a_unique_summary.json new file mode 100644 index 0000000000..6deaca5f2b --- /dev/null +++ b/tests/goldens/python_oracle/analysis_shared_equal_regional_queries_missing_column_readers_and_a_unique_summary.json @@ -0,0 +1,148 @@ +[ +[ +"shapes", +"78e5cd70ce361d823798634b" +], +[ +"models", +{ +"missing_east": "aba5ab28f3a97ef8fce3c485", +"missing_north": "777ae26d6fa90296228d39f8", +"missing_west": "8a38648fbc0412a83d2626ef", +"orders_east": "4784ce99683381a7cb1bbeca", +"orders_north": "4784ce99683381a7cb1bbeca", +"orders_south": "4784ce99683381a7cb1bbeca", +"orders_summary": "1bda84c5cb7bff52c8d05569", +"orders_west": "4784ce99683381a7cb1bbeca", +"totals_east": "77d2a746f8facada159be569", +"totals_north": "a8d32a96d12ea19c455c183d", +"totals_south": "3b15726cb112aac93fc49acf", +"totals_west": "2b5d9cbefea62a4be70e381b" +} +], +[ +"catalog", +"9c499b98266c28cea392795d" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"shapes", +"78e5cd70ce361d823798634b" +], +[ +"models", +{ +"missing_east": "aba5ab28f3a97ef8fce3c485", +"missing_north": "777ae26d6fa90296228d39f8", +"missing_west": "8a38648fbc0412a83d2626ef", +"orders_east": "4784ce99683381a7cb1bbeca", +"orders_north": "4784ce99683381a7cb1bbeca", +"orders_south": "4784ce99683381a7cb1bbeca", +"orders_summary": "1bda84c5cb7bff52c8d05569", +"orders_west": "4784ce99683381a7cb1bbeca", +"totals_east": "77d2a746f8facada159be569", +"totals_north": "a8d32a96d12ea19c455c183d", +"totals_south": "3b15726cb112aac93fc49acf", +"totals_west": "2b5d9cbefea62a4be70e381b" +} +], +[ +"catalog", +"9c499b98266c28cea392795d" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +], +[ +"proof", +"74234e98afe7498fb5daf1f3" +] +] diff --git a/tests/goldens/python_oracle/contracts_generated_enforced_implicit_typed_nullability_and_dynamic_contracts.json b/tests/goldens/python_oracle/contracts_generated_enforced_implicit_typed_nullability_and_dynamic_contracts.json new file mode 100644 index 0000000000..443217bb53 --- /dev/null +++ b/tests/goldens/python_oracle/contracts_generated_enforced_implicit_typed_nullability_and_dynamic_contracts.json @@ -0,0 +1,722 @@ +[ +[ +"contracts", +{ +"None": "946a3061a7e72843e29b93c8", +"bigquery": "946a3061a7e72843e29b93c8", +"databricks": "946a3061a7e72843e29b93c8", +"duckdb": "946a3061a7e72843e29b93c8", +"postgres": "946a3061a7e72843e29b93c8", +"snowflake": "946a3061a7e72843e29b93c8", +"tsql": "946a3061a7e72843e29b93c8" +} +], +[ +"contracts", +{ +"None": "e298b23cdc712b436ba9140b", +"bigquery": "e298b23cdc712b436ba9140b", +"databricks": "e298b23cdc712b436ba9140b", +"duckdb": "e298b23cdc712b436ba9140b", +"postgres": "e298b23cdc712b436ba9140b", +"snowflake": "e298b23cdc712b436ba9140b", +"tsql": "e298b23cdc712b436ba9140b" +} +], +[ +"contracts", +{ +"None": "b3283bf184bb082f364b8537", +"bigquery": "b3283bf184bb082f364b8537", +"databricks": "b3283bf184bb082f364b8537", +"duckdb": "b3283bf184bb082f364b8537", +"postgres": "b3283bf184bb082f364b8537", +"snowflake": "b3283bf184bb082f364b8537", +"tsql": "b3283bf184bb082f364b8537" +} +], +[ +"contracts", +{ +"None": "b1e12cf6dc9584935dabf76a", +"bigquery": "b1e12cf6dc9584935dabf76a", +"databricks": "b1e12cf6dc9584935dabf76a", +"duckdb": "b1e12cf6dc9584935dabf76a", +"postgres": "b1e12cf6dc9584935dabf76a", +"snowflake": "b1e12cf6dc9584935dabf76a", +"tsql": "b1e12cf6dc9584935dabf76a" +} +], +[ +"contracts", +{ +"None": "e44260e0d2411c3cce8781cc", +"bigquery": "e44260e0d2411c3cce8781cc", +"databricks": "e44260e0d2411c3cce8781cc", +"duckdb": "e44260e0d2411c3cce8781cc", +"postgres": "e44260e0d2411c3cce8781cc", +"snowflake": "e44260e0d2411c3cce8781cc", +"tsql": "e44260e0d2411c3cce8781cc" +} +], +[ +"contracts", +{ +"None": "2ea2c17632881c11f524f96c", +"bigquery": "2ea2c17632881c11f524f96c", +"databricks": "2ea2c17632881c11f524f96c", +"duckdb": "2ea2c17632881c11f524f96c", +"postgres": "2ea2c17632881c11f524f96c", +"snowflake": "2ea2c17632881c11f524f96c", +"tsql": "2ea2c17632881c11f524f96c" +} +], +[ +"contracts", +{ +"None": "0b6e350a4f4afde493cb8626", +"bigquery": "0b6e350a4f4afde493cb8626", +"databricks": "0b6e350a4f4afde493cb8626", +"duckdb": "0b6e350a4f4afde493cb8626", +"postgres": "0b6e350a4f4afde493cb8626", +"snowflake": "0b6e350a4f4afde493cb8626", +"tsql": "0b6e350a4f4afde493cb8626" +} +], +[ +"contracts", +{ +"None": "ec97cc8e40b7631612395b21", +"bigquery": "ec97cc8e40b7631612395b21", +"databricks": "ec97cc8e40b7631612395b21", +"duckdb": "ec97cc8e40b7631612395b21", +"postgres": "ec97cc8e40b7631612395b21", +"snowflake": "ec97cc8e40b7631612395b21", +"tsql": "ec97cc8e40b7631612395b21" +} +], +[ +"contracts", +{ +"None": "a428eb672c78b30d5702cafd", +"bigquery": "a428eb672c78b30d5702cafd", +"databricks": "a428eb672c78b30d5702cafd", +"duckdb": "a428eb672c78b30d5702cafd", +"postgres": "a428eb672c78b30d5702cafd", +"snowflake": "a428eb672c78b30d5702cafd", +"tsql": "a428eb672c78b30d5702cafd" +} +], +[ +"contracts", +{ +"None": "839434d5b73abdf9499ad59e", +"bigquery": "839434d5b73abdf9499ad59e", +"databricks": "839434d5b73abdf9499ad59e", +"duckdb": "839434d5b73abdf9499ad59e", +"postgres": "839434d5b73abdf9499ad59e", +"snowflake": "839434d5b73abdf9499ad59e", +"tsql": "839434d5b73abdf9499ad59e" +} +], +[ +"contracts", +{ +"None": "ab9b0c5c3dd6f54aea71a5f1", +"bigquery": "ab9b0c5c3dd6f54aea71a5f1", +"databricks": "ab9b0c5c3dd6f54aea71a5f1", +"duckdb": "ab9b0c5c3dd6f54aea71a5f1", +"postgres": "ab9b0c5c3dd6f54aea71a5f1", +"snowflake": "ab9b0c5c3dd6f54aea71a5f1", +"tsql": "ab9b0c5c3dd6f54aea71a5f1" +} +], +[ +"contracts", +{ +"None": "d9c54c1a8d6089f971147bfc", +"bigquery": "d9c54c1a8d6089f971147bfc", +"databricks": "d9c54c1a8d6089f971147bfc", +"duckdb": "d9c54c1a8d6089f971147bfc", +"postgres": "d9c54c1a8d6089f971147bfc", +"snowflake": "d9c54c1a8d6089f971147bfc", +"tsql": "d9c54c1a8d6089f971147bfc" +} +], +[ +"contracts", +{ +"None": "48ff6f452c064d9c0d6f68ed", +"bigquery": "48ff6f452c064d9c0d6f68ed", +"databricks": "48ff6f452c064d9c0d6f68ed", +"duckdb": "48ff6f452c064d9c0d6f68ed", +"postgres": "48ff6f452c064d9c0d6f68ed", +"snowflake": "48ff6f452c064d9c0d6f68ed", +"tsql": "78d512867db744527fe3982b" +} +], +[ +"contracts", +{ +"None": "17c278499d9aad7922d610d5", +"bigquery": "17c278499d9aad7922d610d5", +"databricks": "17c278499d9aad7922d610d5", +"duckdb": "17c278499d9aad7922d610d5", +"postgres": "17c278499d9aad7922d610d5", +"snowflake": "17c278499d9aad7922d610d5", +"tsql": "17c278499d9aad7922d610d5" +} +], +[ +"contracts", +{ +"None": "c332cbe9d45bff687e91f93b", +"bigquery": "c332cbe9d45bff687e91f93b", +"databricks": "c332cbe9d45bff687e91f93b", +"duckdb": "c332cbe9d45bff687e91f93b", +"postgres": "c332cbe9d45bff687e91f93b", +"snowflake": "c332cbe9d45bff687e91f93b", +"tsql": "c332cbe9d45bff687e91f93b" +} +], +[ +"contracts", +{ +"None": "23893ae7f9f05f0777697eba", +"bigquery": "23893ae7f9f05f0777697eba", +"databricks": "23893ae7f9f05f0777697eba", +"duckdb": "23893ae7f9f05f0777697eba", +"postgres": "23893ae7f9f05f0777697eba", +"snowflake": "23893ae7f9f05f0777697eba", +"tsql": "23893ae7f9f05f0777697eba" +} +], +[ +"contracts", +{ +"None": "bcc0d54db4ee9d237ef10dd4", +"bigquery": "bcc0d54db4ee9d237ef10dd4", +"databricks": "bcc0d54db4ee9d237ef10dd4", +"duckdb": "bcc0d54db4ee9d237ef10dd4", +"postgres": "bcc0d54db4ee9d237ef10dd4", +"snowflake": "bcc0d54db4ee9d237ef10dd4", +"tsql": "bcc0d54db4ee9d237ef10dd4" +} +], +[ +"contracts", +{ +"None": "0d0a771fb0ff7b39fb021d4d", +"bigquery": "0d0a771fb0ff7b39fb021d4d", +"databricks": "0d0a771fb0ff7b39fb021d4d", +"duckdb": "0d0a771fb0ff7b39fb021d4d", +"postgres": "0d0a771fb0ff7b39fb021d4d", +"snowflake": "0d0a771fb0ff7b39fb021d4d", +"tsql": "0d0a771fb0ff7b39fb021d4d" +} +], +[ +"contracts", +{ +"None": "98b119ddd61340fcdf4830fb", +"bigquery": "98b119ddd61340fcdf4830fb", +"databricks": "98b119ddd61340fcdf4830fb", +"duckdb": "98b119ddd61340fcdf4830fb", +"postgres": "98b119ddd61340fcdf4830fb", +"snowflake": "98b119ddd61340fcdf4830fb", +"tsql": "98b119ddd61340fcdf4830fb" +} +], +[ +"contracts", +{ +"None": "f100476682030d396856d58d", +"bigquery": "f100476682030d396856d58d", +"databricks": "f100476682030d396856d58d", +"duckdb": "f100476682030d396856d58d", +"postgres": "f100476682030d396856d58d", +"snowflake": "f100476682030d396856d58d", +"tsql": "f100476682030d396856d58d" +} +], +[ +"contracts", +{ +"None": "d03a2acd92b5e17c753a9272", +"bigquery": "d03a2acd92b5e17c753a9272", +"databricks": "d03a2acd92b5e17c753a9272", +"duckdb": "d03a2acd92b5e17c753a9272", +"postgres": "d03a2acd92b5e17c753a9272", +"snowflake": "d03a2acd92b5e17c753a9272", +"tsql": "d03a2acd92b5e17c753a9272" +} +], +[ +"contracts", +{ +"None": "2d4b87c5b06ff335bd6c741b", +"bigquery": "2d4b87c5b06ff335bd6c741b", +"databricks": "2d4b87c5b06ff335bd6c741b", +"duckdb": "2d4b87c5b06ff335bd6c741b", +"postgres": "2d4b87c5b06ff335bd6c741b", +"snowflake": "2d4b87c5b06ff335bd6c741b", +"tsql": "2d4b87c5b06ff335bd6c741b" +} +], +[ +"contracts", +{ +"None": "a2dffd29b4f083e47c096d79", +"bigquery": "a2dffd29b4f083e47c096d79", +"databricks": "a2dffd29b4f083e47c096d79", +"duckdb": "a2dffd29b4f083e47c096d79", +"postgres": "a2dffd29b4f083e47c096d79", +"snowflake": "a2dffd29b4f083e47c096d79", +"tsql": "a2dffd29b4f083e47c096d79" +} +], +[ +"contracts", +{ +"None": "de4c230e461e81a5ec9457cf", +"bigquery": "de4c230e461e81a5ec9457cf", +"databricks": "de4c230e461e81a5ec9457cf", +"duckdb": "de4c230e461e81a5ec9457cf", +"postgres": "de4c230e461e81a5ec9457cf", +"snowflake": "de4c230e461e81a5ec9457cf", +"tsql": "de4c230e461e81a5ec9457cf" +} +], +[ +"contracts", +{ +"None": "ffd2f2034ea38a1c665386fe", +"bigquery": "ffd2f2034ea38a1c665386fe", +"databricks": "ffd2f2034ea38a1c665386fe", +"duckdb": "ffd2f2034ea38a1c665386fe", +"postgres": "ffd2f2034ea38a1c665386fe", +"snowflake": "ffd2f2034ea38a1c665386fe", +"tsql": "ffd2f2034ea38a1c665386fe" +} +], +[ +"contracts", +{ +"None": "b3283bf184bb082f364b8537", +"bigquery": "b3283bf184bb082f364b8537", +"databricks": "b3283bf184bb082f364b8537", +"duckdb": "b3283bf184bb082f364b8537", +"postgres": "b3283bf184bb082f364b8537", +"snowflake": "b3283bf184bb082f364b8537", +"tsql": "b3283bf184bb082f364b8537" +} +], +[ +"contracts", +{ +"None": "c11f8c29184eeda19979e5d2", +"bigquery": "c11f8c29184eeda19979e5d2", +"databricks": "c11f8c29184eeda19979e5d2", +"duckdb": "c11f8c29184eeda19979e5d2", +"postgres": "c11f8c29184eeda19979e5d2", +"snowflake": "c11f8c29184eeda19979e5d2", +"tsql": "c11f8c29184eeda19979e5d2" +} +], +[ +"contracts", +{ +"None": "6a14752b404ff8337dbb4c51", +"bigquery": "6a14752b404ff8337dbb4c51", +"databricks": "6a14752b404ff8337dbb4c51", +"duckdb": "6a14752b404ff8337dbb4c51", +"postgres": "6a14752b404ff8337dbb4c51", +"snowflake": "6a14752b404ff8337dbb4c51", +"tsql": "6a14752b404ff8337dbb4c51" +} +], +[ +"contracts", +{ +"None": "67cc42e5fd32018ec01cf44c", +"bigquery": "67cc42e5fd32018ec01cf44c", +"databricks": "67cc42e5fd32018ec01cf44c", +"duckdb": "67cc42e5fd32018ec01cf44c", +"postgres": "67cc42e5fd32018ec01cf44c", +"snowflake": "67cc42e5fd32018ec01cf44c", +"tsql": "67cc42e5fd32018ec01cf44c" +} +], +[ +"contracts", +{ +"None": "d766e542b46b503b1d64b5ec", +"bigquery": "d766e542b46b503b1d64b5ec", +"databricks": "d766e542b46b503b1d64b5ec", +"duckdb": "d766e542b46b503b1d64b5ec", +"postgres": "d766e542b46b503b1d64b5ec", +"snowflake": "d766e542b46b503b1d64b5ec", +"tsql": "d766e542b46b503b1d64b5ec" +} +], +[ +"contracts", +{ +"None": "f55edb3192180fa6df21c085", +"bigquery": "f55edb3192180fa6df21c085", +"databricks": "f55edb3192180fa6df21c085", +"duckdb": "f55edb3192180fa6df21c085", +"postgres": "f55edb3192180fa6df21c085", +"snowflake": "f55edb3192180fa6df21c085", +"tsql": "f55edb3192180fa6df21c085" +} +], +[ +"contracts", +{ +"None": "b3283bf184bb082f364b8537", +"bigquery": "b3283bf184bb082f364b8537", +"databricks": "b3283bf184bb082f364b8537", +"duckdb": "b3283bf184bb082f364b8537", +"postgres": "b3283bf184bb082f364b8537", +"snowflake": "b3283bf184bb082f364b8537", +"tsql": "b3283bf184bb082f364b8537" +} +], +[ +"contracts", +{ +"None": "36ccf7779e90a958c5dcad96", +"bigquery": "36ccf7779e90a958c5dcad96", +"databricks": "36ccf7779e90a958c5dcad96", +"duckdb": "36ccf7779e90a958c5dcad96", +"postgres": "36ccf7779e90a958c5dcad96", +"snowflake": "36ccf7779e90a958c5dcad96", +"tsql": "36ccf7779e90a958c5dcad96" +} +], +[ +"contracts", +{ +"None": "e44260e0d2411c3cce8781cc", +"bigquery": "e44260e0d2411c3cce8781cc", +"databricks": "e44260e0d2411c3cce8781cc", +"duckdb": "e44260e0d2411c3cce8781cc", +"postgres": "e44260e0d2411c3cce8781cc", +"snowflake": "e44260e0d2411c3cce8781cc", +"tsql": "e44260e0d2411c3cce8781cc" +} +], +[ +"contracts", +{ +"None": "cd5296ac257b6e4f10c3000d", +"bigquery": "cd5296ac257b6e4f10c3000d", +"databricks": "cd5296ac257b6e4f10c3000d", +"duckdb": "cd5296ac257b6e4f10c3000d", +"postgres": "cd5296ac257b6e4f10c3000d", +"snowflake": "cd5296ac257b6e4f10c3000d", +"tsql": "cd5296ac257b6e4f10c3000d" +} +], +[ +"contracts", +{ +"None": "0fb1be349cccda275d77113d", +"bigquery": "0fb1be349cccda275d77113d", +"databricks": "0fb1be349cccda275d77113d", +"duckdb": "0fb1be349cccda275d77113d", +"postgres": "0fb1be349cccda275d77113d", +"snowflake": "0fb1be349cccda275d77113d", +"tsql": "0fb1be349cccda275d77113d" +} +], +[ +"contracts", +{ +"None": "d9843bd5f2e76b8d875badaf", +"bigquery": "d9843bd5f2e76b8d875badaf", +"databricks": "d9843bd5f2e76b8d875badaf", +"duckdb": "d9843bd5f2e76b8d875badaf", +"postgres": "d9843bd5f2e76b8d875badaf", +"snowflake": "d9843bd5f2e76b8d875badaf", +"tsql": "d9843bd5f2e76b8d875badaf" +} +], +[ +"contracts", +{ +"None": "afb26acda81b184518d6d6f5", +"bigquery": "afb26acda81b184518d6d6f5", +"databricks": "f6dafe38c2aa2436ad17d2e6", +"duckdb": "f6dafe38c2aa2436ad17d2e6", +"postgres": "afb26acda81b184518d6d6f5", +"snowflake": "f6dafe38c2aa2436ad17d2e6", +"tsql": "afb26acda81b184518d6d6f5" +} +], +[ +"contracts", +{ +"None": "2a167c9cb4bdcef7cfbcd99a", +"bigquery": "2a167c9cb4bdcef7cfbcd99a", +"databricks": "2a167c9cb4bdcef7cfbcd99a", +"duckdb": "2a167c9cb4bdcef7cfbcd99a", +"postgres": "2a167c9cb4bdcef7cfbcd99a", +"snowflake": "2a167c9cb4bdcef7cfbcd99a", +"tsql": "2a167c9cb4bdcef7cfbcd99a" +} +], +[ +"contracts", +{ +"None": "ea9fe2e44b57cc7f6a5654aa", +"bigquery": "ea9fe2e44b57cc7f6a5654aa", +"databricks": "ea9fe2e44b57cc7f6a5654aa", +"duckdb": "ea9fe2e44b57cc7f6a5654aa", +"postgres": "ea9fe2e44b57cc7f6a5654aa", +"snowflake": "ea9fe2e44b57cc7f6a5654aa", +"tsql": "ea9fe2e44b57cc7f6a5654aa" +} +], +[ +"contracts", +{ +"None": "fe017b6cb02eef5219322f7c", +"bigquery": "fe017b6cb02eef5219322f7c", +"databricks": "fe017b6cb02eef5219322f7c", +"duckdb": "fe017b6cb02eef5219322f7c", +"postgres": "fe017b6cb02eef5219322f7c", +"snowflake": "34168d14eef2cb971b3882fb", +"tsql": "fe017b6cb02eef5219322f7c" +} +], +[ +"contracts", +{ +"None": "7d8609a5dcd3a0f32d347465", +"bigquery": "7d8609a5dcd3a0f32d347465", +"databricks": "7d8609a5dcd3a0f32d347465", +"duckdb": "7d8609a5dcd3a0f32d347465", +"postgres": "7d8609a5dcd3a0f32d347465", +"snowflake": "7d8609a5dcd3a0f32d347465", +"tsql": "7d8609a5dcd3a0f32d347465" +} +], +[ +"contracts", +{ +"None": "8dd6f78d1bbd41f3f2f556fb", +"bigquery": "8dd6f78d1bbd41f3f2f556fb", +"databricks": "8dd6f78d1bbd41f3f2f556fb", +"duckdb": "8dd6f78d1bbd41f3f2f556fb", +"postgres": "8dd6f78d1bbd41f3f2f556fb", +"snowflake": "8dd6f78d1bbd41f3f2f556fb", +"tsql": "8dd6f78d1bbd41f3f2f556fb" +} +], +[ +"contracts", +{ +"None": "891f3d8b2c293698577c7813", +"bigquery": "891f3d8b2c293698577c7813", +"databricks": "891f3d8b2c293698577c7813", +"duckdb": "891f3d8b2c293698577c7813", +"postgres": "891f3d8b2c293698577c7813", +"snowflake": "891f3d8b2c293698577c7813", +"tsql": "891f3d8b2c293698577c7813" +} +], +[ +"contracts", +{ +"None": "cbbf749b3fdb1008cd35c8ee", +"bigquery": "cbbf749b3fdb1008cd35c8ee", +"databricks": "cbbf749b3fdb1008cd35c8ee", +"duckdb": "cbbf749b3fdb1008cd35c8ee", +"postgres": "cbbf749b3fdb1008cd35c8ee", +"snowflake": "cbbf749b3fdb1008cd35c8ee", +"tsql": "cbbf749b3fdb1008cd35c8ee" +} +], +[ +"contracts", +{ +"None": "6f1634dc604b82f58c1d760f", +"bigquery": "6f1634dc604b82f58c1d760f", +"databricks": "6f1634dc604b82f58c1d760f", +"duckdb": "6f1634dc604b82f58c1d760f", +"postgres": "6f1634dc604b82f58c1d760f", +"snowflake": "6f1634dc604b82f58c1d760f", +"tsql": "6f1634dc604b82f58c1d760f" +} +], +[ +"contracts", +{ +"None": "2fb2d4657d6af84c32083288", +"bigquery": "2fb2d4657d6af84c32083288", +"databricks": "2fb2d4657d6af84c32083288", +"duckdb": "2fb2d4657d6af84c32083288", +"postgres": "2fb2d4657d6af84c32083288", +"snowflake": "2fb2d4657d6af84c32083288", +"tsql": "2fb2d4657d6af84c32083288" +} +], +[ +"contracts", +{ +"None": "a9bdcb7ee2642092b9c2e2ae", +"bigquery": "a9bdcb7ee2642092b9c2e2ae", +"databricks": "a9bdcb7ee2642092b9c2e2ae", +"duckdb": "a9bdcb7ee2642092b9c2e2ae", +"postgres": "a9bdcb7ee2642092b9c2e2ae", +"snowflake": "a9bdcb7ee2642092b9c2e2ae", +"tsql": "a9bdcb7ee2642092b9c2e2ae" +} +], +[ +"contracts", +{ +"None": "a8bc34d679ed5c1bd41c17ba", +"bigquery": "0f72c2e3063cc166300becea", +"databricks": "a8bc34d679ed5c1bd41c17ba", +"duckdb": "a8bc34d679ed5c1bd41c17ba", +"postgres": "a8bc34d679ed5c1bd41c17ba", +"snowflake": "0f72c2e3063cc166300becea", +"tsql": "a8bc34d679ed5c1bd41c17ba" +} +], +[ +"contracts", +{ +"None": "6e5f3057275c88687658bb88", +"bigquery": "6e5f3057275c88687658bb88", +"databricks": "6e5f3057275c88687658bb88", +"duckdb": "6e5f3057275c88687658bb88", +"postgres": "6e5f3057275c88687658bb88", +"snowflake": "6e5f3057275c88687658bb88", +"tsql": "6e5f3057275c88687658bb88" +} +], +[ +"contracts", +{ +"None": "b3283bf184bb082f364b8537", +"bigquery": "b3283bf184bb082f364b8537", +"databricks": "b3283bf184bb082f364b8537", +"duckdb": "b3283bf184bb082f364b8537", +"postgres": "b3283bf184bb082f364b8537", +"snowflake": "b3283bf184bb082f364b8537", +"tsql": "b3283bf184bb082f364b8537" +} +], +[ +"contracts", +{ +"None": "6581612a11662f5afd928e61", +"bigquery": "6581612a11662f5afd928e61", +"databricks": "6581612a11662f5afd928e61", +"duckdb": "6581612a11662f5afd928e61", +"postgres": "6581612a11662f5afd928e61", +"snowflake": "6581612a11662f5afd928e61", +"tsql": "6581612a11662f5afd928e61" +} +], +[ +"contracts", +{ +"None": "3405db15b2687320907ae528", +"bigquery": "3405db15b2687320907ae528", +"databricks": "3405db15b2687320907ae528", +"duckdb": "3405db15b2687320907ae528", +"postgres": "3405db15b2687320907ae528", +"snowflake": "3405db15b2687320907ae528", +"tsql": "3405db15b2687320907ae528" +} +], +[ +"contracts", +{ +"None": "1bd8641f841c3847419d163b", +"bigquery": "1bd8641f841c3847419d163b", +"databricks": "1bd8641f841c3847419d163b", +"duckdb": "1bd8641f841c3847419d163b", +"postgres": "1bd8641f841c3847419d163b", +"snowflake": "1bd8641f841c3847419d163b", +"tsql": "1bd8641f841c3847419d163b" +} +], +[ +"contracts", +{ +"None": "b3283bf184bb082f364b8537", +"bigquery": "b3283bf184bb082f364b8537", +"databricks": "b3283bf184bb082f364b8537", +"duckdb": "b3283bf184bb082f364b8537", +"postgres": "b3283bf184bb082f364b8537", +"snowflake": "b3283bf184bb082f364b8537", +"tsql": "b3283bf184bb082f364b8537" +} +], +[ +"contracts", +{ +"None": "70130ae9c4f7aa6a50756c6b", +"bigquery": "70130ae9c4f7aa6a50756c6b", +"databricks": "70130ae9c4f7aa6a50756c6b", +"duckdb": "70130ae9c4f7aa6a50756c6b", +"postgres": "70130ae9c4f7aa6a50756c6b", +"snowflake": "70130ae9c4f7aa6a50756c6b", +"tsql": "70130ae9c4f7aa6a50756c6b" +} +], +[ +"contracts", +{ +"None": "cbbf749b3fdb1008cd35c8ee", +"bigquery": "cbbf749b3fdb1008cd35c8ee", +"databricks": "cbbf749b3fdb1008cd35c8ee", +"duckdb": "cbbf749b3fdb1008cd35c8ee", +"postgres": "cbbf749b3fdb1008cd35c8ee", +"snowflake": "cbbf749b3fdb1008cd35c8ee", +"tsql": "cbbf749b3fdb1008cd35c8ee" +} +], +[ +"contracts", +{ +"None": "0e98df1b9bfd713dda177188", +"bigquery": "0e98df1b9bfd713dda177188", +"databricks": "0e98df1b9bfd713dda177188", +"duckdb": "0e98df1b9bfd713dda177188", +"postgres": "0e98df1b9bfd713dda177188", +"snowflake": "0e98df1b9bfd713dda177188", +"tsql": "0e98df1b9bfd713dda177188" +} +], +[ +"contracts", +{ +"None": "b69ef1eaba1124a7e710d482", +"bigquery": "b69ef1eaba1124a7e710d482", +"databricks": "b69ef1eaba1124a7e710d482", +"duckdb": "b69ef1eaba1124a7e710d482", +"postgres": "b69ef1eaba1124a7e710d482", +"snowflake": "b69ef1eaba1124a7e710d482", +"tsql": "b69ef1eaba1124a7e710d482" +} +], +[ +"contracts", +{ +"None": "866ae81507c3a535c0225de2", +"bigquery": "866ae81507c3a535c0225de2", +"databricks": "866ae81507c3a535c0225de2", +"duckdb": "866ae81507c3a535c0225de2", +"postgres": "866ae81507c3a535c0225de2", +"snowflake": "866ae81507c3a535c0225de2", +"tsql": "866ae81507c3a535c0225de2" +} +] +] diff --git a/tests/goldens/python_oracle/cte_facts_casts_case_coalesce_if_iff_adapter_rules_set_operations_stars_joins_filters.json b/tests/goldens/python_oracle/cte_facts_casts_case_coalesce_if_iff_adapter_rules_set_operations_stars_joins_filters.json new file mode 100644 index 0000000000..b7ac4fbe19 --- /dev/null +++ b/tests/goldens/python_oracle/cte_facts_casts_case_coalesce_if_iff_adapter_rules_set_operations_stars_joins_filters.json @@ -0,0 +1,20002 @@ +[ +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"c4aa1da0f1d478755dcf8a3a" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"7dba6a1e770fcc198f69d145" +], +[ +"cte_facts", +"e55706d39e555ea7115c576c" +], +[ +"cte_facts", +"87ef0419b3ea862c9735302e" +], +[ +"cte_facts", +"bdcb307145ced4668afe64e3" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"6d76f8a48f9b12ee518e60fb" +], +[ +"cte_facts", +"5ffd2069d857db078b0ec5c2" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"b8e380077825cf182ace2d99" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"6a0d23ddf3acd4eb8690adc1" +], +[ +"cte_facts", +"d93f5e8f59a3d40112e9332a" +], +[ +"cte_facts", +"17c588f2bbb97a4bc13443f0" +], +[ +"cte_facts", +"fd8b37a35f3e2c74c92576d8" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"3c7c4024333942fa430e93d4" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"e5c0431376b17c69ec8bb239" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"19b25264866922f98a2dcb19" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"5e98624071bd40877af25354" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"f3b58b842ed9380d8ae1ce94" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"8ad9c73dcb08b7eacb70299e" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"fbb441f302177546e3833646" +], +[ +"cte_facts", +"2ac4e5c7259c7cbd45a09753" +], +[ +"cte_facts", +"a4b0ab53b7f8c3a6975714f1" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"359f7b43ff014fb622d621f9" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"9573ce4ca7b2b1fba23b8c84" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"95e71c4565200f73840d303d" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"ed71610322a74156754f5d27" +], +[ +"cte_facts", +"a48132b7780ae8d603d76900" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"6a0d23ddf3acd4eb8690adc1" +], +[ +"cte_facts", +"ca1a177f7157dec08bb1bc7c" +], +[ +"cte_facts", +"039ac124b2350f419e7ccd87" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"343133878e398b8afc9d4ec2" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a1393e4430e2d96e740ed4d3" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"864639f359cdbdd39a1f08a8" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"5151c7461586a79a23178305" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"653a5d5e3f9a849d912c7f85" +], +[ +"cte_facts", +"02745ecccaca07e75093e1b1" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"934209e73aef79ef60ea8520" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"3c868975bfd30e3e6785859d" +], +[ +"cte_facts", +"2ad9f23db26467e4e2f389d1" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"204bc8bed3e771cc7eebc037" +], +[ +"cte_facts", +"e424f045b964a22cc93b52fe" +], +[ +"cte_facts", +"da73f43053e1e067e3c27d95" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"d24d917c7ae3992ae654e52e" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"882da20a3b2430bec6b02456" +], +[ +"cte_facts", +"411a4ff3c72a2d03bf69579f" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"681af4ba9ec9ff73ebe5afdd" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"f44562e2016b7337866b3ef1" +], +[ +"cte_facts", +"c742d17ed46b2233ba193beb" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"8aa0bfe1294c418cbcea98a7" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"75898bdb63df78bcf19c6b21" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"5b7ed9bf45e0827c61c44143" +], +[ +"cte_facts", +"8199e5ad510ba5d0bd0d20ed" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"4db4546cf049f2d63cebe9f7" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"3c7c4024333942fa430e93d4" +], +[ +"cte_facts", +"af3195b0c034a44bd2bdd812" +], +[ +"cte_facts", +"7e5cc2be9df60dac53d4f891" +], +[ +"cte_facts", +"07366cdce02e55b0f4364c50" +], +[ +"cte_facts", +"aa9fb5b8c130c6ffb432f3f8" +], +[ +"cte_facts", +"7521fec50dbc20c6306c7cc6" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"e5c0431376b17c69ec8bb239" +], +[ +"cte_facts", +"08385877e1a9d2a18c9ca75d" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"0ba77f9f2c880134f9ae0ce1" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"e00d4ad6ac1059ec06a5eabf" +], +[ +"cte_facts", +"35384c58f5428d4c096a4569" +], +[ +"cte_facts", +"f2176833ed4d1168120afec4" +], +[ +"cte_facts", +"5a85c76baa2f4e4dc772787d" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"42aa8a2fc4d0488a5eee3f8d" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"ba9cfeda084c6e74101948f6" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"6a0d23ddf3acd4eb8690adc1" +], +[ +"cte_facts", +"085967ae5ed3a757c5b0feb8" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"8bda81857f610884feee3230" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"b289d13480a6673a743e82e4" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"ce3ed0ce92618374381ad418" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"e3e721cf187332480c9e5ad2" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"da39cb61a8156b9d35e40ff8" +], +[ +"cte_facts", +"f5895c1d77c8f590ef4e7477" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"79c08cc8c06967f247cdfd09" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"3a48896ab8bf836265be5643" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"ec0da57e1e89b3e0b93227fe" +], +[ +"cte_facts", +"075df3a32942712e6d91b09e" +], +[ +"cte_facts", +"882da20a3b2430bec6b02456" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"ace5a6c00909b0bec1f2aefc" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"370d84396f619d4bc85b671e" +], +[ +"cte_facts", +"e5d6faf13655ed5a2dfdeb02" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a00bc1aea089f5badf154464" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"826bf6453b49a73cdf53aec8" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"1bfa15e991eb93ee9aeadc37" +], +[ +"cte_facts", +"9930623e1aee198195f1d0fe" +], +[ +"cte_facts", +"58392bbc2de6742937d7a68b" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"edd5f8f92b661b4075de3702" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"aab135855fd57bd42d0abf49" +], +[ +"cte_facts", +"915f9b197daf381c8ef0b5c4" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"e8dc441dbb5444fff5ef76fa" +], +[ +"cte_facts", +"9538db3dc0abfe1068ef4dfb" +], +[ +"cte_facts", +"62309c4535558a08999e41d7" +], +[ +"cte_facts", +"5925fee334e58d657b2b9aef" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"00a7ec97323806d55c3e51e6" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"da296187cb7225b157fd6ff6" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"1b09452e6b382fa38fd04ac8" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"03cb6976ba20a18a3ea5f850" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"903b989eb8e513c673a41ee5" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"dfed7518ced05f2523d2be87" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"e1193bd17eb647af362b2c6b" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"3fe437233e76b32c82aa4960" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7217b115b977b29e5404ca4" +], +[ +"cte_facts", +"3277f806a210ac9a80e25cb3" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"5b1a1b16aba91eb020793d3a" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"5a74f0d5ac433c353777d637" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"9e7eb59bc3b77041fb934759" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a11994b9d5efb063864097c4" +], +[ +"cte_facts", +"18417401649ba8eb931f5f1f" +], +[ +"cte_facts", +"a20c70ff116575d08a066320" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"f3256d9ef6946683c94d4150" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"24797cad26dd72d1f1a0a886" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"e00d4ad6ac1059ec06a5eabf" +], +[ +"cte_facts", +"5a453cd7b93ed7b68e6f8de8" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a562adac793967e5ac560f2f" +], +[ +"cte_facts", +"a928caabb1ae4d21f12bba19" +], +[ +"cte_facts", +"9846802632ecc9c9e6131e20" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"20e87b1d9005062c36c16b4b" +], +[ +"cte_facts", +"123959fc913a0db12bcc1de7" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"b2fd164aefb6da8aa8962bd4" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"2d73f308ba410450fb15e37f" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"847b413032c1e5993f51c539" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"6288ed72565ac4e60d67e5ac" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"e00d4ad6ac1059ec06a5eabf" +], +[ +"cte_facts", +"a7e34cf87ff4348a9640e6ab" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"5d81e113a2e67899c88cbc1c" +], +[ +"cte_facts", +"8a25919eaec2b38a1643761f" +], +[ +"cte_facts", +"acb0c618555111c112ae71c2" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"6e3464bf07093435340eefa6" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"aa9fb5b8c130c6ffb432f3f8" +], +[ +"cte_facts", +"e112dab990efa8668b76b7ac" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"785c80e17f1ac174c0151de1" +], +[ +"cte_facts", +"5151c7461586a79a23178305" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"4377bd36fe5c13dfa27b6a62" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"df75f39d2709de69b46c11ec" +], +[ +"cte_facts", +"06e4c5dee9a367aad4191ceb" +], +[ +"cte_facts", +"172ae9b0adad29f893e6ee1e" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"b28020a95692a449f55a5fdb" +], +[ +"cte_facts", +"decf92afee5279adb4e9baf2" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"0f2e0f6a350ede31cde1d277" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"1766b78edb98f037adb93443" +], +[ +"cte_facts", +"45600a76b057f3bc8d7aa623" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"0fe37f13ac7d5d3af376d7ec" +], +[ +"cte_facts", +"90dad19621993cfadf9abb81" +], +[ +"cte_facts", +"024ff35a53aaaee5cb977edd" +], +[ +"cte_facts", +"c2ef1a1274c86ef5a5488140" +], +[ +"cte_facts", +"af3195b0c034a44bd2bdd812" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"945fdae8cd8736881f672638" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"20e87b1d9005062c36c16b4b" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"68706a47d024899f769eb2db" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"b387f20e3aa10fe75788fb57" +], +[ +"cte_facts", +"c7240994805b0343e1f7b508" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"f12cafb0286960a1cf50c8e0" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"5ee078ffad2c2dd7de9d273e" +], +[ +"cte_facts", +"e3378a1959667c216051398a" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"38202ce0208447eb438ff5e9" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"1d9a728cd6935010f4b9eb67" +], +[ +"cte_facts", +"f90294ebb9638ba3b9ad7280" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"f4dbb308e7c8e371d6be6109" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"abf6ef72e65b008efcc58f84" +], +[ +"cte_facts", +"c007d695718a581c99533580" +], +[ +"cte_facts", +"8213eaf4cdd52bbed31c0402" +], +[ +"cte_facts", +"79126c548cd04db1361ce77c" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"6b1968a71df44affd6ca82ec" +], +[ +"cte_facts", +"4a4dd3e640fbf97d1b20b4e7" +], +[ +"cte_facts", +"a1393e4430e2d96e740ed4d3" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"f41357edc80bde20af9b02d1" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"df75f39d2709de69b46c11ec" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"13018cb6e748ed66382b9663" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"0fcd016def2c6a87bd549112" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"c2ef1a1274c86ef5a5488140" +], +[ +"cte_facts", +"df75f39d2709de69b46c11ec" +], +[ +"cte_facts", +"6d5b9939ae74a230637f0e55" +], +[ +"cte_facts", +"6d76d2d25d077d84fd780b34" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"681cf8357fb16b851e3096eb" +], +[ +"cte_facts", +"60b233038b04045136a907b6" +], +[ +"cte_facts", +"1fd9c3fbfd67a1908c9a796b" +], +[ +"cte_facts", +"606c7a9480f49d5612d66d2a" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"1f8dbc9ba9b0b39e455f8aea" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"b751dbe75bd57eb0270e5f25" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"931c32179bb339f5390d28ca" +], +[ +"cte_facts", +"2fddbf292233c79bcaaba2c2" +], +[ +"cte_facts", +"5430136f6bffab1727da3f78" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"cf56d985716a981f1117d243" +], +[ +"cte_facts", +"02a6a797e954c6207879bfb5" +], +[ +"cte_facts", +"4821a73aa15fd91072beb470" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"9efc74715706347643980677" +], +[ +"cte_facts", +"24d17721c79882b0a6454187" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"3fe437233e76b32c82aa4960" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a00bc1aea089f5badf154464" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"4377bd36fe5c13dfa27b6a62" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"d756bdc130b80ac669a33f5d" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"6df197f15020a677b51f12d5" +], +[ +"cte_facts", +"3cefaac56bac25fdb8a0c2d7" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"d8d334479feee0848404d6d4" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"74c48b6f726adfcd4d31a1d1" +], +[ +"cte_facts", +"c890db40a2f2ab2c538ef503" +], +[ +"cte_facts", +"09dc74b9ec8a19ca0e931a6f" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"b2abfc225ad5b092fe9ac4a6" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"47fc474e7873313d76b77a4a" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a3e2165aa660f4d87a8fdf83" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"0ff36f2b49db0e4d671f2617" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"f1d1b41c96997d7e6de43873" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"281d8ccb4f1abf88fa77c482" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"308949c4abeae0319d98caaf" +], +[ +"cte_facts", +"5c2dc0b2057d0c2922975568" +], +[ +"cte_facts", +"8f8370abd4d163c28199f1b7" +], +[ +"cte_facts", +"370d84396f619d4bc85b671e" +], +[ +"cte_facts", +"e472c1a16e9196ae9c6c8fd7" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"bcb2c930000e14237701e41c" +], +[ +"cte_facts", +"6c32e27c13d903f4d74d8897" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"e58e07048c41f9428f391a12" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"da73f43053e1e067e3c27d95" +], +[ +"cte_facts", +"39ed39fa998f81756bf1428f" +], +[ +"cte_facts", +"6210461521a0458ea6179424" +], +[ +"cte_facts", +"b53da886256c402811142838" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"eed09387c738f440df36ea2f" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"03c799c49085d71b734a8387" +], +[ +"cte_facts", +"dee5964f5d2de02ff70d818b" +], +[ +"cte_facts", +"006f45db244fdae25f809555" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a9d8c38fffa45e3b0d783f" +], +[ +"cte_facts", +"27db24149f2eb0ea4bec43bb" +], +[ +"cte_facts", +"d756bdc130b80ac669a33f5d" +], +[ +"cte_facts", +"31ce05446f06237043d47233" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"2a3244f3e68c2fa3b469e0e6" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"ef6098dfd72b64b656c91b5f" +], +[ +"cte_facts", +"cc5b8b5d6a66f8fafdd62656" +], +[ +"cte_facts", +"10e8544574f2f945ffae2040" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"cf121293d0da0cd5c19bc028" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"b9db6b400c08d41ff6ffa8fa" +], +[ +"cte_facts", +"6820c680b3e1ead11bf4a810" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"0e5a93beb28a7907f982f2f7" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"329741eafdfb707c0754b2a8" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"784ea83c107483495cf058ac" +], +[ +"cte_facts", +"47a1eac84943176c4f7a9804" +], +[ +"cte_facts", +"e316b93608cdb7ad0f0b8b3a" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"483ff2f29b13c836c87aaa58" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"8f8370abd4d163c28199f1b7" +], +[ +"cte_facts", +"8e7c297f23d00786ef682bb6" +], +[ +"cte_facts", +"10eb7c78ba7a51052f84322b" +], +[ +"cte_facts", +"fe03ab15d1c955db36241607" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"116f83c4e2caf8ff0449e46c" +], +[ +"cte_facts", +"66b1e27d5c7221b41db2a29d" +], +[ +"cte_facts", +"109c5b2531d5283555d42bf3" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"988cfb8925411f841ae56bc8" +], +[ +"cte_facts", +"3cba35c370aaf50c7489c5e9" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"b7a00046e5722e993b5b0e35" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"c9aa0341836c73978257bd2c" +], +[ +"cte_facts", +"b8c4da60c1f4ccd89c98d3bc" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"f331e74518af118048b1c22f" +], +[ +"cte_facts", +"3c733fbd97f11c1ae39ee072" +], +[ +"cte_facts", +"5cf31fa4748a07198b799516" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"e67d658f2f46e2727c497700" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"1e0b5081e91e76f874870f56" +], +[ +"cte_facts", +"9c3cd032cba764839a7c50f6" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"2211ce1dc3b63b8634d7e29b" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"5719f687b441d45b1b1f6262" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"791f0c0098a88896baa49451" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"b5630daadcfeb802c880b22b" +], +[ +"cte_facts", +"decf92afee5279adb4e9baf2" +], +[ +"cte_facts", +"ba45f9e7a0225156bcb5ebfa" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"d2489c5742c84311be0ca63a" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"931c32179bb339f5390d28ca" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"0066561a40fd49f80b37f727" +], +[ +"cte_facts", +"203f7a3902dd81670be0cbfb" +], +[ +"cte_facts", +"934209e73aef79ef60ea8520" +], +[ +"cte_facts", +"380265d92939e2ba3160c23c" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"f50d670cc1e96b61fad904cb" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"71113f45c0f00ae666dfb16f" +], +[ +"cte_facts", +"22b7dad8df2a84eae1fa80ce" +], +[ +"cte_facts", +"e5c0431376b17c69ec8bb239" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"abcfe8ec9c9c62480ebc7f99" +], +[ +"cte_facts", +"d4eaa039373b942c57e7e468" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"6c21dd5f85e82727a1bce8c3" +], +[ +"cte_facts", +"7cc40af0e041262d96463592" +], +[ +"cte_facts", +"71eea0018d52ec2098e37e19" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"d42403f29355378a9219f95a" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"c655926ac346061e33cd5aa8" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"cdb86a0ad527a6e25dab3363" +], +[ +"cte_facts", +"411a4ff3c72a2d03bf69579f" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"87627cc58e40e20711a025e2" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"2885b666e34bf5f69d5ba345" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"f100433a6ddd67cc3adb0d90" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"3be2ce131c1b738099e48896" +], +[ +"cte_facts", +"f530e38a1e389ba3589607d5" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"87650811bfa009b0feaf9bf4" +], +[ +"cte_facts", +"370d84396f619d4bc85b671e" +], +[ +"cte_facts", +"93d80d968a5aae65cddc194d" +], +[ +"cte_facts", +"5f479551e0eec78c41e71ba4" +], +[ +"cte_facts", +"eb95bccc50b3d769903746d6" +], +[ +"cte_facts", +"72f8e2dce9458a0213c2d2e2" +], +[ +"cte_facts", +"78ee6edb6a140a35daf6171b" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"7591e5efd7f226ea6648a828" +], +[ +"cte_facts", +"0bbfc524e9661c142ed7451a" +], +[ +"cte_facts", +"3309b324a7affadc48493aa6" +], +[ +"cte_facts", +"5ab72e089388d9dacf062f24" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"6a1861cd3e0566037f48751c" +], +[ +"cte_facts", +"95c582ea331b1c5498bfe485" +], +[ +"cte_facts", +"8d072c14a9d47791236ccce6" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"eed6fb3c58891d0068bac226" +], +[ +"cte_facts", +"4db4546cf049f2d63cebe9f7" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"f5b6b22b1d2051b8f8cd0744" +], +[ +"cte_facts", +"717f9807521044ccd494c02b" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"f9ddc19d61db0a1cf577c901" +], +[ +"cte_facts", +"a707c5b5165a27fc99861e5e" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"8f8370abd4d163c28199f1b7" +], +[ +"cte_facts", +"a7a9d8c38fffa45e3b0d783f" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"1e6f4cafeb0816cadeda8442" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"22fa8b6e8197f352e18f42f5" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"256299c4516f7c76fffd081f" +], +[ +"cte_facts", +"b72e68f738369de9b4c48790" +], +[ +"cte_facts", +"9d93133a60e49fee8fce8407" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"7f7f8f9b78d8b925e445416b" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"8994f278d44f6025a9fe0dbd" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"7ceb1f8c590d035be75a0a11" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"60c0c75661d495024c69323a" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"54a8494778eb2bcfa7a02231" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"55272ddc4f2bf5ab0526db7e" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"f41357edc80bde20af9b02d1" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"54718ce1f1c11fdde82afbe8" +], +[ +"cte_facts", +"4438d42825736fd903a3f0e4" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"882da20a3b2430bec6b02456" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"3beb8118486379f13a539b34" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"77b6c73fcf5946b9f7ac14aa" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"d7a4345e265c6f5a312e4540" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a34aca63995de9eb9a80b25e" +], +[ +"cte_facts", +"8d3c7a6e4d4db73443ad3afc" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"86b6d38cc3cce4981c3613c3" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"fab4e282daf75896518c98e4" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"4267c6ef3c4b0e04fc1f534d" +], +[ +"cte_facts", +"f311fef1ccbce6eb8cf9429a" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"c81147291ef378f27d56bdfc" +], +[ +"cte_facts", +"7df2768aaf03df896e6c8294" +], +[ +"cte_facts", +"c372dcd661f06065515e73e9" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"44e93b1bd1331e5681040334" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"7a3eb07506b9f2b59a597a1f" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"e5c0431376b17c69ec8bb239" +], +[ +"cte_facts", +"8a25919eaec2b38a1643761f" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"f718dd96e91014fd7962bda5" +], +[ +"cte_facts", +"16275f1ddcbbaf8f2df584e7" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"093e96245cc5209d4cbaeeba" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"0f5f2c7f4bfe8e219c4cae64" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"c3f795ce70c03ceb6b9daff8" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"5afa88ea2136b6a2e0d3a38b" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"d0158c58e7eeeb01f2c7eeb8" +], +[ +"cte_facts", +"15d0e4cf583be4aba460322c" +], +[ +"cte_facts", +"9de02647b93dc61457319f68" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"d30777b977850bbb40133d05" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"44f1dfbe9a8900c1a9feced9" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"6f4902b97556de2379c5efaa" +], +[ +"cte_facts", +"533f30891827411589ceca56" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"43be6bc915a43316ede185f3" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"d423a9ee75a313ba0ac74340" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"8c7ae05db549df52437873a9" +], +[ +"cte_facts", +"d8c4e1a3927b8f7d6ac5508e" +], +[ +"cte_facts", +"934209e73aef79ef60ea8520" +], +[ +"cte_facts", +"10380b7e75ea91f69fa626f8" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"4faacd50fddae2c8bf989322" +], +[ +"cte_facts", +"ea4e83b0cc26afd79f3d8458" +], +[ +"cte_facts", +"045618110a08e3aba8535fca" +], +[ +"cte_facts", +"a85fcaa6808c48fc9f7bec80" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a9c7c5354062238c0d6f2471" +], +[ +"cte_facts", +"2e5876c579421961f3ac5e88" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"5d319a9b513c464da65780f3" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"6469cfea0333baa85290dfbd" +], +[ +"cte_facts", +"ccb3ca9faa2a2282e1a880c5" +], +[ +"cte_facts", +"7c8a9dbd956abe11190a9e35" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"f4faaf760631624f1129378c" +], +[ +"cte_facts", +"a28af4ef3973749da47c6efb" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"7fe291699d06e6f801b0b3d2" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"54b2cc62496239f28826bb7f" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"deeceb5570e18756f333224c" +], +[ +"cte_facts", +"b622ed75a6cbaf518f37ea6b" +], +[ +"cte_facts", +"62d6915e88a664468aa33a9b" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"4377bd36fe5c13dfa27b6a62" +], +[ +"cte_facts", +"c481f08eade4324aed8dfc29" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"0c6ffc23cf231c73af4f8dee" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"971cb38e6d436a6cc035a32b" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"dd44d632b2b04f3899f72c21" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"10eb7c78ba7a51052f84322b" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a87c7943afd394f6ae25403a" +], +[ +"cte_facts", +"821689a7a3e12c0d14dcfdcc" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"3658079b0bda58d02c8c05a8" +], +[ +"cte_facts", +"ea3b39581bfe93505adabc66" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"0d74a69a8a5156281e3f2c06" +], +[ +"cte_facts", +"00b0ed38c8fd1aa0bfed91a7" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"cd063b7695dcb3d2a337d35f" +], +[ +"cte_facts", +"2266f190ec921a04c95473a6" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"4db4546cf049f2d63cebe9f7" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"decf92afee5279adb4e9baf2" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"c1ab292d0c08374fe35dd66b" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"c18610f62881611ac3a56785" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"f1b42ec21893a4c35ec4ddc1" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"2f64cd14dea2a987f8ef3df7" +], +[ +"cte_facts", +"b5c98e4f0861a9f86f510633" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"4377bd36fe5c13dfa27b6a62" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"8376b2f6625ec70a4b5679a6" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"4210f03a445d2854e9cb2884" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"f718dd96e91014fd7962bda5" +], +[ +"cte_facts", +"072c5bf2ceeb89ce0dd6f905" +], +[ +"cte_facts", +"85cf1023b521c603df7c680c" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"10abfab7ff22045b320b29d4" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"52bfcc544e1562d6cf4f2aee" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"e519f60e4183232aebc79aca" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"6322aaddede94778335eb00a" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"3e3b087f4c2846e834a8e822" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"5b404172620c8f1f2f5cf564" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"931c32179bb339f5390d28ca" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"d418b3d13418a7326edd4dcb" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"cef999db49ecf911ed2963d3" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"56b5e7e1523b53ec07eab721" +], +[ +"cte_facts", +"decf92afee5279adb4e9baf2" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"0a23d441d2369f2cab3b5d02" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"3518df502ad92141ba65ab80" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"45600a76b057f3bc8d7aa623" +], +[ +"cte_facts", +"cad111dda2e97bb573884b77" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"b9db6b400c08d41ff6ffa8fa" +], +[ +"cte_facts", +"3a9bf5cc8ff8bb0b49f2413b" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"9829ed0c99f7bc45acafe6f8" +], +[ +"cte_facts", +"20616b7443884ed31d002f1c" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"72cfad6995ba8a98867eb76c" +], +[ +"cte_facts", +"e349e079a068748626a741ff" +], +[ +"cte_facts", +"4c8999523b680e6658a4927a" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"7d0a3c31eeabdef193c78b9b" +], +[ +"cte_facts", +"6c243a3c44675de330f98e0d" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"d2a983eda00be6963424d04c" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"ffcd5286466af711ccf0c5a9" +], +[ +"cte_facts", +"c65ff553b876af4ee7bf360f" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"403a84c001658bcaf682f913" +], +[ +"cte_facts", +"ce64de05cea0dbeffe392a78" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"682ea922f2e010d016b3e82b" +], +[ +"cte_facts", +"e22acfe2eb5978367a4d13dc" +], +[ +"cte_facts", +"50550ed36eab4ead7df032d4" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"e8799445c9d370ac5ee84acb" +], +[ +"cte_facts", +"eb27411a15000e74077716cd" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"b7f417e9963bafec74b192e8" +], +[ +"cte_facts", +"a4cf7fa9ab41dd424494a453" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"d3c50785aaa5bb86fa58309b" +], +[ +"cte_facts", +"00fd89b5fc22e79c877eb65d" +], +[ +"cte_facts", +"c91b6caf02be38ceca64da20" +], +[ +"cte_facts", +"9a1604d2aba32886ff141d17" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"370d84396f619d4bc85b671e" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"70a83fa8faa7241de600a62e" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"370d84396f619d4bc85b671e" +], +[ +"cte_facts", +"717f9807521044ccd494c02b" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"cddfe9511ccf6d8b9b49ace3" +], +[ +"cte_facts", +"e11249b1be1dfcf4994830e3" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"6f967aed45f75589baec1064" +], +[ +"cte_facts", +"699cddb166e4d10b46c751d3" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a493dfdfa46884ab30b7c2d5" +], +[ +"cte_facts", +"648fce592e474a51a8b8fe6e" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"ef2fbedb17c498b2fb208591" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"8ff88bf913e03c73c4014edf" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"16161bc32b9ba2887a46339e" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a28af4ef3973749da47c6efb" +], +[ +"cte_facts", +"a7519eff523c32bdb14df8b7" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"cd8469ce3ccd15a1c382bc75" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"5925fee334e58d657b2b9aef" +], +[ +"cte_facts", +"411a4ff3c72a2d03bf69579f" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"17c155f5051dec610cf1d7c3" +], +[ +"cte_facts", +"26b57013b89a8760ea1c0b02" +], +[ +"cte_facts", +"7dadb5e76ee2a386f8989acd" +], +[ +"cte_facts", +"da85f23769ecb0b659bc027b" +], +[ +"cte_facts", +"50a4033641545f5af091f0c4" +], +[ +"cte_facts", +"6c5ad24cfb63d828de3fd55f" +], +[ +"cte_facts", +"b1b1a85f62cdce1ce48bc72e" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"d7d418253e6b9047f009f94b" +], +[ +"cte_facts", +"879e8fa5ec50584af1c5ef12" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"600bf5e5cf97ffeac7a142ef" +], +[ +"cte_facts", +"acc890e354bfbe8cb3c12266" +], +[ +"cte_facts", +"a15ddaa580d32f77d6166fca" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"7856143b5b9ca78818234b3a" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"15098845e756d79339f10de4" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"5925fee334e58d657b2b9aef" +], +[ +"cte_facts", +"968ac983ec3cc08095608953" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"d756bdc130b80ac669a33f5d" +], +[ +"cte_facts", +"18de50fa234011accf6c888e" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"af3195b0c034a44bd2bdd812" +], +[ +"cte_facts", +"1fbbda2053911f1b6732e2c2" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"30e28ae34fe2bdfbf7984569" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"fc73d2937f51b39800f08d79" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a9d8c38fffa45e3b0d783f" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a3e2f1c61882c647b7ad1606" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"fafde00af0b403c065be9bd8" +], +[ +"cte_facts", +"4017554cbedd50d1d663cb1a" +], +[ +"cte_facts", +"724b4f87bc24e04a242abc4e" +], +[ +"cte_facts", +"0cadbf4ce39ca81eacb0a281" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a902825ec0f49b9a7582ebf7" +], +[ +"cte_facts", +"e9df0d596f8baaa218efa6bd" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"3df0f6801a6bc31ff67743c6" +], +[ +"cte_facts", +"93bb657ded7152f4c013951c" +], +[ +"cte_facts", +"eb0efbb3b8901a1d577bed95" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"decf92afee5279adb4e9baf2" +], +[ +"cte_facts", +"5e63bd95425ce1c8fc255b1b" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"46b4b6d25d42544f2e7bf6ae" +], +[ +"cte_facts", +"6a2520f074d54da8f620c9bf" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"b9db6b400c08d41ff6ffa8fa" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"32815c8454b772eacab325c4" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"01424d7107cbfd6d4092bcae" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"18f17ed14fb6f31dab9678de" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"f124eb146f0e87f82092b295" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"c15b9f9104e33ea6ddd0d1bb" +], +[ +"cte_facts", +"f32f1dc3c953c65fb60a8409" +], +[ +"cte_facts", +"eeeed8fc1171dc7f5ab3ffa5" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"7a6fe2670b633b7236bccaa8" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"da73f43053e1e067e3c27d95" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"9a71ebd527cc7f6809ec410b" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"c98b2f2b24e00badc6429e6c" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"c62cd1aac4add9211f48320c" +], +[ +"cte_facts", +"6437ba15995efb77ff972715" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"15ff7d6fd44a58aa62053116" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"decf92afee5279adb4e9baf2" +], +[ +"cte_facts", +"508cc53138f894e5627f48e3" +], +[ +"cte_facts", +"6d4b88a0d215c6a1be9d389d" +], +[ +"cte_facts", +"48f28a55437fbc26cc953a36" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a00bc1aea089f5badf154464" +], +[ +"cte_facts", +"a864cdac67cdc2df9420b582" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"176236cffb1d1348a8a95a3a" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"3fe437233e76b32c82aa4960" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"45667988a22246c62f1933ad" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"7f2f3fd963b1442bd48cb26a" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"8b50460ef85cc2e406ce9237" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"7354aafdac4123877aeef378" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"931c32179bb339f5390d28ca" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"aa037e35d249f604369a9440" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"9df6f7f4c8d934c60e16ad14" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"3dc57dea717e159008b46ebb" +], +[ +"cte_facts", +"ddc453c4206a43050d3b6049" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"42aa8a2fc4d0488a5eee3f8d" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"689c627180ab2d3095c16e16" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"af4ef5c4775a8788ed7cd06c" +], +[ +"cte_facts", +"86caa0f97baef00d6a65c92f" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"4829c1b6749ee3f0daf22aaf" +], +[ +"cte_facts", +"39e1e270de512b0a6885ec36" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"d7b3fb8077eaf1c2fb780267" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"3cc8ed52f4c2c5c9d7b57220" +], +[ +"cte_facts", +"03ebaa5c774b130e8767f57d" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"34ca064c10296ffccea0a5f5" +], +[ +"cte_facts", +"e00aa2da2c3fe8a5d52183bf" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"bdf3304dd619954c5b054408" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"3e8a0f7c60497164c54a54bb" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"8b371600511fc7556a9cb430" +], +[ +"cte_facts", +"7ed64be8384fac306cbfd6cb" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"866eaf511c16d9d0e6a5895d" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"55b1bbfe9e280b444aace2df" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"2745e60c90656bcae17df793" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"fee32a84edda43487e9851aa" +], +[ +"cte_facts", +"5151c7461586a79a23178305" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"85e9113cb994dddc1fa3a0b4" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"3dae2a2648fc31a8c0f68813" +], +[ +"cte_facts", +"c00c29b0f7cdc26397c61c73" +], +[ +"cte_facts", +"56ba16ccbc1a35ee2d8194f6" +], +[ +"cte_facts", +"d72b1c57ff00d40c2e18baaa" +], +[ +"cte_facts", +"c1a6786c2a7333279329f9ef" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"ec1cf562821f033e0c882b80" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"38a3fce16527519e5a47d4dc" +], +[ +"cte_facts", +"90387527db320fd4530d0d65" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"b6fc91d919272da017c90906" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"89f2d9e16f0b43e53c05fd8d" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"889b6c62ca816f4a80ad650c" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"e90addde127fb134ee41b2a8" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"da73f43053e1e067e3c27d95" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"746963960f2bd5efa4a6c29f" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"cd543ab9b7396d384d83218a" +], +[ +"cte_facts", +"af3195b0c034a44bd2bdd812" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"222d7b52bbdebca10d580a37" +], +[ +"cte_facts", +"474dab40da8cffbe8ebdbd23" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"20e87b1d9005062c36c16b4b" +], +[ +"cte_facts", +"4377bd36fe5c13dfa27b6a62" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"0eaa00d71fed762eeadb364a" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"04bd69854331607540553a09" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"870bae4bb82d707918bfac02" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"74d1eb1fdc6459093b34c2f8" +], +[ +"cte_facts", +"340d1242609a9cc38b705454" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"146bf7bc8cf050902c1c0739" +], +[ +"cte_facts", +"4db4546cf049f2d63cebe9f7" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"2f7b10931a47cce1fad6aca1" +], +[ +"cte_facts", +"3013bf7ed9ce610e158c3e9e" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"f2d2443cac2d1cb73d075191" +], +[ +"cte_facts", +"5e98624071bd40877af25354" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a8fa44034b5eb021bf07ee9e" +], +[ +"cte_facts", +"ae6cc3a921aa9e65f4eeea1d" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"1e4c0ce0c6a71926b53e3185" +], +[ +"cte_facts", +"399fbc7c26192a531216e512" +], +[ +"cte_facts", +"f0ef2b9cb40550c9e8b6f5bf" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"446781fa398ac9ef2b09da0b" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"f3810b404f0c2d48fee96272" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"da73f43053e1e067e3c27d95" +], +[ +"cte_facts", +"331e46e44f675c4402d03ab9" +], +[ +"cte_facts", +"4a1148a10b4ae1a1a2cb4ac4" +], +[ +"cte_facts", +"20eb4d1ed598a393febf0aeb" +], +[ +"cte_facts", +"6a7f99ab3b34b975098ed78d" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"d8d7d9b0b50847f0e16c04a5" +], +[ +"cte_facts", +"3c7c4024333942fa430e93d4" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"31ce05446f06237043d47233" +], +[ +"cte_facts", +"eed09387c738f440df36ea2f" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"7f25145c4f3ba9be42315bd0" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"90387527db320fd4530d0d65" +], +[ +"cte_facts", +"20e87b1d9005062c36c16b4b" +], +[ +"cte_facts", +"4829c1b6749ee3f0daf22aaf" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a15a6c8b36eccf68bd084a71" +], +[ +"cte_facts", +"aa7d182ec04bf5ab611a1e24" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"23902d77fb9b4aaaa3ee1134" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"ecb31e7eb76f1ab840d61a72" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"1aadee58327c359b7f20b9bd" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"ed719fee5997eba94c6c4e82" +], +[ +"cte_facts", +"176236cffb1d1348a8a95a3a" +], +[ +"cte_facts", +"be5c26ec5c61e562e525af2c" +], +[ +"cte_facts", +"03d28eb7ba964b869666b1b8" +], +[ +"cte_facts", +"1a10de1f046cd2e9040ba228" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"6c66d510b5cdd3be11708f29" +], +[ +"cte_facts", +"6c7bfac4d071e2e577cd2047" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"ba8ae129584568609efa8ec3" +], +[ +"cte_facts", +"5e98624071bd40877af25354" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"2fcd2b715aee970b09d1939b" +], +[ +"cte_facts", +"fa12d3dbbd5af3efdd7f0421" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"ab537a44bfdd87c1584026da" +], +[ +"cte_facts", +"0474da9ad560751c44fabff7" +], +[ +"cte_facts", +"6322aaddede94778335eb00a" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"785c80e17f1ac174c0151de1" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"02c20a1ad10b6ffce259f85a" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"f07df18b5f3ced96efc291e0" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7e34cf87ff4348a9640e6ab" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"20e87b1d9005062c36c16b4b" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"d93f5e8f59a3d40112e9332a" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"02c20a1ad10b6ffce259f85a" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"c6b9e7bd79af73a1f216107c" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"da96cac1ebdeced6c3246ae8" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"2990a9e80ac314ca21fae9c8" +], +[ +"cte_facts", +"5486820130e7d072faa3cba9" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"9a99cc03fbf906873ee7e937" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"cacdbaa5df3670bd4f7a9b94" +], +[ +"cte_facts", +"8d828bb774344e50a7735dba" +], +[ +"cte_facts", +"f5b6b22b1d2051b8f8cd0744" +], +[ +"cte_facts", +"0786540577b0ace95d71ad84" +], +[ +"cte_facts", +"32815c8454b772eacab325c4" +], +[ +"cte_facts", +"3ac5ee10f91811f01944d9c7" +], +[ +"cte_facts", +"1e0b5081e91e76f874870f56" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"18b667356bdf7d0a5fc06f4b" +], +[ +"cte_facts", +"27197b5a18a8c3e48f949dd5" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"eeb45e2a9b64af1b8ad097d9" +], +[ +"cte_facts", +"7ee701be385e1ae26d7a2208" +], +[ +"cte_facts", +"6e5df2a4b157c0255f44d28e" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"806b51bc7079e88baf49fe67" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"b9db6b400c08d41ff6ffa8fa" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"52beb074b74156ba426d1a77" +], +[ +"cte_facts", +"8e5638a90799fb743c2841ed" +], +[ +"cte_facts", +"2d26c04a383ddab2aca4e3d7" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"18686fdcdb2615b70dc0360a" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"f26b279b0b41306ae3c96aa0" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"80414a3979b2e356937bb2ed" +], +[ +"cte_facts", +"b83b74a4dc3fff3aa91284e1" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"77ec9ddd6051a57c72242867" +], +[ +"cte_facts", +"c0d665860fe9c17f70942d5a" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"5430136f6bffab1727da3f78" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"c38762f662ff0b7de6e10d92" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"81b6f3fe4406c201014229bb" +], +[ +"cte_facts", +"3211527037b1f7e8b09ce127" +], +[ +"cte_facts", +"be421c74025339379c86ac54" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"e0baa91f7f0662b887678387" +], +[ +"cte_facts", +"ea96e238b5198477bd30504e" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"948432641f53792583d62aec" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"1a0fdfb8298ca9abc215790b" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"bdbd822563b2abbf38be705d" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"4377bd36fe5c13dfa27b6a62" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"5b489acd4f2bfddb195e445c" +], +[ +"cte_facts", +"a764807d918dfed855d0d54b" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"c0e614b9236f852a9a5a4d88" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"38cd134067ce8cec9bcb1eb7" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"e9a10d9ecc404895bc26b290" +], +[ +"cte_facts", +"1a0c9680b7d085f48d59450e" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"1d5dac17fd611343add862c0" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"212945ada13b0575456393b2" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"8f496459bd9aeb74fde77092" +], +[ +"cte_facts", +"3526fc0d243926a1b8d1bfd5" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"2de3863e3e3b27acd68bcd5e" +], +[ +"cte_facts", +"bb28a5d87b552ea2ff02562e" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"968ac983ec3cc08095608953" +], +[ +"cte_facts", +"0ee1c5438cb1674266334a30" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"0365ce77fd80a82b3837efd9" +], +[ +"cte_facts", +"370d84396f619d4bc85b671e" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"df75f39d2709de69b46c11ec" +], +[ +"cte_facts", +"18aa68b661707540d013a1aa" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"632d76e38f512795278acc8b" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"4829c1b6749ee3f0daf22aaf" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"9275c572ad156e1371f0169d" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"5db4de5ded005854ce189217" +], +[ +"cte_facts", +"2de3863e3e3b27acd68bcd5e" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"91f33e1f9226951a42cac62b" +], +[ +"cte_facts", +"e0f8c4648393de6d52e21670" +], +[ +"cte_facts", +"1de27371a7b364734e17aa43" +], +[ +"cte_facts", +"a359414d50c42d0f30c62771" +], +[ +"cte_facts", +"af3195b0c034a44bd2bdd812" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"b54b2784662a41c6abbb7858" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"31ce05446f06237043d47233" +], +[ +"cte_facts", +"10e8544574f2f945ffae2040" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"9fc6df17d8108b864aa710b0" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"1597e324edd3cec6f0027ddf" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"7724aae4d3885eb719cfee48" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"6c8dfce830c9c56286adec9f" +], +[ +"cte_facts", +"4ba0ec0516eeaba347ccd059" +], +[ +"cte_facts", +"1304983664d2978cc4f297a4" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"9b98bcee5e947ab1439259c4" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"8213eaf4cdd52bbed31c0402" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"ff893ebe8b9df3be720d98bc" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"e00d4ad6ac1059ec06a5eabf" +], +[ +"cte_facts", +"83f5cacdeaf0c39078a79c4d" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"fd89f3bc8252382c92432bf1" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"866197cd45179e4e1a259563" +], +[ +"cte_facts", +"f472ed6755ee4e92ac2f5aaa" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"68901ad45a6e183434b39562" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"706d333168ed41aa142cb207" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"d5c66882e640673c5b89219f" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"e5c0431376b17c69ec8bb239" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"931c32179bb339f5390d28ca" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"6811049aa7fc3ccb8d8f7468" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"6f239d1144bd40c7dd17638f" +], +[ +"cte_facts", +"4a6c2ffa2bfcdf5811d032ec" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"3732b652976d866f62ec1395" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"5b95f6ef841799064b011876" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a60af443087f4754cfe8b096" +], +[ +"cte_facts", +"ad844c13aea623cb25525766" +], +[ +"cte_facts", +"a7e34cf87ff4348a9640e6ab" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"8e5962667a116d08801e95a3" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"b9b5d6c8e97490a048652589" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"e00d4ad6ac1059ec06a5eabf" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"2d9bf12e8bdbe1ec265d90fb" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"3fe437233e76b32c82aa4960" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"6edce263e0068e32623d3f8c" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"8c89a24415e398be8b458e02" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"aa9fb5b8c130c6ffb432f3f8" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"38a3fce16527519e5a47d4dc" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"23fac08cfeb334ee50515ae5" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"ee62b965f7f6d45a85b765cd" +], +[ +"cte_facts", +"e239a1686d1f1d9dded75223" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"0113b7ad75eed5d36f3e19d5" +], +[ +"cte_facts", +"1c60aaee0389232e5f392c48" +], +[ +"cte_facts", +"4ff9584900e296755295a004" +], +[ +"cte_facts", +"abea53f46b01bfc5c605892a" +], +[ +"cte_facts", +"785c80e17f1ac174c0151de1" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"81c3da14dd15a3343fa89eed" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"3ba4bdbe76d52b41018f10ec" +], +[ +"cte_facts", +"0ff36f2b49db0e4d671f2617" +], +[ +"cte_facts", +"d80211449eb69949deb46cee" +], +[ +"cte_facts", +"02a5edd85d8890831bbfd64a" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"c922d7e47e445f529ba3a894" +], +[ +"cte_facts", +"bb55a93c577ebd25e50cf25f" +], +[ +"cte_facts", +"938fb882c31bcfddce96019b" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"084bb9024215fc5151ac04fd" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"216a02ac2a8b7aec5b84ca8f" +], +[ +"cte_facts", +"e7adf7cb46b2a63cb95ffcd4" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"9fd5eec71cce4b3955e43c2a" +], +[ +"cte_facts", +"35d41990b57768acc2e64855" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"e83331025b460b5b1db2ac0b" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"5ace86ed3ce43650d084ab56" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"3fe437233e76b32c82aa4960" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"55272ddc4f2bf5ab0526db7e" +], +[ +"cte_facts", +"4267c6ef3c4b0e04fc1f534d" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"98a21fc76f62ca1100f585ec" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"93c7bc68db4521dd0b4d935d" +], +[ +"cte_facts", +"c545264f84e0b84c419023c9" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"e68771101b9d8278e74de199" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"f0200c31632a6ed78fa2ddd8" +], +[ +"cte_facts", +"aa9fb5b8c130c6ffb432f3f8" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"b5b1fa21f92d46934e93cbb7" +], +[ +"cte_facts", +"9b7ebf36f5738ce9d14b448f" +], +[ +"cte_facts", +"ea7d43dc213da833dc086914" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"983ed2a5345d16d2f1e3556c" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"f0e3ef84de102fb2182ea596" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"ed6e7ae60db102a5a8f1e1d7" +], +[ +"cte_facts", +"0e878e41481a463a59693be5" +], +[ +"cte_facts", +"df66bdbfb7145ea9aad66dfe" +], +[ +"cte_facts", +"e77fab1588be25e357c0036e" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"b517878fdf98bdb3a3085de1" +], +[ +"cte_facts", +"0c977422459721fd1319673c" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"af3195b0c034a44bd2bdd812" +], +[ +"cte_facts", +"bb287c4cda57bb19efdf94f8" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"d756bdc130b80ac669a33f5d" +], +[ +"cte_facts", +"7b60be8f794170b6312f29b5" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"2eff63a7a320516bdf597635" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"5e98624071bd40877af25354" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"ffe1dcb3daa1ea5dd9c407f1" +], +[ +"cte_facts", +"e83331025b460b5b1db2ac0b" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a132f30269b1e41a2c2cfbca" +], +[ +"cte_facts", +"931c32179bb339f5390d28ca" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"6147ec54d88cdc185de9b7a0" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"76f8a289edaafe08a4e235d4" +], +[ +"cte_facts", +"eed09387c738f440df36ea2f" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"1cc31e14451491fc4bf9a746" +], +[ +"cte_facts", +"d8394f37537921d46e9af114" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"f82e4c28299beb3fd592ec8c" +], +[ +"cte_facts", +"9b10a032e998f9b508453e2e" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"77ad261f2aef5eff170bd758" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"ebcda82bfc70b8c3cb7d0475" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"4a7fc820c600415923387067" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a5ad95629ef11d8210d6df50" +], +[ +"cte_facts", +"d0136621c65b44dc92cd9efd" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"2b8f2388d8a80fe648053caf" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"eceda2463eb3f0a0331d6627" +], +[ +"cte_facts", +"7f8818c0fcf334491f14c81e" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"57bc33b3034a86ba92ce61bd" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"e94c9b3702d0e8ce57f4e812" +], +[ +"cte_facts", +"7fd4cfa846005c876daa106d" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"f2b8a299663371a16ba027e2" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"76fbde16e5018a3338af1520" +], +[ +"cte_facts", +"1bf89ce635efd55eecca19f3" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"d5f172d538ae498351a18a7a" +], +[ +"cte_facts", +"fffbc2d90b6e24bc27a3cc02" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"e616619423cd5f6eb3bf3f7c" +], +[ +"cte_facts", +"d2d6ac4f84f18280c5d4eb5d" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"154c6e31a55e2eae556491ea" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"49723f40e6844829d36201ae" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"588882179f955f02bdd6fedf" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"5e98624071bd40877af25354" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"1fa2232360e261c0687d0a9f" +], +[ +"cte_facts", +"3fbff07651ac258bb5f10bfe" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"217b0848a62510855d234790" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"001bf04fdeef66eb649c6e68" +], +[ +"cte_facts", +"6c32e27c13d903f4d74d8897" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"f4faaf760631624f1129378c" +], +[ +"cte_facts", +"2de3863e3e3b27acd68bcd5e" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"398f4fcd11ee6485967e9ed4" +], +[ +"cte_facts", +"b13d6eb2ab09475180774632" +], +[ +"cte_facts", +"7a8b69fb197812dc73337580" +], +[ +"cte_facts", +"b47437e9162a4259914cffaf" +], +[ +"cte_facts", +"f14698199fc21fc01014b1ec" +], +[ +"cte_facts", +"ce2d8d18a31c69eef70bc0fc" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"c3dcbee73d9514842426619c" +], +[ +"cte_facts", +"32da4cac10364c5d0461ecca" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"c4608444066c277d37e53df1" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"f760c556f57cc408c0a8525d" +], +[ +"cte_facts", +"ff94ee1b456022577fb27f97" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"641cb2035ef82dc30d26b814" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"fc8c8b97e61a58a1aadd530c" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"446781fa398ac9ef2b09da0b" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"5f9045a269fea413a2c93a7f" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"ebf46095225224a1bc3e1118" +], +[ +"cte_facts", +"dcfd0ec49419a739e22a2681" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"13a41ef62daa4dec695d25de" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"e3d3aa495d85546fd146b823" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"2ef709c135d4c85542b034f2" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"274ae94d765726de2457ba3d" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"c568ba6835c4328c9250871e" +], +[ +"cte_facts", +"9a28b41895aafd1d182f896c" +], +[ +"cte_facts", +"2a1b3b25a2755b6450b21327" +], +[ +"cte_facts", +"63da43ff8f839940bee14689" +], +[ +"cte_facts", +"7b335f85f1a65e16456ad1c1" +], +[ +"cte_facts", +"7f8818c0fcf334491f14c81e" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"c0c9a4341d1bd05389c8202d" +], +[ +"cte_facts", +"ed7a57df04174634583ad8e0" +], +[ +"cte_facts", +"39c207390ec4471a96042576" +], +[ +"cte_facts", +"a96c6210131bf7af2941185c" +], +[ +"cte_facts", +"d4c14ed86311ebc54b9011a9" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"5b1ed9afebdb8d1177b73ebd" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"0801ec3fce3d1a9ec19e5e45" +], +[ +"cte_facts", +"c776bbb8c981fcc825367088" +], +[ +"cte_facts", +"a7e34cf87ff4348a9640e6ab" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"58ddaad738c5c6a4c191e0d3" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"d5e45e06c322f90ee64b9ae2" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"8213eaf4cdd52bbed31c0402" +], +[ +"cte_facts", +"76fbde16e5018a3338af1520" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"424da9db08cfafb2ed58b48c" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"bf68c26218e4157f705ac5d6" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a6cbd84661cdd47b0319aa47" +], +[ +"cte_facts", +"6c8c882a31428b4daa8e1416" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"debb55071d52e6821ff94dbe" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"0304237baca7bf7d3c9b9160" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"562f8cb13dc7c0a591c241df" +], +[ +"cte_facts", +"5d8f7967acfd60307ded961c" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"dd6f0d2cba110b0f4fc07030" +], +[ +"cte_facts", +"151bb12e03386bade0488e59" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"d671dd1568bb33cacba18fe3" +], +[ +"cte_facts", +"0a0319cce89ec0ea67e430d5" +], +[ +"cte_facts", +"07366cdce02e55b0f4364c50" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"f74757ac819f89ce2a6edaf5" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"110ec58e72dc9f157b48ec24" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"6345ed5392a8ffcd509b9885" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"06ef714b8645fe110ef354e5" +], +[ +"cte_facts", +"3b380fdf718163633c80ab04" +], +[ +"cte_facts", +"b7a00046e5722e993b5b0e35" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"03f7e8f3f607b1729449e074" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"1e0b5081e91e76f874870f56" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"38f4b4ac40110dd5d6c43ac3" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"43affe2cabc459f8f2d5fe8c" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"e5c0431376b17c69ec8bb239" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"5925fee334e58d657b2b9aef" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"bc0564bea4769ff15698b1e9" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"846f6db9b87dda404b0c1d38" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"7e3e7cde138fff723be84030" +], +[ +"cte_facts", +"adeb378c7dadf8f8e7c78de8" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"78ccb60eb824aca93eea5952" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"ed14a02df491908326c36a0e" +], +[ +"cte_facts", +"80eddcee4f7d6d50d429f095" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"1b7be1486c7c5f5519df1ad9" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"376039d137b0dfc3d958138b" +], +[ +"cte_facts", +"728cf1cae2e80446a669cf4b" +], +[ +"cte_facts", +"a9c7c5354062238c0d6f2471" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"3e1e55395e14d623d40e6c06" +], +[ +"cte_facts", +"78d19eb5074452cf596ae63a" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a76b45855ec0e590e431bd25" +], +[ +"cte_facts", +"67f73487af6cd1ee11fbbff3" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"9b97e6bd2b57b4b3f232d675" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"850302e48dad146a3ae20ce9" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"317e800ef36eb8b5b4dce5bb" +], +[ +"cte_facts", +"411a4ff3c72a2d03bf69579f" +], +[ +"cte_facts", +"a5c5a86e776178782820b709" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"9c3e1cd177ced343021acdab" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a510edd83e6b1105b5d51f9a" +], +[ +"cte_facts", +"45aa53c7771fd78ab16e069c" +], +[ +"cte_facts", +"975661bbfd7197055870311d" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"b9db6b400c08d41ff6ffa8fa" +], +[ +"cte_facts", +"54d072cbee2e7a4fba46edce" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"49d45df284d296a56ee65e4a" +], +[ +"cte_facts", +"ef309f48e3ec31f900a089ae" +], +[ +"cte_facts", +"06ef714b8645fe110ef354e5" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"85932829e1eba29f55f85fa1" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"d4bf62c734315405890a719c" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"5925fee334e58d657b2b9aef" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"3c7c4024333942fa430e93d4" +], +[ +"cte_facts", +"2fcd2b715aee970b09d1939b" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"176236cffb1d1348a8a95a3a" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"1950f85d661f38d00a43a072" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"709313942a21ac3635ddebef" +], +[ +"cte_facts", +"522dc172f9dee3ff63e77523" +], +[ +"cte_facts", +"304123802323a41033dc1109" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"79ee6c9aa5f6c5464f47eaf5" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"0e0c22543052bcba25c24ee8" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"42c5894e3fac7417bafdb06f" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"d25d576e8c29384d6e3a951b" +], +[ +"cte_facts", +"282e58a5cab310f65dc89256" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"b30b3a5b8206262570b2279f" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"b8ab4d3fb1d826e488cd167c" +], +[ +"cte_facts", +"40e0586d9cb8dc767730f329" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"3c7c4024333942fa430e93d4" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"adc7bf939011845b2892a089" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"e41164db8ce57be3c32429cb" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"785c80e17f1ac174c0151de1" +], +[ +"cte_facts", +"ca056830e31331e3ff379150" +], +[ +"cte_facts", +"0e878e41481a463a59693be5" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"ece79de0c40038457c065b8d" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"02c20a1ad10b6ffce259f85a" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"bb59180ccec9e3f77871df73" +], +[ +"cte_facts", +"eed09387c738f440df36ea2f" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"edc5dc5be882183f5e9a6627" +], +[ +"cte_facts", +"a9d09f68525851448df1619d" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"d11e73177a45c2003416219a" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"80607bae97f5cab985a0add2" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"fa5292e62800a8b353f52ffb" +], +[ +"cte_facts", +"79ef7772d1f5797b348e8b43" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"0fcd016def2c6a87bd549112" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"3c733fbd97f11c1ae39ee072" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"c0ddac7e337047910d4af364" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"fca2e9545f438f2926e0956a" +], +[ +"cte_facts", +"6a367d1121b68654c9b81b8f" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"28517cfe8279da271d002c07" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"8f70825238c1aed0ef3c5734" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"19cbe6cae615b8225b4d1911" +], +[ +"cte_facts", +"998e0045327d41c7ce1c7fc2" +], +[ +"cte_facts", +"3853a58d03252066f405f1b7" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"9985655040a4cc43bcf546ab" +], +[ +"cte_facts", +"ca986628c7bc0136a33f2e8b" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"b8b59942cb1ea5085385db68" +], +[ +"cte_facts", +"4491c04a3ad474c8909c281a" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"f1477a690868e13f2bb9eb6e" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"617cda2ff1739604ce791140" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"370d84396f619d4bc85b671e" +], +[ +"cte_facts", +"de84f9b1f0d7f195a575ec17" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"6bf16ad094d49e4ff755aaa5" +], +[ +"cte_facts", +"0fcd016def2c6a87bd549112" +], +[ +"cte_facts", +"77f2eda17db6070726ecd3e8" +], +[ +"cte_facts", +"09c76537f00d6996193e4023" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"866c00a7464f747e4fc1a355" +], +[ +"cte_facts", +"f718dd96e91014fd7962bda5" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"652c0d0472b4a3a0f3893a4a" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"79c3fbfd20423f5f440db2f6" +], +[ +"cte_facts", +"7df2768aaf03df896e6c8294" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"71e612beaa6828ce304a8265" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7e34cf87ff4348a9640e6ab" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"39857f46f51874c34b627875" +], +[ +"cte_facts", +"304123802323a41033dc1109" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"dc38281fff03583f84500a85" +], +[ +"cte_facts", +"7cd5968bd2431af05f1bb764" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"92813c0cf1f3a3e54ede7bea" +], +[ +"cte_facts", +"75c3670efc226426287b4420" +], +[ +"cte_facts", +"9c2fdc6b3cc80466ffe530e6" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"b12b8f8d5bf1fe6b9b4e1d88" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"17bd4ac3f3b32158337513f4" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"db82ebef83acd2dba14fa0bb" +], +[ +"cte_facts", +"c88e2c848da46750a3e10090" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"4017732f4172dc299af21bf9" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"c8e8c3407ac5fa66155815df" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"411a4ff3c72a2d03bf69579f" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"02c20a1ad10b6ffce259f85a" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"f44562e2016b7337866b3ef1" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"00523d6cc539a1a45f58e449" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"c0100d022bf48772483a6a15" +], +[ +"cte_facts", +"a3efb9ef0986176c3b09dfcc" +], +[ +"cte_facts", +"8507cf1c529a106f2e13fffe" +], +[ +"cte_facts", +"22ff3cc6b2af9a9ca87ca53d" +], +[ +"cte_facts", +"da73f43053e1e067e3c27d95" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"2332482f0d5470c46bfd4320" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"f14aeb66f78e1e1c707427a9" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"3ed17b7fa9332ade3e4213cb" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"45700208396b1cc8351ee18f" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"882da20a3b2430bec6b02456" +], +[ +"cte_facts", +"4137400d4873c2f19e62d629" +], +[ +"cte_facts", +"5c61a4fa431cdc1b6096de56" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"f61223afe8f99d968451e5e9" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"d0f30baa34da1a1897488afa" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"38a3fce16527519e5a47d4dc" +], +[ +"cte_facts", +"b1732c1ea755b9cde57997c8" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"60fab6cc07969ac9351ddd38" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"198721712d2f8ef86f7e7fda" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"20e87b1d9005062c36c16b4b" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"f6909d24c4f7453b984e0847" +], +[ +"cte_facts", +"6919dea74d6ef4c9952c4629" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"3bd45518b09712347a2ef45c" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"80651e94f0605a416f252251" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"2572be21f7b70b9003611f53" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"2ee7dac611a2ef598b6cb05c" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"34e8f5e18a0953c970faed46" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"e00d4ad6ac1059ec06a5eabf" +], +[ +"cte_facts", +"f9385aed33447ee5749935f6" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"176236cffb1d1348a8a95a3a" +], +[ +"cte_facts", +"22b7dad8df2a84eae1fa80ce" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"0d7acbcef647c47fd41868cd" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"cf56d985716a981f1117d243" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"06747f8f125a6f8f60beccd5" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"4f5c613de86bf7ba685e1b38" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a186e62463a75d56fa99a168" +], +[ +"cte_facts", +"3572a77a1b6c5d56b6d4c0a2" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"411a4ff3c72a2d03bf69579f" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"f44562e2016b7337866b3ef1" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"f5b6b22b1d2051b8f8cd0744" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"4e20b482b2ca8381e7722dde" +], +[ +"cte_facts", +"9d234bb409046114d928a3e7" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"167cae4760889d1a7b691444" +], +[ +"cte_facts", +"2b48a26a0968f24175be90da" +], +[ +"cte_facts", +"91847bbf302640893ce7091e" +], +[ +"cte_facts", +"15396ac51ec2a87b7975b2ee" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"b062cad1c498245f389680c1" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7e34cf87ff4348a9640e6ab" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"6acb5d46486abbd86d07a32c" +], +[ +"cte_facts", +"837fded28e2525151065e19a" +], +[ +"cte_facts", +"0f7737b7a085356138660a00" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"18f165bb966172cd19eb3778" +], +[ +"cte_facts", +"370d84396f619d4bc85b671e" +], +[ +"cte_facts", +"7c6bcd67b4bd5b7206a081a1" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"6a722e7515ebbc0b544e0d61" +], +[ +"cte_facts", +"3fb71d1a8bebc35dc1f86037" +], +[ +"cte_facts", +"3f139d2b797bcafcb656f602" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"094711ab815a9f9abb2cef04" +], +[ +"cte_facts", +"5430136f6bffab1727da3f78" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"c6589cffd6b1797e0f3cee11" +], +[ +"cte_facts", +"52c1bab5e329e40ca8063b3c" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"df75f39d2709de69b46c11ec" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"2ecfe5fe67d5eb423bdb20a7" +], +[ +"cte_facts", +"0f6959e2f022a11fb32e924b" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"c3a69d2114f4559690cd99c0" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"41dfcb3ed1ab08f365780741" +], +[ +"cte_facts", +"eed09387c738f440df36ea2f" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"86c1fc030301d50a25902f1a" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"3c42a804678d240d555de69a" +], +[ +"cte_facts", +"40ff1d40e1c275b97610c47e" +], +[ +"cte_facts", +"934209e73aef79ef60ea8520" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"d756bdc130b80ac669a33f5d" +], +[ +"cte_facts", +"af42f471da9339f89a57c51c" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"51aa4ca0bdb7122fcf5b1715" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"f32994d63a63eb3412200e37" +], +[ +"cte_facts", +"7b4ccafa93b90812e60756a4" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"3f13ff71cb4f7715d34a734a" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"4cbf182f05bad1387d70beb0" +], +[ +"cte_facts", +"90a6b973affaf7794e8c4f36" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"482239c9930c7cf20692a4f2" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"c620f3eeda4d73be333a395c" +], +[ +"cte_facts", +"5b750c06c17c5daeb14c197b" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"3f2fb8522e8878a3b1475097" +], +[ +"cte_facts", +"a062ba15f5478b4307d16fff" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"8a87961dd00f7d91b9d4903f" +], +[ +"cte_facts", +"176236cffb1d1348a8a95a3a" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"6a0d23ddf3acd4eb8690adc1" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"42320d623165cc351e15e022" +], +[ +"cte_facts", +"5aa160dbc9b6f9229c08eee4" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"724b0a1e76206495b83adad1" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"e11249b1be1dfcf4994830e3" +], +[ +"cte_facts", +"105520f8ba54d96da7805226" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"ece6d02b7c31182b588e0e9c" +], +[ +"cte_facts", +"b450c7e0522841b10504c038" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"6590a6a60dd0c4088715e55f" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"5476567567fe27022c69294d" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"f0c0806da842233f660f5b23" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"45600a76b057f3bc8d7aa623" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a72c743c7c2bae036ed3fdd5" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"b1876c9a7d136ec05b20875d" +], +[ +"cte_facts", +"cb1e3c176eaff984ca80e2a0" +], +[ +"cte_facts", +"27f1ee0b6b0b8de1cf296f8b" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"d756bdc130b80ac669a33f5d" +], +[ +"cte_facts", +"20e87b1d9005062c36c16b4b" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"2e1d5902a5a38aced28f0ac2" +], +[ +"cte_facts", +"649fc2938efd41829c6718b9" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"4723ea834d37c8c25e26490d" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"52c7ecf5d0e95a86e0777083" +], +[ +"cte_facts", +"57356413266917a0e7f9b859" +], +[ +"cte_facts", +"a35b720bbd7c384685d84ab8" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"dbe31d25e4ff467fb8099b7e" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"717f9807521044ccd494c02b" +], +[ +"cte_facts", +"44c669d3aae250d5b9951a33" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"82abceeb231f4799e7f41964" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"1dec64953bee4bdce4b97fe3" +], +[ +"cte_facts", +"b610899b0bee8217d42ad037" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"f69d3f9b13b8fdfb1632a79a" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"f65d89afc9299f5382043cca" +], +[ +"cte_facts", +"e00d4ad6ac1059ec06a5eabf" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"370d84396f619d4bc85b671e" +], +[ +"cte_facts", +"7e8f4301e581327def7a580c" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"749b1c663334dc30a879d996" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"c2ef1a1274c86ef5a5488140" +], +[ +"cte_facts", +"4645d690fc914eee6ae7d048" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a0c84be8f7df1fa0f886f33e" +], +[ +"cte_facts", +"2fe95bcd33db9c87de6f84ac" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"5925fee334e58d657b2b9aef" +], +[ +"cte_facts", +"5430136f6bffab1727da3f78" +], +[ +"cte_facts", +"b72b6640cb67f64a3783938e" +], +[ +"cte_facts", +"f718dd96e91014fd7962bda5" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"b40a9896c881b9b1e938bd0c" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"bdbab1d9d0daed776a52f047" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"b9db6b400c08d41ff6ffa8fa" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"eed09387c738f440df36ea2f" +], +[ +"cte_facts", +"e00d4ad6ac1059ec06a5eabf" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"cc5655212a098199b71e7449" +], +[ +"cte_facts", +"df75f39d2709de69b46c11ec" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"983ed2a5345d16d2f1e3556c" +], +[ +"cte_facts", +"6d155123816cd5295ad9d571" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"757a1f33485495f0e52ad63c" +], +[ +"cte_facts", +"f6b1021085276b102cfce8af" +], +[ +"cte_facts", +"92a174cbcd73b25dd952e30d" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"3fe437233e76b32c82aa4960" +], +[ +"cte_facts", +"9dea54f35af551f8c6ee5968" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"6322aaddede94778335eb00a" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"555ffa18ace28a83825157c9" +], +[ +"cte_facts", +"5151c7461586a79a23178305" +], +[ +"cte_facts", +"fccb554a9c592d0fadee0346" +], +[ +"cte_facts", +"e5c0431376b17c69ec8bb239" +], +[ +"cte_facts", +"20b6d78991ebd21f46f723fe" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"68a7603c70c03fcd659a0611" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"6dd3532c9e14bc53690ae9c9" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"bdcd0ea2bb1049b7505a5ece" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"6d5deb36bdc1757d495e495d" +], +[ +"cte_facts", +"eb48fafd626c55af4b87bd06" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"1e176ee352799421a8143b4d" +], +[ +"cte_facts", +"2be2584746d3dac4c3889c23" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a3c892e417a8e2434de6cc55" +], +[ +"cte_facts", +"45600a76b057f3bc8d7aa623" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"0008a33cdc496fb5d9ca058d" +], +[ +"cte_facts", +"e00d4ad6ac1059ec06a5eabf" +], +[ +"cte_facts", +"6a0d23ddf3acd4eb8690adc1" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"28087d08814f48b361b6de28" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"c8618e68970fbaae78ffd442" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"c7720fc8f445f61bcb6ac336" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"f6e05c8fa07d9c5010df7ec9" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"67f73487af6cd1ee11fbbff3" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"efff1da58173ea8714b21c43" +], +[ +"cte_facts", +"6fbf0d34cf84c348aeb42ed4" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"4d04d887fd5749253bfdccc9" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"0a954bba38ae2080b88d6921" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"1dc7242a51ed6594b30fdc78" +], +[ +"cte_facts", +"efa1946f3d8f60be2b34c8fc" +], +[ +"cte_facts", +"a7a9d8c38fffa45e3b0d783f" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"b7b004bd7635995d8e178b8d" +], +[ +"cte_facts", +"230187b1abce8a1b559f84c7" +], +[ +"cte_facts", +"2e8bfc93f583fb4c66145e1a" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"411a4ff3c72a2d03bf69579f" +], +[ +"cte_facts", +"3fe437233e76b32c82aa4960" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"2b6ec43a6adb05e1070a1a67" +], +[ +"cte_facts", +"8213eaf4cdd52bbed31c0402" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"ff81d2718a9358e6d11a7d17" +], +[ +"cte_facts", +"7c388fd67abc2f7ecacdf320" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"df75f39d2709de69b46c11ec" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"31ce05446f06237043d47233" +], +[ +"cte_facts", +"417e56016d81d2a2b9e54978" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"9814f167c5e690ff5393c592" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"7c0a20dbdfe9c498722ece6c" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"e0433020deea53816ed5d589" +], +[ +"cte_facts", +"10dd65ded5d2a613d7e76869" +], +[ +"cte_facts", +"7d08e8cc7252a21881b0a06a" +], +[ +"cte_facts", +"884ef8337bb248e6a85d0323" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"5fda458df92dcb35646f7c1e" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"7cdf221d2716922f37239061" +], +[ +"cte_facts", +"af3195b0c034a44bd2bdd812" +], +[ +"cte_facts", +"2551f80846c76cb4ebc6ee59" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"dc5b9a03ad06b0e83d3850ae" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a2bf0ba96f291766da4b8231" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"33067b71e6d313793b357817" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"c454ed3c77155f7e0ffea0e0" +], +[ +"cte_facts", +"30eb40553c58070860089625" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"f5b6b22b1d2051b8f8cd0744" +], +[ +"cte_facts", +"4d2ac2ea950a76c76d323aa2" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"18e92e7285d57a10ffedff53" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"934209e73aef79ef60ea8520" +], +[ +"cte_facts", +"10939e2c68c391793bc15845" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"1d630bc706f2b85b48524f89" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"283a220696a9ea82e6aa2bf3" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"55661e8c9a1cb90749113cb6" +], +[ +"cte_facts", +"a4bf342d0c9e6b5cd745b698" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"1adb2f87f940f4c5fd062ec7" +], +[ +"cte_facts", +"5ccd07c548e45a47210b7eab" +], +[ +"cte_facts", +"5925fee334e58d657b2b9aef" +], +[ +"cte_facts", +"f4faaf760631624f1129378c" +], +[ +"cte_facts", +"29f51d8d2d25b4cf4a10192c" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"fa8c09959f2b4abb8fc39d75" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"aa9fb5b8c130c6ffb432f3f8" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"45bde05dfa3b204fb9c3c267" +], +[ +"cte_facts", +"968ac983ec3cc08095608953" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"c2978b1d68f26c464a33be3f" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"d6fe3bb05b1e42103ec84689" +], +[ +"cte_facts", +"ce1fda3f641433a4a8a20fec" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"9ee1c182c8ce3fa5d197571f" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"5925fee334e58d657b2b9aef" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"decf92afee5279adb4e9baf2" +], +[ +"cte_facts", +"1b4d494122e075d8b4aa86ca" +], +[ +"cte_facts", +"b62fe8bcefa2fae4625b239e" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"12669194c8d2fa9b4830aab4" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"d81e5a2a7c847b1d584deb76" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"d873d767a5240e8320a9f3c1" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"98997267dc7829329c88863a" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"04ec651262cc8a34f8da48d2" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"0007f8aed5dac22287f82f14" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"4905c2d2e2cfda3f3cd3de86" +], +[ +"cte_facts", +"6883af43657eead1388ea976" +], +[ +"cte_facts", +"0178c92bc3e95130d8325935" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"49609676b34689ddbe6c8808" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"da08b72d11b0a80a8495de2f" +], +[ +"cte_facts", +"51a24379b83c83a2e69994fc" +], +[ +"cte_facts", +"67c08c0d73340f1f782a02ac" +], +[ +"cte_facts", +"968ac983ec3cc08095608953" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"67f73487af6cd1ee11fbbff3" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"e4ee03c96282047db6c36058" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"e7de0bf2dccfa04e1e958140" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"2222724cc55247891ba41d85" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"b71001a6ec20631f3665dc45" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"b1a6056040f2c34e6b3f1f7f" +], +[ +"cte_facts", +"32210938ba6d3e75a6aceb8e" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"47703e9840821a5ebfa8d277" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"3272c956ea97dcdfbbbab306" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"da08b72d11b0a80a8495de2f" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"1feaf21815c57c30beebd634" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"968ac983ec3cc08095608953" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"7f8818c0fcf334491f14c81e" +], +[ +"cte_facts", +"6322aaddede94778335eb00a" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"2ce8d910c48b794c490efb74" +], +[ +"cte_facts", +"da8d9d78a475d9d818df1693" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"7ca804955997d73ca6f3fb2f" +], +[ +"cte_facts", +"1d165c3bda32e7efa4df9d2d" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"46b4b6d25d42544f2e7bf6ae" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"290c1ea2572e98dc857570bb" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"31b39c205d3312db2725ba07" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"304123802323a41033dc1109" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"3aaeb75fc3b1cef6572146b1" +], +[ +"cte_facts", +"f9ba2c1daedeb60ad9376773" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"46b4b6d25d42544f2e7bf6ae" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"4377bd36fe5c13dfa27b6a62" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"037d6ccdd1fcea617040ed61" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"55aa6edc7136de96533893b8" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"b4498848a12664c38a13bf96" +], +[ +"cte_facts", +"ed1e41d85d2509124c7b456b" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"df75f39d2709de69b46c11ec" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"ca6551b0fec7e33588062815" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"f95a77a0e7de4f31d0137f99" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"963f959d14589a1a8f2c87b5" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"d140395495d0968003787b7d" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7e34cf87ff4348a9640e6ab" +], +[ +"cte_facts", +"4267c6ef3c4b0e04fc1f534d" +], +[ +"cte_facts", +"eed09387c738f440df36ea2f" +], +[ +"cte_facts", +"016ec924ccc4489fe8878cda" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"b975abf2d08ab0b0205feb69" +], +[ +"cte_facts", +"3fe1087dfdb455dde4653246" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"e83331025b460b5b1db2ac0b" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"10b859f1a678eec1c34a0cc5" +], +[ +"cte_facts", +"3cb41141daa9ddd0d74f3729" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7e34cf87ff4348a9640e6ab" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"418e76271ad967ca78780e1e" +], +[ +"cte_facts", +"da39cb61a8156b9d35e40ff8" +], +[ +"cte_facts", +"51e237dd90a604a3b3f3aa19" +], +[ +"cte_facts", +"8500a483f8df24f38c8c23d2" +], +[ +"cte_facts", +"5925fee334e58d657b2b9aef" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"81624485f5514e17f503f5c3" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"b196d92b38e52754a254a1b1" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"e5d0be0066c79e2eec970fd7" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"5917fcd7440f8573b4ab68ca" +], +[ +"cte_facts", +"040a05a204cc7cbc4bd535b8" +], +[ +"cte_facts", +"5925fee334e58d657b2b9aef" +], +[ +"cte_facts", +"3f5a1a74656e9d7762bf1362" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"f253b49d79c557c338e6307e" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a38235e266f041741142a40d" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"00523d6cc539a1a45f58e449" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"2a0fb1c4f88fbf544e9183de" +], +[ +"cte_facts", +"5bc37cccece14cde52342bc6" +], +[ +"cte_facts", +"7e0536f9e5b2b98d26a56e04" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"4953cb13b3d9baeefe2615a1" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"968ac983ec3cc08095608953" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"be4c9788dc924b3100840d0f" +], +[ +"cte_facts", +"249f7e5f71a39006f3c14a72" +], +[ +"cte_facts", +"acc36cd08c12fa39661bea65" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"82cd724e966b57061496224e" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"411a4ff3c72a2d03bf69579f" +], +[ +"cte_facts", +"decf92afee5279adb4e9baf2" +], +[ +"cte_facts", +"088c7ce81d5775c768596f66" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"ec25592a7d409e081b6b784c" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"c3a69d2114f4559690cd99c0" +], +[ +"cte_facts", +"e5c0431376b17c69ec8bb239" +], +[ +"cte_facts", +"eed09387c738f440df36ea2f" +], +[ +"cte_facts", +"446781fa398ac9ef2b09da0b" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"785c80e17f1ac174c0151de1" +], +[ +"cte_facts", +"b3d9fdd96920c3c9ef12c652" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"969be68816a2bf237912467d" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"7fce065b3e64611d802cf333" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"c701bbcd7815869a9a8594d0" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"3fcdaa38c3809a7d32a1bd2b" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"53d5f34211bf506d07b1f2eb" +], +[ +"cte_facts", +"f852138658c425bd9a006b1a" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"ba4713328c180e6ad5d2407a" +], +[ +"cte_facts", +"474a269e5f95b8ea76d81ca5" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"dc08d1c4bf866bf308b3fa98" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"b39cfe621a79645d55a4771d" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a9df1451df001f07290aa075" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"dc08d1c4bf866bf308b3fa98" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"53c504b91c72b3153ddd59ad" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"66b45459fb385666c9ff99e0" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"95f07e40c09dfade0e42f5f9" +], +[ +"cte_facts", +"46b4b6d25d42544f2e7bf6ae" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"1ae691e5459e8fb2d011da84" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"e19909d2d575ac3a9a125712" +], +[ +"cte_facts", +"c8e192f83a60d696d37209fc" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"e1c48991009118f93f7baf3b" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"4267c6ef3c4b0e04fc1f534d" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"383b4dda57032b52cb30c912" +], +[ +"cte_facts", +"5430136f6bffab1727da3f78" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"2993f996e60f7066a938f79e" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"d8265cc727a41d136697ac89" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"2878549a7d60ce3431c19f45" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"2b6ec43a6adb05e1070a1a67" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"0e878e41481a463a59693be5" +], +[ +"cte_facts", +"cb9f05ef54d8018793a75f56" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"ff839717362d149880c0fb24" +], +[ +"cte_facts", +"251da44f07a6718b8b46dc5c" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"41170c7e7f50b26cd532e977" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"983ed2a5345d16d2f1e3556c" +], +[ +"cte_facts", +"4b0b4c079d65284cbf57769e" +], +[ +"cte_facts", +"a7e34cf87ff4348a9640e6ab" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"67f73487af6cd1ee11fbbff3" +], +[ +"cte_facts", +"eb56f580419df376b3679abb" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"f62a7b127ec0ec8d98a625c5" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"324799a36510203a6f2c6af3" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"c2ef1a1274c86ef5a5488140" +], +[ +"cte_facts", +"f3db0ea9dc43c0c11f041a43" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"151bb12e03386bade0488e59" +], +[ +"cte_facts", +"5430136f6bffab1727da3f78" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"91b036bb4d0c755410bb7dce" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a158d664e26aef086fdd9a38" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"f32798d859a5c7979ecba6d6" +], +[ +"cte_facts", +"b21a415513d11154cd105b61" +], +[ +"cte_facts", +"3732b652976d866f62ec1395" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a217e4c6047b1b194a54ed72" +], +[ +"cte_facts", +"c8fc0cb813f1bd1a3b12468a" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"8e842a0c0b1a5901617d182f" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"2457ecd54476f010c09ca4ab" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"eed09387c738f440df36ea2f" +], +[ +"cte_facts", +"717f9807521044ccd494c02b" +], +[ +"cte_facts", +"5151c7461586a79a23178305" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"7b5e9f6e6f5ec8ec244738e6" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"882da20a3b2430bec6b02456" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"c243e31a2befa203a6154650" +], +[ +"cte_facts", +"c2f38e187b15ec634a125aad" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a00bc1aea089f5badf154464" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"4807fe43c31af8238626fe39" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"683338c7522beb9c05a72612" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"21f4e89cc35d9e8b7f3bfe63" +], +[ +"cte_facts", +"e00d4ad6ac1059ec06a5eabf" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"3274f33301a6a3c97000363f" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"7df2768aaf03df896e6c8294" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"3703fddae1b50fc130eafd01" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"f0640e958bba25c48aad0984" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"411a4ff3c72a2d03bf69579f" +], +[ +"cte_facts", +"17ee5b26084855e33f69240c" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"3fe437233e76b32c82aa4960" +], +[ +"cte_facts", +"ea7d43dc213da833dc086914" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"f31f9eca9b04d25eff8b5df1" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"243fd67a323d23e67fd3db2b" +], +[ +"cte_facts", +"fadc71852c5c0ab7b5169281" +], +[ +"cte_facts", +"26481ce75c005203b1413d01" +], +[ +"cte_facts", +"7a596b24bb047c6e03732ed5" +], +[ +"cte_facts", +"db05336e2f04f398af8bff82" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"df75f39d2709de69b46c11ec" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a6bb709b6e4d2e86603784c4" +], +[ +"cte_facts", +"4c16e56339db6dd62df77424" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"1d0aefb742d3cc3ccdf41167" +], +[ +"cte_facts", +"d0c2eac7fb0bea36376d8aca" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"e57fa2019527d5da7b74ec9d" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a748c19ed802f3646685c6cd" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"07c7150255f0fcaf9dc5fd4e" +], +[ +"cte_facts", +"fbdc8fece530908241600a61" +], +[ +"cte_facts", +"71be1b331269611775b39569" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"e00d4ad6ac1059ec06a5eabf" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"ad7975b1c11568771ba44d1f" +], +[ +"cte_facts", +"197a57c57abf0ce6d8117ae4" +], +[ +"cte_facts", +"2ac93f229c5c55a83a2d4e1e" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"55272ddc4f2bf5ab0526db7e" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"38de0f2076daf1d1cdf8ca12" +], +[ +"cte_facts", +"99962340aae102b749214f5b" +], +[ +"cte_facts", +"c9e03f7293c494b468ea3a84" +], +[ +"cte_facts", +"ddc453c4206a43050d3b6049" +], +[ +"cte_facts", +"d11e73177a45c2003416219a" +], +[ +"cte_facts", +"fd8b37a35f3e2c74c92576d8" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"2b48327eac2857de28723a8b" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a1790d109eb9cc7ac8442c6b" +], +[ +"cte_facts", +"aff94128a9a6a9d58ea8c9d3" +], +[ +"cte_facts", +"02c20a1ad10b6ffce259f85a" +], +[ +"cte_facts", +"4829c1b6749ee3f0daf22aaf" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"deeceb5570e18756f333224c" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"285a14299a30379b36f18e59" +], +[ +"cte_facts", +"7ea5b68fca19d8e61031fdd4" +], +[ +"cte_facts", +"6acb5d46486abbd86d07a32c" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"5151c7461586a79a23178305" +], +[ +"cte_facts", +"5e40ec0e62c3718d4caa7b27" +], +[ +"cte_facts", +"446781fa398ac9ef2b09da0b" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"f94231934a8c3e86f70abd3d" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"5818c802e60b73c5a7eb5777" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"82091a3a728cc1417e3e5ae3" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"ea6861c3d537c45e738b2efa" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"d05000ea3b06a6932c017289" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"84ea798721e6c47aeb14f586" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"9a6252d8bd4fc1316ccaab48" +], +[ +"cte_facts", +"2dd3f3a5cfebb64437827eac" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a69d279fffaa9ae58a8addbb" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"ce3293dc971e498033109aff" +], +[ +"cte_facts", +"9814f167c5e690ff5393c592" +], +[ +"cte_facts", +"975661bbfd7197055870311d" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"95ca4e21e5a247437ebbddd2" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"07c7150255f0fcaf9dc5fd4e" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"5ac96140ae9c682b95d52c2c" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"76591a1a1f8a63dca0278c50" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"6a0d23ddf3acd4eb8690adc1" +], +[ +"cte_facts", +"68ca358ec525a5ffb3c4cd35" +], +[ +"cte_facts", +"ea42d50b24e83414e92ca8a7" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"4db4ac00559e311fab7826c9" +], +[ +"cte_facts", +"f44562e2016b7337866b3ef1" +], +[ +"cte_facts", +"62309c4535558a08999e41d7" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"25f08f5c7c074952b086c536" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"879e8fa5ec50584af1c5ef12" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"f5b6b22b1d2051b8f8cd0744" +], +[ +"cte_facts", +"c8d747bb19cb77e6ffda9003" +], +[ +"cte_facts", +"af3e2f1452177aa202453ffe" +], +[ +"cte_facts", +"3379a101945f58072771f412" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"20e87b1d9005062c36c16b4b" +], +[ +"cte_facts", +"72e789c2a0764633c8f1e636" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"76b78e9fbe01664ac682d010" +], +[ +"cte_facts", +"fe330670ca51793280992f7d" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"8ca61dedd06208f13b0e129e" +], +[ +"cte_facts", +"537f955a1bdf530fef4d39c9" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"cbb025e2b4148912c45027b1" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"436b014b14265d8019841d73" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"970ab5a29b026b200a202a7e" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"decf92afee5279adb4e9baf2" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a9bd0e3ae152fc636e8ef5af" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"0271725c92598880b265f021" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"98669ad166dbfc3dfbe09e2f" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"da2c7ec20946232109d43b7d" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"20e87b1d9005062c36c16b4b" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"9ca4644f22b8c74ee3797803" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"7834d8a101237abd8f35634b" +], +[ +"cte_facts", +"983ed2a5345d16d2f1e3556c" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"612d5180f2d9e383994af37a" +], +[ +"cte_facts", +"5bc3260ed7f963f7a4694635" +], +[ +"cte_facts", +"b5e27d6d5aee44223428a6be" +], +[ +"cte_facts", +"a20c63c9a459df679beec7b7" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"7c156b40c6ac7f1176e795d6" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"c2ef1a1274c86ef5a5488140" +], +[ +"cte_facts", +"d66b6d0428a6f95d8318c53a" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"2942869bb9e3f82842befdcf" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"0e878e41481a463a59693be5" +], +[ +"cte_facts", +"4ee2a5c08d13528a237d7b53" +], +[ +"cte_facts", +"73d16bf6421a7e278ce66baa" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"fce25a5297f52605b9efe6d7" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"32352f8b74230942bbc5bb4c" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"8ca61dedd06208f13b0e129e" +], +[ +"cte_facts", +"cbafa1982d2fabe42cab90bc" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"df75f39d2709de69b46c11ec" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"0207c19e8f59719855a52afd" +], +[ +"cte_facts", +"decf92afee5279adb4e9baf2" +], +[ +"cte_facts", +"fdbaa125d44c45819eccd00b" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"9b2b965b7876af21160f7287" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"20b9f444a1efbd5329c078db" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"c60a8e5fd02b52099cfe02d0" +], +[ +"cte_facts", +"18c6ccce22456faf6e6481b0" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a15a6c8b36eccf68bd084a71" +], +[ +"cte_facts", +"2ddd610b20ffdb4fb6b23729" +], +[ +"cte_facts", +"9bdfc40f10bdfcde4358032b" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"411a4ff3c72a2d03bf69579f" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"310686d1164e8e4c36b2a716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"e616619423cd5f6eb3bf3f7c" +], +[ +"cte_facts", +"20e56d455ffb35f8a4fc392b" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"975661bbfd7197055870311d" +], +[ +"cte_facts", +"21c6723982eb517d413a2f0d" +], +[ +"cte_facts", +"47ce4c603b269637acffc231" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"ff94ee1b456022577fb27f97" +], +[ +"cte_facts", +"600bf5e5cf97ffeac7a142ef" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"893f0c62ce53a72d332ac0bf" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"d30777b977850bbb40133d05" +], +[ +"cte_facts", +"f65699a7947784a10af4d56f" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"7816cb41efefaf9a53582088" +], +[ +"cte_facts", +"134f1f18ae356ecff89ffa05" +], +[ +"cte_facts", +"e550fe99452f9369374a43aa" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"2fcd2b715aee970b09d1939b" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"4074edd4c9844c8f0464bb10" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"c98042e640b64e0213124d44" +], +[ +"cte_facts", +"5a453cd7b93ed7b68e6f8de8" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"043656cc4910ccf8996cd6f9" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"823cd0f2ed932642009878a5" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"4ed55662a7fd257c4580d5db" +], +[ +"cte_facts", +"2581d3f5dad6a8fd1d2a59c1" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"1ff6aff6138509d87ef388c0" +], +[ +"cte_facts", +"4829c1b6749ee3f0daf22aaf" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"cc21305ff6f775769ffe22a0" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"4645d690fc914eee6ae7d048" +], +[ +"cte_facts", +"e163bc8972fd78f3cbedf2e0" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"7ccb221a0d0f2af9addd4009" +], +[ +"cte_facts", +"2c713820741de9d6d39db0f9" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7e34cf87ff4348a9640e6ab" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"5705f459c4fef601e9de2216" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"8b42dbc662c729fdf5311853" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a186e62463a75d56fa99a168" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"627bab400810971b05ee7dee" +], +[ +"cte_facts", +"7f289dd18993c29e40469dee" +], +[ +"cte_facts", +"99962340aae102b749214f5b" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"e228b36c9c39623e981b109a" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"d6f2fa2e0bdf33cb03a885df" +], +[ +"cte_facts", +"3c733fbd97f11c1ae39ee072" +], +[ +"cte_facts", +"4d2ac2ea950a76c76d323aa2" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"446781fa398ac9ef2b09da0b" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"78fc47b18cd2e829e476963f" +], +[ +"cte_facts", +"1e0b5081e91e76f874870f56" +], +[ +"cte_facts", +"7d3e2e6d18d037714f03b362" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"304123802323a41033dc1109" +], +[ +"cte_facts", +"f718dd96e91014fd7962bda5" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"754bb30a1a568f1bb9cd2b9f" +], +[ +"cte_facts", +"f5b6b22b1d2051b8f8cd0744" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"bff0842055947ae5ef20e050" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"aa0cffa33cea460d3abb6f82" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"98bec2974d565eb8da2d52f2" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"5e98624071bd40877af25354" +], +[ +"cte_facts", +"3f7d100dc2e33a2295ed892c" +], +[ +"cte_facts", +"da08b72d11b0a80a8495de2f" +], +[ +"cte_facts", +"d8d7d9b0b50847f0e16c04a5" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"02c20a1ad10b6ffce259f85a" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"8b004a796c5ec4af837cdc99" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"b517891860773a735a936b11" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"02c20a1ad10b6ffce259f85a" +], +[ +"cte_facts", +"4db4546cf049f2d63cebe9f7" +], +[ +"cte_facts", +"2971230791a89beacb266ca5" +], +[ +"cte_facts", +"105e18d72cafb88c3bba073d" +], +[ +"cte_facts", +"2de3863e3e3b27acd68bcd5e" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"3732b652976d866f62ec1395" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"fa78956a78e531f7ba4f6bbe" +], +[ +"cte_facts", +"8dbae9c6daee5c71e110ecf9" +], +[ +"cte_facts", +"5abe465025f727c471fa8a32" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"0d9a8d99fa86f5318ebd0b51" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"bf912cb617cf5276d3f3cb69" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"fd7c2d795a3033d55c9fe53e" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"8e8a2e7778d6ceeb65c93208" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a428c8b7529d336b14a92aff" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"eb44901cb5bef8a9623eb440" +], +[ +"cte_facts", +"142e5a445d063f8072735675" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"de23276a41fca52983fca6e9" +], +[ +"cte_facts", +"e5c0431376b17c69ec8bb239" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"38a3fce16527519e5a47d4dc" +], +[ +"cte_facts", +"5d01e1fe272632e24389e00f" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"e83331025b460b5b1db2ac0b" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"d493e2bde56595f2f45c5620" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"9e48f5c1ca7472eec267dc40" +], +[ +"cte_facts", +"b1d48ff3f4e22895f2372695" +], +[ +"cte_facts", +"1ea34dd04bc4230cd86dcc59" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"627e639dcd1624abbf32acca" +], +[ +"cte_facts", +"9b10a032e998f9b508453e2e" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a5ccf830e534696f595a3ac7" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"d18c9d48be2a96845523817b" +], +[ +"cte_facts", +"6f967aed45f75589baec1064" +], +[ +"cte_facts", +"e5c0431376b17c69ec8bb239" +], +[ +"cte_facts", +"ded7cbfa470e34d049eb6847" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"2179e2ce4ce9db4c1409b8e7" +], +[ +"cte_facts", +"c6b992be63a0a1341c2789de" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"7df2768aaf03df896e6c8294" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"af3195b0c034a44bd2bdd812" +], +[ +"cte_facts", +"56a2c31ae98e78ad0153970c" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"877a40768913bceb77234a09" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"6322aaddede94778335eb00a" +], +[ +"cte_facts", +"aa9fb5b8c130c6ffb432f3f8" +], +[ +"cte_facts", +"e228b36c9c39623e981b109a" +], +[ +"cte_facts", +"3d6d751da31e7fecf614f50a" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"fa78956a78e531f7ba4f6bbe" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"fe960f3513b186a69e6db3bc" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"bc5fc94739b12157ed94f2d0" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a51d44f88302c135b7f40232" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"1bfa15e991eb93ee9aeadc37" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"25c49563553f4b37747919ae" +], +[ +"cte_facts", +"decf92afee5279adb4e9baf2" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"687a1a7ceab548f637b5bfc6" +], +[ +"cte_facts", +"a00bc1aea089f5badf154464" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"52232f43fbe850c6672e95a7" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"ee2f1e6c32c94d1161ac3181" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"9930623e1aee198195f1d0fe" +], +[ +"cte_facts", +"f10c2e7703b93cfa2a7c2470" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"63f1f83c774d21323b822d63" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a9d8c38fffa45e3b0d783f" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"01b18a813c0e139f7141d489" +], +[ +"cte_facts", +"37f4f889dd27c4d2715a0f43" +], +[ +"cte_facts", +"a7e34cf87ff4348a9640e6ab" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"ef602f1b1f3491ef6b896357" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"8ce9bf1a58898a0b054656e4" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"6bcf69afe466a8a9751e9ded" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"370d84396f619d4bc85b671e" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"f56d783c937245b628fbe0e4" +], +[ +"cte_facts", +"a7e34cf87ff4348a9640e6ab" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"1c5747d7ca108e739c99e68b" +], +[ +"cte_facts", +"9ff66d22a8237eb258b3e02b" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"c321e0b7baae09e495a97ded" +], +[ +"cte_facts", +"46e612be9b2d5c332f91c2fe" +], +[ +"cte_facts", +"7c2c000285de82df6d7c66d1" +], +[ +"cte_facts", +"f9d884f02c33e38ffa6ac8e7" +], +[ +"cte_facts", +"0acaddaf873d067a844a7a56" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"51adb7a7b43a2e77762636fe" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"af3195b0c034a44bd2bdd812" +], +[ +"cte_facts", +"467e6e2db71288e4a594cc3f" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"06ef714b8645fe110ef354e5" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"5e98624071bd40877af25354" +], +[ +"cte_facts", +"a186e62463a75d56fa99a168" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"1ff578ebe02377c97036fe6a" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"55272ddc4f2bf5ab0526db7e" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"36d8a83a3563b286923195ac" +], +[ +"cte_facts", +"91120486c67447cb5dca6723" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"7ecf7f2b6754dddfcf690a8f" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"bacdeb92b7c2a043b4d54896" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"bac2cce5147fa305f14f21cd" +], +[ +"cte_facts", +"83c05f9bcabc42c474badf6b" +], +[ +"cte_facts", +"bf631a28a36fdf54a225c864" +], +[ +"cte_facts", +"ea7d43dc213da833dc086914" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"411a4ff3c72a2d03bf69579f" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"0ef179b9a0178ae379429e5a" +], +[ +"cte_facts", +"8b0096aea967f3de921be026" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"cc2a0d6e14869bc62792bb26" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"72050c12500b770ad291701c" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"8871f19bfb0b4e95225018ec" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"c671c33396672c9c79db48c4" +], +[ +"cte_facts", +"4575b1c93f423910102d880c" +], +[ +"cte_facts", +"afbf1b83e47396a0be837435" +], +[ +"cte_facts", +"46a25e730d1bdf56fb0a014b" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"56ab0c91556976b203ddd1e2" +], +[ +"cte_facts", +"38f4b4ac40110dd5d6c43ac3" +], +[ +"cte_facts", +"612d5180f2d9e383994af37a" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"5cd1fc8c032b6c627687105d" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"67f73487af6cd1ee11fbbff3" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"10e8e48c05a85795eb1c5044" +], +[ +"cte_facts", +"c4092e7706a7e6ed9ddf2b81" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"797e9c6250ec1d5640117d48" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"be1dd96ced3ebd1b1877244d" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"2aa652bf2cfec1da7f8c1173" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"c6fbf3e94d78ae117161fd19" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"9ff66d22a8237eb258b3e02b" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"38f4b4ac40110dd5d6c43ac3" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"80fa83935ddd8f6b08eeeb7a" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"411a4ff3c72a2d03bf69579f" +], +[ +"cte_facts", +"a7e34cf87ff4348a9640e6ab" +], +[ +"cte_facts", +"d24996d97ff4fef546bc3724" +], +[ +"cte_facts", +"bee38be89606bf949435caed" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"0a364c624111090c04f021a2" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"5b2d31a14b17341b0a949eb6" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"be1dd96ced3ebd1b1877244d" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"942040d62815f7336996f1af" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"10c4206e33f15bf86e1370fd" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"7f8818c0fcf334491f14c81e" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"2a959c85bd742066eee11c5c" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"292377d372fbc3dc3bb81492" +], +[ +"cte_facts", +"e5c0431376b17c69ec8bb239" +], +[ +"cte_facts", +"ed3848ce1b9ff99a1ca19c0a" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"755b369d1abd98c0cb9b83ca" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"d1a10a5283331fd270bbffc9" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"55272ddc4f2bf5ab0526db7e" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"eacad644b7889b7c54bf9840" +], +[ +"cte_facts", +"ea7d43dc213da833dc086914" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"88c909edfc66dc4271930356" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"ce3bf2dbfc7032bb0ce56b9f" +], +[ +"cte_facts", +"b8a677090052ffe5dfa0aa0b" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"7df2768aaf03df896e6c8294" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"48696258c7ec779e1ea036ae" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"df75f39d2709de69b46c11ec" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"6ff06232aabb72d368cfeae1" +], +[ +"cte_facts", +"3a9bf5cc8ff8bb0b49f2413b" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"968ac983ec3cc08095608953" +], +[ +"cte_facts", +"847aea89c4a3335728e3c612" +], +[ +"cte_facts", +"e8e5161a6f481ab44ae68a45" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"91b01cb7215d541f75cea4b8" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"d2878b450de47bb786eb0c96" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"eab186d2e7e5c4848d00d629" +], +[ +"cte_facts", +"55272ddc4f2bf5ab0526db7e" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"b40d732b81585f13ec3a22b3" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"d11e73177a45c2003416219a" +], +[ +"cte_facts", +"4d6759b4b9808c6022a18ea2" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"7ab94b1c6244c902eb67db59" +], +[ +"cte_facts", +"3c7c4024333942fa430e93d4" +], +[ +"cte_facts", +"eb3f6e1b0c45a4aa7d0a398e" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"9582bf20f07771c62e78b769" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"98c52349b67d23dfb2848c40" +], +[ +"cte_facts", +"6bd9bc7c2c16689ddd8ea738" +], +[ +"cte_facts", +"fb5a8619439d2baf467531b8" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"ce62a882c7bbc0eb5852bbcf" +], +[ +"cte_facts", +"b82d76b3de38f603cf2b0526" +], +[ +"cte_facts", +"fa6d8a8b325e116a0d5d829c" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"e05d64f215bd4e41bbeee00b" +], +[ +"cte_facts", +"e42ef49172e3dfa8ea8015ed" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"decf92afee5279adb4e9baf2" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"1e0b5081e91e76f874870f56" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"9bbe2e359e8edf8fea763fc7" +], +[ +"cte_facts", +"8ca61dedd06208f13b0e129e" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"5978d6eb10ab9e14421e1f71" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"df75f39d2709de69b46c11ec" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"e9290211930fee5e99fd9acb" +], +[ +"cte_facts", +"c2ef1a1274c86ef5a5488140" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"3df33633ea4e2783889aa339" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"f99a8a4b00f1bae2ca8f39e5" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"8ce2acfe9bb7ea1362545d17" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"ea96e238b5198477bd30504e" +], +[ +"cte_facts", +"3201b6eeeef7c538f171dce2" +], +[ +"cte_facts", +"0a62ff40d4f9fe56c5359f2c" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"8ae6c233d1d58a1ae685d56c" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"446781fa398ac9ef2b09da0b" +], +[ +"cte_facts", +"446781fa398ac9ef2b09da0b" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"442fabe01e432e3177422456" +], +[ +"cte_facts", +"928f47456cdfcdc751cccd31" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"e06900147c8f31d9c37b1209" +], +[ +"cte_facts", +"879e8fa5ec50584af1c5ef12" +], +[ +"cte_facts", +"0fbff11a946f4a2ec01abb40" +], +[ +"cte_facts", +"80b147aeadb9d07f6b981647" +], +[ +"cte_facts", +"e3ad81de9f1209b7d2ef35ec" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"9e8c7c69884949b723e2360d" +], +[ +"cte_facts", +"471ae877a2e3fd13c43f6a39" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"f718dd96e91014fd7962bda5" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"7d4315b47d9135f05277c1fc" +], +[ +"cte_facts", +"f8c008083d9c03f03d83c8cf" +], +[ +"cte_facts", +"d037fec55eff933500ace801" +], +[ +"cte_facts", +"fd10a125a304da4065bea134" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"b199df3de4c95cbc60acd0d5" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a9d8c38fffa45e3b0d783f" +], +[ +"cte_facts", +"a7a9d8c38fffa45e3b0d783f" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"6a212a0782392ac284539274" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"b7861944ce6f8e5598ecb504" +], +[ +"cte_facts", +"aa9fb5b8c130c6ffb432f3f8" +], +[ +"cte_facts", +"4db4546cf049f2d63cebe9f7" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a9d8c38fffa45e3b0d783f" +], +[ +"cte_facts", +"25a10549d1ae01a58000cd0e" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"cf56d985716a981f1117d243" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"411a4ff3c72a2d03bf69579f" +], +[ +"cte_facts", +"b7a00046e5722e993b5b0e35" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"236f440b1693641ee2e5d1bd" +], +[ +"cte_facts", +"d756bdc130b80ac669a33f5d" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"d756bdc130b80ac669a33f5d" +], +[ +"cte_facts", +"c3227e0d82eae5a699230286" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"bbdc27f8430ec345f2a0aa48" +], +[ +"cte_facts", +"5832d5537c11108289369e5f" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a4c96acb626116be3fb32cbb" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a15a6c8b36eccf68bd084a71" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"d672a1f46cae99b6118bffb9" +], +[ +"cte_facts", +"decf92afee5279adb4e9baf2" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"983ed2a5345d16d2f1e3556c" +], +[ +"cte_facts", +"ba48ca02849c994ece991e1f" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"514f07ef557fc9d7f7af5a93" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"1150565952dfe907fa12740f" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"d45fb2c887dd774246d10f61" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a9c7c5354062238c0d6f2471" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"e5c0431376b17c69ec8bb239" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"502bc77fdd1949aac4873b0d" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"e5c0431376b17c69ec8bb239" +], +[ +"cte_facts", +"f5b6b22b1d2051b8f8cd0744" +], +[ +"cte_facts", +"446781fa398ac9ef2b09da0b" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"314073b0d335b1d62091f044" +], +[ +"cte_facts", +"96c64e0ded4ba628e1653f40" +], +[ +"cte_facts", +"d73a408b0cab64dd3e8068d7" +], +[ +"cte_facts", +"20e87b1d9005062c36c16b4b" +], +[ +"cte_facts", +"25a10549d1ae01a58000cd0e" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"e00d4ad6ac1059ec06a5eabf" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"44bec6427a56cac3c1205f3b" +], +[ +"cte_facts", +"983ed2a5345d16d2f1e3556c" +], +[ +"cte_facts", +"c01a47626a907b90a83be9b6" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"c10c2bea99ae7d0b0b7f8597" +], +[ +"cte_facts", +"25a10549d1ae01a58000cd0e" +], +[ +"cte_facts", +"5430136f6bffab1727da3f78" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"b7274a1810cc185851e65ce5" +], +[ +"cte_facts", +"943060f97c1b26bd5461c8f5" +], +[ +"cte_facts", +"0a4b3cbac83ebcf9c3e4d647" +], +[ +"cte_facts", +"2e4a6a1fcffeb6a8e1d15e10" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"3ee0c2f34f0b58b3b5e14f93" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"ad302b5c5cf18359c71c36a9" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"962e7c206696722146a65acc" +], +[ +"cte_facts", +"5e98624071bd40877af25354" +], +[ +"cte_facts", +"845f2755a6571af998db7619" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"b7bf1d8e6e042ae95ad5efad" +], +[ +"cte_facts", +"07c7150255f0fcaf9dc5fd4e" +], +[ +"cte_facts", +"424e3607822bb4be2e1d6e05" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"c2ef1a1274c86ef5a5488140" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a94ad245364fd7872dbf4864" +], +[ +"cte_facts", +"e946d24f59d2f646bbe5c5fd" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"7aa55059d621c5f3131ff31a" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"2bffd0749d7e8d7811bede12" +], +[ +"cte_facts", +"4377bd36fe5c13dfa27b6a62" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"d0fc51a3fd267dd6581f737d" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"2de3863e3e3b27acd68bcd5e" +], +[ +"cte_facts", +"26d66c1506328beaec0f199a" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"c673c90e1972992cce693cb0" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"c469cfefd0affbfe7ffd273e" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"17fcafd3607575d317543125" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"7b0577a48135bbd47c670e17" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"e79441481098a255703e4e81" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"934209e73aef79ef60ea8520" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"c0ddac7e337047910d4af364" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"831eca53f82912733dc514d7" +], +[ +"cte_facts", +"9dd090a6429a40f2e4b6f108" +], +[ +"cte_facts", +"882da20a3b2430bec6b02456" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"881674709cec7cb115a04e78" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"4377bd36fe5c13dfa27b6a62" +], +[ +"cte_facts", +"762b6211fab680cc67ecca2c" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"5fd7bd460e3c527ef04b1099" +], +[ +"cte_facts", +"feb9235f367134393bb02e10" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"d54e34db9e36522f6d471204" +], +[ +"cte_facts", +"d7614dbe582d2f103c7461a8" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a145d981f53f939f824c319c" +], +[ +"cte_facts", +"879e8fa5ec50584af1c5ef12" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"e83331025b460b5b1db2ac0b" +], +[ +"cte_facts", +"d87fea57b43a56c38d7b0b05" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"07c7150255f0fcaf9dc5fd4e" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"2c0f877bb4c8f707c1975ac6" +], +[ +"cte_facts", +"934209e73aef79ef60ea8520" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"38de13edd098e9fef798f70c" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"e1ff8faa5277683c5e31b40e" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"3c7c4024333942fa430e93d4" +], +[ +"cte_facts", +"167cf9c912e644cf4ef3daed" +], +[ +"cte_facts", +"afc2249b34136f0c630661e4" +], +[ +"cte_facts", +"6d20eb5aef6b72ea0cc8b39f" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"0d3614828e2f4b5c3c3ca2ba" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"c8ada545dcbfb06a0a866525" +], +[ +"cte_facts", +"28382d4577b8cd305211f99c" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"41f0303c8377f9b414988aef" +], +[ +"cte_facts", +"a7e34cf87ff4348a9640e6ab" +], +[ +"cte_facts", +"30fcf054a8192ae04e617319" +], +[ +"cte_facts", +"b86e85acd2d15fb34ca979c5" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"4f5c613de86bf7ba685e1b38" +], +[ +"cte_facts", +"664bffc25c9f2efb1f37053e" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"22c87aeb15d4844e3748362c" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"c521b9d1b0084aafccb77db6" +], +[ +"cte_facts", +"5cc4aa1bf51dfb23ebd34d5d" +], +[ +"cte_facts", +"1facb03191eab779eb187997" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"69eb5c3a254e812eb33df7fc" +], +[ +"cte_facts", +"e616619423cd5f6eb3bf3f7c" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"e9630613ae7b7c40cff99261" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"decf92afee5279adb4e9baf2" +], +[ +"cte_facts", +"9c5fe8212f6c104e58f8a146" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"236f440b1693641ee2e5d1bd" +], +[ +"cte_facts", +"b976ce111f5bf18c67c6b490" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"f301f4d6d2dab7665154bf25" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"0ff36f2b49db0e4d671f2617" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"decf92afee5279adb4e9baf2" +], +[ +"cte_facts", +"14c604fbddeb705ee2872a99" +], +[ +"cte_facts", +"8083370fa0ead4f9af8cb0b6" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"45a5185979b9f820b0058626" +], +[ +"cte_facts", +"5925fee334e58d657b2b9aef" +], +[ +"cte_facts", +"be736807124339a0a1c410d8" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"418e76271ad967ca78780e1e" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"343133878e398b8afc9d4ec2" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"ec98b19df2d4b0c5b7223608" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"e5c0431376b17c69ec8bb239" +], +[ +"cte_facts", +"13c6de73dd9de5ac6bf0037e" +], +[ +"cte_facts", +"c8ada545dcbfb06a0a866525" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"617ed1874f379e6a768b996e" +], +[ +"cte_facts", +"80b337a9f115298079a9bcfc" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"b15daac7d7a5fb4b834de84e" +], +[ +"cte_facts", +"6a0d23ddf3acd4eb8690adc1" +], +[ +"cte_facts", +"31ce05446f06237043d47233" +], +[ +"cte_facts", +"cf1168ff284299b75c57c9b1" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"5430136f6bffab1727da3f78" +], +[ +"cte_facts", +"a49aa42ae820bd886c8f5796" +], +[ +"cte_facts", +"f4faaf760631624f1129378c" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"9b10a032e998f9b508453e2e" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"80b0c8aa54f739249a1755f8" +], +[ +"cte_facts", +"df75f39d2709de69b46c11ec" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"e00d4ad6ac1059ec06a5eabf" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"cc1270875c486a516ad0684b" +], +[ +"cte_facts", +"ba7d76432f08d918fbfcd3f4" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"e83331025b460b5b1db2ac0b" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"7ae39c4f9935ae9f91b35417" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"b9f949d4cc5bec682e71b5f6" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"6bd60dcc297125b2d33ee528" +], +[ +"cte_facts", +"b1a6056040f2c34e6b3f1f7f" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"c9bb60687815b7fd87ac6de7" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"931c32179bb339f5390d28ca" +], +[ +"cte_facts", +"785c80e17f1ac174c0151de1" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"934209e73aef79ef60ea8520" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"931c32179bb339f5390d28ca" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"323a2aa8aeea917ae183741e" +], +[ +"cte_facts", +"decf92afee5279adb4e9baf2" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"494f8ba6c8148923e77c5fbc" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"e616619423cd5f6eb3bf3f7c" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"ec9e6329e8f49cff8e7ad9ec" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"b4aea9555d5badeb28b80c3c" +], +[ +"cte_facts", +"e922001a12292d0640de3543" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"4377bd36fe5c13dfa27b6a62" +], +[ +"cte_facts", +"6b301515a097329dc3dea376" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"d4c14ed86311ebc54b9011a9" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"6b68919c26ac72cf8c5917f8" +], +[ +"cte_facts", +"2f3e7c0d66dfb4841008dc7a" +], +[ +"cte_facts", +"0ae01e775186032a46e2d7f8" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"b9ca9fb380cf29787051a4e4" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"f44562e2016b7337866b3ef1" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"6d030114c00b9d13ede8191f" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"20e87b1d9005062c36c16b4b" +], +[ +"cte_facts", +"abf6ef72e65b008efcc58f84" +], +[ +"cte_facts", +"6e6b4f0853902fb5771cac06" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"7df2768aaf03df896e6c8294" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"84611df4437258dad142d9d9" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"3beb8118486379f13a539b34" +], +[ +"cte_facts", +"0d972b0a013e308e6bef5433" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"165757241c36f8dbeaa6f4c7" +], +[ +"cte_facts", +"89635859e400c81e7d499fbc" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"0ccdbcb06a8ef737561da019" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"73b1effe619301b79ca31b9c" +], +[ +"cte_facts", +"eb6f02a66c40dd142124cfed" +], +[ +"cte_facts", +"e266b3adf96c73613a987818" +], +[ +"cte_facts", +"25a10549d1ae01a58000cd0e" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a9724dd337fbfc891eb7f173" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"11c86e815b4e7745ce308c15" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"02c20a1ad10b6ffce259f85a" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"931c32179bb339f5390d28ca" +], +[ +"cte_facts", +"58190c870eb7e4d6f518d229" +], +[ +"cte_facts", +"d59e252be9d2d0a5fdcb7c43" +], +[ +"cte_facts", +"35310061081f1ca0a805b6fd" +], +[ +"cte_facts", +"95c878fdaff0ff89d40d4dee" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"998dea787a69416f0fd447f1" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"78908fd99fbd26b0cfd83ef2" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"e17a7646aaeb5caddd14b1f4" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"c1c38f3b91d5b4fe5437f4fe" +], +[ +"cte_facts", +"356b53eeb08ce1f1c88b3b5d" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"9ccaa670d5e0e168faf1209a" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"22b16c75c454a71a7bdb9880" +], +[ +"cte_facts", +"3530e4c6fb1da09d012c270c" +], +[ +"cte_facts", +"0ec1a6575356c3a38663a8fc" +], +[ +"cte_facts", +"3faaaadc7b7cc9efb19175cf" +], +[ +"cte_facts", +"e4d853295fe692e5c86d60dc" +], +[ +"cte_facts", +"95eed6ac5f76289b7a9b5922" +], +[ +"cte_facts", +"04278e4fa62692e93672a830" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +], +[ +"cte_facts", +"446781fa398ac9ef2b09da0b" +], +[ +"cte_facts", +"a7a3f9c643602c78a03c7716" +] +] diff --git a/tests/goldens/python_oracle/declaration_usages_usage_scan_edges.json b/tests/goldens/python_oracle/declaration_usages_usage_scan_edges.json new file mode 100644 index 0000000000..431e8234f4 --- /dev/null +++ b/tests/goldens/python_oracle/declaration_usages_usage_scan_edges.json @@ -0,0 +1,86 @@ +[ +[ +"declaration_usages", +"6adc2535c49443cb6b3cc3cd" +], +[ +"declaration_usages", +"6070cec0a6fcc43f8c7ab528" +], +[ +"declaration_usages", +"6786f18f6ff42aa577c99d86" +], +[ +"declaration_usages", +"6070cec0a6fcc43f8c7ab528" +], +[ +"declaration_usages", +"7851fd987ffcb6afe0244d4d" +], +[ +"declaration_usages", +"6070cec0a6fcc43f8c7ab528" +], +[ +"declaration_usages", +"6070cec0a6fcc43f8c7ab528" +], +[ +"declaration_usages", +"7851fd987ffcb6afe0244d4d" +], +[ +"declaration_usages", +"6070cec0a6fcc43f8c7ab528" +], +[ +"declaration_usages", +"99c78fa41fe002d8642754e5" +], +[ +"declaration_usages", +"6786f18f6ff42aa577c99d86" +], +[ +"declaration_usages", +"ac6c4233f9df675ec4b5f9fd" +], +[ +"declaration_usages", +"6786f18f6ff42aa577c99d86" +], +[ +"declaration_usages", +"6786f18f6ff42aa577c99d86" +], +[ +"declaration_usages", +"6adc2535c49443cb6b3cc3cd" +], +[ +"declaration_usages", +"6786f18f6ff42aa577c99d86" +], +[ +"declaration_usages", +"077a3f290320a2b8cea483fc" +], +[ +"declaration_usages", +"6f95d4337ea1069397695fc8" +], +[ +"declaration_usages", +"6f95d4337ea1069397695fc8" +], +[ +"declaration_usages", +"6f95d4337ea1069397695fc8" +], +[ +"declaration_usages", +"077a3f290320a2b8cea483fc" +] +] diff --git a/tests/goldens/python_oracle/explicit_references_edge_projects.json b/tests/goldens/python_oracle/explicit_references_edge_projects.json new file mode 100644 index 0000000000..5116d3538a --- /dev/null +++ b/tests/goldens/python_oracle/explicit_references_edge_projects.json @@ -0,0 +1,54 @@ +[ +[ +"explicit_references", +"b70b8e802a4b67adeb1fc2e3" +], +[ +"explicit_references", +"1f2e788d4349e0a43ed9d99e" +], +[ +"explicit_references", +"21233f8423253e48e8844b06" +], +[ +"explicit_references", +"8a8030c53ec888f2b6a28cc4" +], +[ +"explicit_references", +"18216c9b230d59f93e117e5b" +], +[ +"explicit_references", +"204c1570007330f19d3d5ef1" +], +[ +"explicit_references", +"d41afb90907fa281b173024c" +], +[ +"explicit_references", +"34b91f2790f83b0b7d3d4820" +], +[ +"explicit_references", +"a9461cb64efcfc87f387dd4e" +], +[ +"explicit_references", +"92e4d194703692bbf96d85a3" +], +[ +"explicit_references", +"7e3caa377591a83b80f4d859" +], +[ +"explicit_references", +"aec22e4d642969f541fa5af9" +], +[ +"explicit_references", +"c16aa298ae2448053bd5e47a" +] +] diff --git a/tests/goldens/python_oracle/fast_lineage_generated_stars_nested_ctes_set_operations_quoting_and_opted_out_models.json b/tests/goldens/python_oracle/fast_lineage_generated_stars_nested_ctes_set_operations_quoting_and_opted_out_models.json new file mode 100644 index 0000000000..1c47a3ac48 --- /dev/null +++ b/tests/goldens/python_oracle/fast_lineage_generated_stars_nested_ctes_set_operations_quoting_and_opted_out_models.json @@ -0,0 +1,5570 @@ +[ +[ +"lineage", +{ +"0:orders_model_0.has_model": "b5bea41b6c623f7c09f1bf24", +"10:orders_model_15.has_model": "b5bea41b6c623f7c09f1bf24", +"11:orders_model_15.has_star": "fcbcf165908dd18a9e49f7ff", +"12:orders_model_15.edge_count": "4e07408562bedb8b60ce05c1", +"13:orders_model_15.targeting": "8fe2f3d0a303eca5503031b5", +"14:orders_model_15.sourced": "6786f18f6ff42aa577c99d86", +"15:orders_model_3.has_model": "b5bea41b6c623f7c09f1bf24", +"16:orders_model_3.has_star": "fcbcf165908dd18a9e49f7ff", +"17:orders_model_3.edge_count": "d4735e3a265e16eee03f5971", +"18:orders_model_3.targeting": "857c83e64739100814d8f497", +"19:orders_model_3.sourced": "6786f18f6ff42aa577c99d86", +"1:orders_model_0.has_star": "b5bea41b6c623f7c09f1bf24", +"20:orders_model_6.has_model": "b5bea41b6c623f7c09f1bf24", +"21:orders_model_6.has_star": "fcbcf165908dd18a9e49f7ff", +"22:orders_model_6.edge_count": "4e07408562bedb8b60ce05c1", +"23:orders_model_6.targeting": "e875a603bb4eaac6f28aef6b", +"24:orders_model_6.sourced": "c1aee4a42103a082541c19b7", +"25:orders_model_9.has_model": "b5bea41b6c623f7c09f1bf24", +"26:orders_model_9.has_star": "b5bea41b6c623f7c09f1bf24", +"27:orders_model_9.edge_count": "ef2d127de37b942baad06145", +"28:orders_model_9.targeting": "c1aee4a42103a082541c19b7", +"29:orders_model_9.sourced": "6bbb8ae1c03cae3174007e24", +"2:orders_model_0.edge_count": "4e07408562bedb8b60ce05c1", +"30:orders_model_1.has_model": "b5bea41b6c623f7c09f1bf24", +"31:orders_model_1.has_star": "b5bea41b6c623f7c09f1bf24", +"32:orders_model_1.edge_count": "4b227777d4dd1fc61c6f884f", +"33:orders_model_1.targeting": "3bcfcc6ee82a411e69515125", +"34:orders_model_1.sourced": "833e3ae8571732e99d47e0fc", +"35:orders_model_10.has_model": "b5bea41b6c623f7c09f1bf24", +"36:orders_model_10.has_star": "b5bea41b6c623f7c09f1bf24", +"37:orders_model_10.edge_count": "4e07408562bedb8b60ce05c1", +"38:orders_model_10.targeting": "c66d9a109cb01d45dd1a86a4", +"39:orders_model_10.sourced": "6786f18f6ff42aa577c99d86", +"3:orders_model_0.targeting": "4654ad70130bf45723d2b8e6", +"40:orders_model_13.has_model": "b5bea41b6c623f7c09f1bf24", +"41:orders_model_13.has_star": "b5bea41b6c623f7c09f1bf24", +"42:orders_model_13.edge_count": "4b227777d4dd1fc61c6f884f", +"43:orders_model_13.targeting": "15745747c1d507b3b5c6d94e", +"44:orders_model_13.sourced": "6786f18f6ff42aa577c99d86", +"45:orders_model_4.has_model": "b5bea41b6c623f7c09f1bf24", +"46:orders_model_4.has_star": "b5bea41b6c623f7c09f1bf24", +"47:orders_model_4.edge_count": "4e07408562bedb8b60ce05c1", +"48:orders_model_4.targeting": "e84cca707b52fbf7a63726fd", +"49:orders_model_4.sourced": "64ca73dda13db25820ee20e0", +"4:orders_model_0.sourced": "1990f5d01e632714338d0160", +"50:orders_model_7.has_model": "b5bea41b6c623f7c09f1bf24", +"51:orders_model_7.has_star": "fcbcf165908dd18a9e49f7ff", +"52:orders_model_7.edge_count": "7902699be42c8a8e46fbbb45", +"53:orders_model_7.targeting": "79896e5d232604aea741ec1b", +"54:orders_model_7.sourced": "6786f18f6ff42aa577c99d86", +"55:orders_model_11.has_model": "b5bea41b6c623f7c09f1bf24", +"56:orders_model_11.has_star": "fcbcf165908dd18a9e49f7ff", +"57:orders_model_11.edge_count": "6b86b273ff34fce19d6b804e", +"58:orders_model_11.targeting": "71a6cc1ef787af00586cdf2e", +"59:orders_model_11.sourced": "6786f18f6ff42aa577c99d86", +"5:orders_model_12.has_model": "b5bea41b6c623f7c09f1bf24", +"60:orders_model_14.has_model": "b5bea41b6c623f7c09f1bf24", +"61:orders_model_14.has_star": "fcbcf165908dd18a9e49f7ff", +"62:orders_model_14.edge_count": "d4735e3a265e16eee03f5971", +"63:orders_model_14.targeting": "906c9537cb6a0320a5145beb", +"64:orders_model_14.sourced": "6786f18f6ff42aa577c99d86", +"65:orders_model_2.has_model": "b5bea41b6c623f7c09f1bf24", +"66:orders_model_2.has_star": "fcbcf165908dd18a9e49f7ff", +"67:orders_model_2.edge_count": "6b86b273ff34fce19d6b804e", +"68:orders_model_2.targeting": "ab366fc8e364e0827653c9de", +"69:orders_model_2.sourced": "414698d284dfb6c4759e3907", +"6:orders_model_12.has_star": "fcbcf165908dd18a9e49f7ff", +"70:orders_model_5.has_model": "b5bea41b6c623f7c09f1bf24", +"71:orders_model_5.has_star": "fcbcf165908dd18a9e49f7ff", +"72:orders_model_5.edge_count": "d4735e3a265e16eee03f5971", +"73:orders_model_5.targeting": "415c0d50fd79d684f7e738ac", +"74:orders_model_5.sourced": "6786f18f6ff42aa577c99d86", +"75:orders_model_8.has_model": "b5bea41b6c623f7c09f1bf24", +"76:orders_model_8.has_star": "b5bea41b6c623f7c09f1bf24", +"77:orders_model_8.edge_count": "6b86b273ff34fce19d6b804e", +"78:orders_model_8.targeting": "bd62b4f2d8abfbc93f9a9d9b", +"79:orders_model_8.sourced": "6786f18f6ff42aa577c99d86", +"7:orders_model_12.edge_count": "d4735e3a265e16eee03f5971", +"80:models": "8076db03c4b29af16b33b043", +"81:edges": "7c6782de6171aee87a5c63ca", +"8:orders_model_12.targeting": "de72923afa7d269dec06170d", +"9:orders_model_12.sourced": "6786f18f6ff42aa577c99d86" +} +], +[ +"lineage", +{ +"0:orders_model_0.has_model": "fcbcf165908dd18a9e49f7ff", +"10:orders_model_15.has_model": "b5bea41b6c623f7c09f1bf24", +"11:orders_model_15.has_star": "fcbcf165908dd18a9e49f7ff", +"12:orders_model_15.edge_count": "4e07408562bedb8b60ce05c1", +"13:orders_model_15.targeting": "8fe2f3d0a303eca5503031b5", +"14:orders_model_15.sourced": "6786f18f6ff42aa577c99d86", +"15:orders_model_3.has_model": "fcbcf165908dd18a9e49f7ff", +"16:orders_model_3.has_star": "fcbcf165908dd18a9e49f7ff", +"17:orders_model_3.edge_count": "5feceb66ffc86f38d952786c", +"18:orders_model_3.targeting": "6786f18f6ff42aa577c99d86", +"19:orders_model_3.sourced": "6786f18f6ff42aa577c99d86", +"1:orders_model_0.has_star": "fcbcf165908dd18a9e49f7ff", +"20:orders_model_6.has_model": "fcbcf165908dd18a9e49f7ff", +"21:orders_model_6.has_star": "fcbcf165908dd18a9e49f7ff", +"22:orders_model_6.edge_count": "5feceb66ffc86f38d952786c", +"23:orders_model_6.targeting": "6786f18f6ff42aa577c99d86", +"24:orders_model_6.sourced": "c1aee4a42103a082541c19b7", +"25:orders_model_9.has_model": "b5bea41b6c623f7c09f1bf24", +"26:orders_model_9.has_star": "b5bea41b6c623f7c09f1bf24", +"27:orders_model_9.edge_count": "ef2d127de37b942baad06145", +"28:orders_model_9.targeting": "c1aee4a42103a082541c19b7", +"29:orders_model_9.sourced": "6bbb8ae1c03cae3174007e24", +"2:orders_model_0.edge_count": "5feceb66ffc86f38d952786c", +"30:orders_model_1.has_model": "b5bea41b6c623f7c09f1bf24", +"31:orders_model_1.has_star": "b5bea41b6c623f7c09f1bf24", +"32:orders_model_1.edge_count": "4b227777d4dd1fc61c6f884f", +"33:orders_model_1.targeting": "3bcfcc6ee82a411e69515125", +"34:orders_model_1.sourced": "98471e4c377a8d5d7068e4ec", +"35:orders_model_10.has_model": "fcbcf165908dd18a9e49f7ff", +"36:orders_model_10.has_star": "fcbcf165908dd18a9e49f7ff", +"37:orders_model_10.edge_count": "5feceb66ffc86f38d952786c", +"38:orders_model_10.targeting": "6786f18f6ff42aa577c99d86", +"39:orders_model_10.sourced": "6786f18f6ff42aa577c99d86", +"3:orders_model_0.targeting": "6786f18f6ff42aa577c99d86", +"40:orders_model_13.has_model": "fcbcf165908dd18a9e49f7ff", +"41:orders_model_13.has_star": "fcbcf165908dd18a9e49f7ff", +"42:orders_model_13.edge_count": "5feceb66ffc86f38d952786c", +"43:orders_model_13.targeting": "6786f18f6ff42aa577c99d86", +"44:orders_model_13.sourced": "6786f18f6ff42aa577c99d86", +"45:orders_model_4.has_model": "fcbcf165908dd18a9e49f7ff", +"46:orders_model_4.has_star": "fcbcf165908dd18a9e49f7ff", +"47:orders_model_4.edge_count": "5feceb66ffc86f38d952786c", +"48:orders_model_4.targeting": "6786f18f6ff42aa577c99d86", +"49:orders_model_4.sourced": "415c0d50fd79d684f7e738ac", +"4:orders_model_0.sourced": "0a51338d2cf0b7f4b891db04", +"50:orders_model_7.has_model": "fcbcf165908dd18a9e49f7ff", +"51:orders_model_7.has_star": "fcbcf165908dd18a9e49f7ff", +"52:orders_model_7.edge_count": "5feceb66ffc86f38d952786c", +"53:orders_model_7.targeting": "6786f18f6ff42aa577c99d86", +"54:orders_model_7.sourced": "6786f18f6ff42aa577c99d86", +"55:orders_model_11.has_model": "b5bea41b6c623f7c09f1bf24", +"56:orders_model_11.has_star": "fcbcf165908dd18a9e49f7ff", +"57:orders_model_11.edge_count": "6b86b273ff34fce19d6b804e", +"58:orders_model_11.targeting": "71a6cc1ef787af00586cdf2e", +"59:orders_model_11.sourced": "6786f18f6ff42aa577c99d86", +"5:orders_model_12.has_model": "b5bea41b6c623f7c09f1bf24", +"60:orders_model_14.has_model": "fcbcf165908dd18a9e49f7ff", +"61:orders_model_14.has_star": "fcbcf165908dd18a9e49f7ff", +"62:orders_model_14.edge_count": "5feceb66ffc86f38d952786c", +"63:orders_model_14.targeting": "6786f18f6ff42aa577c99d86", +"64:orders_model_14.sourced": "6786f18f6ff42aa577c99d86", +"65:orders_model_2.has_model": "b5bea41b6c623f7c09f1bf24", +"66:orders_model_2.has_star": "fcbcf165908dd18a9e49f7ff", +"67:orders_model_2.edge_count": "6b86b273ff34fce19d6b804e", +"68:orders_model_2.targeting": "ab366fc8e364e0827653c9de", +"69:orders_model_2.sourced": "bd62b4f2d8abfbc93f9a9d9b", +"6:orders_model_12.has_star": "fcbcf165908dd18a9e49f7ff", +"70:orders_model_5.has_model": "b5bea41b6c623f7c09f1bf24", +"71:orders_model_5.has_star": "fcbcf165908dd18a9e49f7ff", +"72:orders_model_5.edge_count": "d4735e3a265e16eee03f5971", +"73:orders_model_5.targeting": "415c0d50fd79d684f7e738ac", +"74:orders_model_5.sourced": "6786f18f6ff42aa577c99d86", +"75:orders_model_8.has_model": "b5bea41b6c623f7c09f1bf24", +"76:orders_model_8.has_star": "b5bea41b6c623f7c09f1bf24", +"77:orders_model_8.edge_count": "6b86b273ff34fce19d6b804e", +"78:orders_model_8.targeting": "bd62b4f2d8abfbc93f9a9d9b", +"79:orders_model_8.sourced": "6786f18f6ff42aa577c99d86", +"7:orders_model_12.edge_count": "d4735e3a265e16eee03f5971", +"80:models": "6c2eb1c2dab2a62dcfe944fe", +"81:edges": "59aa1a7bc998bf685d690875", +"8:orders_model_12.targeting": "de72923afa7d269dec06170d", +"9:orders_model_12.sourced": "6786f18f6ff42aa577c99d86" +} +], +[ +"lineage", +{ +"0:orders_model_0.has_model": "b5bea41b6c623f7c09f1bf24", +"10:orders_model_15.has_model": "b5bea41b6c623f7c09f1bf24", +"11:orders_model_15.has_star": "fcbcf165908dd18a9e49f7ff", +"12:orders_model_15.edge_count": "4e07408562bedb8b60ce05c1", +"13:orders_model_15.targeting": "8fe2f3d0a303eca5503031b5", +"14:orders_model_15.sourced": "6786f18f6ff42aa577c99d86", +"15:orders_model_3.has_model": "b5bea41b6c623f7c09f1bf24", +"16:orders_model_3.has_star": "fcbcf165908dd18a9e49f7ff", +"17:orders_model_3.edge_count": "d4735e3a265e16eee03f5971", +"18:orders_model_3.targeting": "857c83e64739100814d8f497", +"19:orders_model_3.sourced": "6786f18f6ff42aa577c99d86", +"1:orders_model_0.has_star": "b5bea41b6c623f7c09f1bf24", +"20:orders_model_6.has_model": "b5bea41b6c623f7c09f1bf24", +"21:orders_model_6.has_star": "fcbcf165908dd18a9e49f7ff", +"22:orders_model_6.edge_count": "4e07408562bedb8b60ce05c1", +"23:orders_model_6.targeting": "e875a603bb4eaac6f28aef6b", +"24:orders_model_6.sourced": "c1aee4a42103a082541c19b7", +"25:orders_model_9.has_model": "b5bea41b6c623f7c09f1bf24", +"26:orders_model_9.has_star": "b5bea41b6c623f7c09f1bf24", +"27:orders_model_9.edge_count": "ef2d127de37b942baad06145", +"28:orders_model_9.targeting": "c1aee4a42103a082541c19b7", +"29:orders_model_9.sourced": "6bbb8ae1c03cae3174007e24", +"2:orders_model_0.edge_count": "4e07408562bedb8b60ce05c1", +"30:orders_model_1.has_model": "b5bea41b6c623f7c09f1bf24", +"31:orders_model_1.has_star": "b5bea41b6c623f7c09f1bf24", +"32:orders_model_1.edge_count": "4b227777d4dd1fc61c6f884f", +"33:orders_model_1.targeting": "3bcfcc6ee82a411e69515125", +"34:orders_model_1.sourced": "833e3ae8571732e99d47e0fc", +"35:orders_model_10.has_model": "b5bea41b6c623f7c09f1bf24", +"36:orders_model_10.has_star": "b5bea41b6c623f7c09f1bf24", +"37:orders_model_10.edge_count": "4e07408562bedb8b60ce05c1", +"38:orders_model_10.targeting": "c66d9a109cb01d45dd1a86a4", +"39:orders_model_10.sourced": "6786f18f6ff42aa577c99d86", +"3:orders_model_0.targeting": "4654ad70130bf45723d2b8e6", +"40:orders_model_13.has_model": "b5bea41b6c623f7c09f1bf24", +"41:orders_model_13.has_star": "b5bea41b6c623f7c09f1bf24", +"42:orders_model_13.edge_count": "4b227777d4dd1fc61c6f884f", +"43:orders_model_13.targeting": "15745747c1d507b3b5c6d94e", +"44:orders_model_13.sourced": "6786f18f6ff42aa577c99d86", +"45:orders_model_4.has_model": "b5bea41b6c623f7c09f1bf24", +"46:orders_model_4.has_star": "b5bea41b6c623f7c09f1bf24", +"47:orders_model_4.edge_count": "4e07408562bedb8b60ce05c1", +"48:orders_model_4.targeting": "e84cca707b52fbf7a63726fd", +"49:orders_model_4.sourced": "64ca73dda13db25820ee20e0", +"4:orders_model_0.sourced": "1990f5d01e632714338d0160", +"50:orders_model_7.has_model": "b5bea41b6c623f7c09f1bf24", +"51:orders_model_7.has_star": "fcbcf165908dd18a9e49f7ff", +"52:orders_model_7.edge_count": "7902699be42c8a8e46fbbb45", +"53:orders_model_7.targeting": "79896e5d232604aea741ec1b", +"54:orders_model_7.sourced": "6786f18f6ff42aa577c99d86", +"55:orders_model_11.has_model": "b5bea41b6c623f7c09f1bf24", +"56:orders_model_11.has_star": "fcbcf165908dd18a9e49f7ff", +"57:orders_model_11.edge_count": "6b86b273ff34fce19d6b804e", +"58:orders_model_11.targeting": "71a6cc1ef787af00586cdf2e", +"59:orders_model_11.sourced": "6786f18f6ff42aa577c99d86", +"5:orders_model_12.has_model": "b5bea41b6c623f7c09f1bf24", +"60:orders_model_14.has_model": "b5bea41b6c623f7c09f1bf24", +"61:orders_model_14.has_star": "fcbcf165908dd18a9e49f7ff", +"62:orders_model_14.edge_count": "d4735e3a265e16eee03f5971", +"63:orders_model_14.targeting": "906c9537cb6a0320a5145beb", +"64:orders_model_14.sourced": "6786f18f6ff42aa577c99d86", +"65:orders_model_2.has_model": "b5bea41b6c623f7c09f1bf24", +"66:orders_model_2.has_star": "fcbcf165908dd18a9e49f7ff", +"67:orders_model_2.edge_count": "6b86b273ff34fce19d6b804e", +"68:orders_model_2.targeting": "ab366fc8e364e0827653c9de", +"69:orders_model_2.sourced": "414698d284dfb6c4759e3907", +"6:orders_model_12.has_star": "fcbcf165908dd18a9e49f7ff", +"70:orders_model_5.has_model": "b5bea41b6c623f7c09f1bf24", +"71:orders_model_5.has_star": "fcbcf165908dd18a9e49f7ff", +"72:orders_model_5.edge_count": "d4735e3a265e16eee03f5971", +"73:orders_model_5.targeting": "415c0d50fd79d684f7e738ac", +"74:orders_model_5.sourced": "6786f18f6ff42aa577c99d86", +"75:orders_model_8.has_model": "b5bea41b6c623f7c09f1bf24", +"76:orders_model_8.has_star": "b5bea41b6c623f7c09f1bf24", +"77:orders_model_8.edge_count": "6b86b273ff34fce19d6b804e", +"78:orders_model_8.targeting": "bd62b4f2d8abfbc93f9a9d9b", +"79:orders_model_8.sourced": "6786f18f6ff42aa577c99d86", +"7:orders_model_12.edge_count": "d4735e3a265e16eee03f5971", +"80:models": "8076db03c4b29af16b33b043", +"81:edges": "7c6782de6171aee87a5c63ca", +"8:orders_model_12.targeting": "de72923afa7d269dec06170d", +"9:orders_model_12.sourced": "6786f18f6ff42aa577c99d86" +} +], +[ +"lineage", +{ +"0:orders_model_0.has_model": "fcbcf165908dd18a9e49f7ff", +"10:orders_model_15.has_model": "b5bea41b6c623f7c09f1bf24", +"11:orders_model_15.has_star": "fcbcf165908dd18a9e49f7ff", +"12:orders_model_15.edge_count": "4e07408562bedb8b60ce05c1", +"13:orders_model_15.targeting": "8fe2f3d0a303eca5503031b5", +"14:orders_model_15.sourced": "6786f18f6ff42aa577c99d86", +"15:orders_model_3.has_model": "fcbcf165908dd18a9e49f7ff", +"16:orders_model_3.has_star": "fcbcf165908dd18a9e49f7ff", +"17:orders_model_3.edge_count": "5feceb66ffc86f38d952786c", +"18:orders_model_3.targeting": "6786f18f6ff42aa577c99d86", +"19:orders_model_3.sourced": "6786f18f6ff42aa577c99d86", +"1:orders_model_0.has_star": "fcbcf165908dd18a9e49f7ff", +"20:orders_model_6.has_model": "fcbcf165908dd18a9e49f7ff", +"21:orders_model_6.has_star": "fcbcf165908dd18a9e49f7ff", +"22:orders_model_6.edge_count": "5feceb66ffc86f38d952786c", +"23:orders_model_6.targeting": "6786f18f6ff42aa577c99d86", +"24:orders_model_6.sourced": "c1aee4a42103a082541c19b7", +"25:orders_model_9.has_model": "b5bea41b6c623f7c09f1bf24", +"26:orders_model_9.has_star": "b5bea41b6c623f7c09f1bf24", +"27:orders_model_9.edge_count": "ef2d127de37b942baad06145", +"28:orders_model_9.targeting": "c1aee4a42103a082541c19b7", +"29:orders_model_9.sourced": "6bbb8ae1c03cae3174007e24", +"2:orders_model_0.edge_count": "5feceb66ffc86f38d952786c", +"30:orders_model_1.has_model": "b5bea41b6c623f7c09f1bf24", +"31:orders_model_1.has_star": "b5bea41b6c623f7c09f1bf24", +"32:orders_model_1.edge_count": "4b227777d4dd1fc61c6f884f", +"33:orders_model_1.targeting": "3bcfcc6ee82a411e69515125", +"34:orders_model_1.sourced": "98471e4c377a8d5d7068e4ec", +"35:orders_model_10.has_model": "fcbcf165908dd18a9e49f7ff", +"36:orders_model_10.has_star": "fcbcf165908dd18a9e49f7ff", +"37:orders_model_10.edge_count": "5feceb66ffc86f38d952786c", +"38:orders_model_10.targeting": "6786f18f6ff42aa577c99d86", +"39:orders_model_10.sourced": "6786f18f6ff42aa577c99d86", +"3:orders_model_0.targeting": "6786f18f6ff42aa577c99d86", +"40:orders_model_13.has_model": "fcbcf165908dd18a9e49f7ff", +"41:orders_model_13.has_star": "fcbcf165908dd18a9e49f7ff", +"42:orders_model_13.edge_count": "5feceb66ffc86f38d952786c", +"43:orders_model_13.targeting": "6786f18f6ff42aa577c99d86", +"44:orders_model_13.sourced": "6786f18f6ff42aa577c99d86", +"45:orders_model_4.has_model": "fcbcf165908dd18a9e49f7ff", +"46:orders_model_4.has_star": "fcbcf165908dd18a9e49f7ff", +"47:orders_model_4.edge_count": "5feceb66ffc86f38d952786c", +"48:orders_model_4.targeting": "6786f18f6ff42aa577c99d86", +"49:orders_model_4.sourced": "415c0d50fd79d684f7e738ac", +"4:orders_model_0.sourced": "0a51338d2cf0b7f4b891db04", +"50:orders_model_7.has_model": "fcbcf165908dd18a9e49f7ff", +"51:orders_model_7.has_star": "fcbcf165908dd18a9e49f7ff", +"52:orders_model_7.edge_count": "5feceb66ffc86f38d952786c", +"53:orders_model_7.targeting": "6786f18f6ff42aa577c99d86", +"54:orders_model_7.sourced": "6786f18f6ff42aa577c99d86", +"55:orders_model_11.has_model": "b5bea41b6c623f7c09f1bf24", +"56:orders_model_11.has_star": "fcbcf165908dd18a9e49f7ff", +"57:orders_model_11.edge_count": "6b86b273ff34fce19d6b804e", +"58:orders_model_11.targeting": "71a6cc1ef787af00586cdf2e", +"59:orders_model_11.sourced": "6786f18f6ff42aa577c99d86", +"5:orders_model_12.has_model": "b5bea41b6c623f7c09f1bf24", +"60:orders_model_14.has_model": "fcbcf165908dd18a9e49f7ff", +"61:orders_model_14.has_star": "fcbcf165908dd18a9e49f7ff", +"62:orders_model_14.edge_count": "5feceb66ffc86f38d952786c", +"63:orders_model_14.targeting": "6786f18f6ff42aa577c99d86", +"64:orders_model_14.sourced": "6786f18f6ff42aa577c99d86", +"65:orders_model_2.has_model": "b5bea41b6c623f7c09f1bf24", +"66:orders_model_2.has_star": "fcbcf165908dd18a9e49f7ff", +"67:orders_model_2.edge_count": "6b86b273ff34fce19d6b804e", +"68:orders_model_2.targeting": "ab366fc8e364e0827653c9de", +"69:orders_model_2.sourced": "bd62b4f2d8abfbc93f9a9d9b", +"6:orders_model_12.has_star": "fcbcf165908dd18a9e49f7ff", +"70:orders_model_5.has_model": "b5bea41b6c623f7c09f1bf24", +"71:orders_model_5.has_star": "fcbcf165908dd18a9e49f7ff", +"72:orders_model_5.edge_count": "d4735e3a265e16eee03f5971", +"73:orders_model_5.targeting": "415c0d50fd79d684f7e738ac", +"74:orders_model_5.sourced": "6786f18f6ff42aa577c99d86", +"75:orders_model_8.has_model": "b5bea41b6c623f7c09f1bf24", +"76:orders_model_8.has_star": "b5bea41b6c623f7c09f1bf24", +"77:orders_model_8.edge_count": "6b86b273ff34fce19d6b804e", +"78:orders_model_8.targeting": "bd62b4f2d8abfbc93f9a9d9b", +"79:orders_model_8.sourced": "6786f18f6ff42aa577c99d86", +"7:orders_model_12.edge_count": "d4735e3a265e16eee03f5971", +"80:models": "6c2eb1c2dab2a62dcfe944fe", +"81:edges": "59aa1a7bc998bf685d690875", +"8:orders_model_12.targeting": "de72923afa7d269dec06170d", +"9:orders_model_12.sourced": "6786f18f6ff42aa577c99d86" +} +], +[ +"lineage", +{ +"0:orders_model_0.has_model": "b5bea41b6c623f7c09f1bf24", +"10:orders_model_15.has_model": "b5bea41b6c623f7c09f1bf24", +"11:orders_model_15.has_star": "fcbcf165908dd18a9e49f7ff", +"12:orders_model_15.edge_count": "4e07408562bedb8b60ce05c1", +"13:orders_model_15.targeting": "8fe2f3d0a303eca5503031b5", +"14:orders_model_15.sourced": "6786f18f6ff42aa577c99d86", +"15:orders_model_3.has_model": "b5bea41b6c623f7c09f1bf24", +"16:orders_model_3.has_star": "fcbcf165908dd18a9e49f7ff", +"17:orders_model_3.edge_count": "d4735e3a265e16eee03f5971", +"18:orders_model_3.targeting": "857c83e64739100814d8f497", +"19:orders_model_3.sourced": "6786f18f6ff42aa577c99d86", +"1:orders_model_0.has_star": "b5bea41b6c623f7c09f1bf24", +"20:orders_model_6.has_model": "b5bea41b6c623f7c09f1bf24", +"21:orders_model_6.has_star": "fcbcf165908dd18a9e49f7ff", +"22:orders_model_6.edge_count": "4e07408562bedb8b60ce05c1", +"23:orders_model_6.targeting": "e875a603bb4eaac6f28aef6b", +"24:orders_model_6.sourced": "c1aee4a42103a082541c19b7", +"25:orders_model_9.has_model": "b5bea41b6c623f7c09f1bf24", +"26:orders_model_9.has_star": "b5bea41b6c623f7c09f1bf24", +"27:orders_model_9.edge_count": "ef2d127de37b942baad06145", +"28:orders_model_9.targeting": "c1aee4a42103a082541c19b7", +"29:orders_model_9.sourced": "6bbb8ae1c03cae3174007e24", +"2:orders_model_0.edge_count": "4e07408562bedb8b60ce05c1", +"30:orders_model_1.has_model": "b5bea41b6c623f7c09f1bf24", +"31:orders_model_1.has_star": "b5bea41b6c623f7c09f1bf24", +"32:orders_model_1.edge_count": "4b227777d4dd1fc61c6f884f", +"33:orders_model_1.targeting": "3bcfcc6ee82a411e69515125", +"34:orders_model_1.sourced": "833e3ae8571732e99d47e0fc", +"35:orders_model_10.has_model": "b5bea41b6c623f7c09f1bf24", +"36:orders_model_10.has_star": "b5bea41b6c623f7c09f1bf24", +"37:orders_model_10.edge_count": "4e07408562bedb8b60ce05c1", +"38:orders_model_10.targeting": "c66d9a109cb01d45dd1a86a4", +"39:orders_model_10.sourced": "6786f18f6ff42aa577c99d86", +"3:orders_model_0.targeting": "4654ad70130bf45723d2b8e6", +"40:orders_model_13.has_model": "b5bea41b6c623f7c09f1bf24", +"41:orders_model_13.has_star": "b5bea41b6c623f7c09f1bf24", +"42:orders_model_13.edge_count": "4b227777d4dd1fc61c6f884f", +"43:orders_model_13.targeting": "15745747c1d507b3b5c6d94e", +"44:orders_model_13.sourced": "6786f18f6ff42aa577c99d86", +"45:orders_model_4.has_model": "b5bea41b6c623f7c09f1bf24", +"46:orders_model_4.has_star": "b5bea41b6c623f7c09f1bf24", +"47:orders_model_4.edge_count": "4e07408562bedb8b60ce05c1", +"48:orders_model_4.targeting": "e84cca707b52fbf7a63726fd", +"49:orders_model_4.sourced": "64ca73dda13db25820ee20e0", +"4:orders_model_0.sourced": "1990f5d01e632714338d0160", +"50:orders_model_7.has_model": "b5bea41b6c623f7c09f1bf24", +"51:orders_model_7.has_star": "fcbcf165908dd18a9e49f7ff", +"52:orders_model_7.edge_count": "7902699be42c8a8e46fbbb45", +"53:orders_model_7.targeting": "79896e5d232604aea741ec1b", +"54:orders_model_7.sourced": "6786f18f6ff42aa577c99d86", +"55:orders_model_11.has_model": "b5bea41b6c623f7c09f1bf24", +"56:orders_model_11.has_star": "fcbcf165908dd18a9e49f7ff", +"57:orders_model_11.edge_count": "6b86b273ff34fce19d6b804e", +"58:orders_model_11.targeting": "71a6cc1ef787af00586cdf2e", +"59:orders_model_11.sourced": "6786f18f6ff42aa577c99d86", +"5:orders_model_12.has_model": "b5bea41b6c623f7c09f1bf24", +"60:orders_model_14.has_model": "b5bea41b6c623f7c09f1bf24", +"61:orders_model_14.has_star": "fcbcf165908dd18a9e49f7ff", +"62:orders_model_14.edge_count": "d4735e3a265e16eee03f5971", +"63:orders_model_14.targeting": "906c9537cb6a0320a5145beb", +"64:orders_model_14.sourced": "6786f18f6ff42aa577c99d86", +"65:orders_model_2.has_model": "b5bea41b6c623f7c09f1bf24", +"66:orders_model_2.has_star": "fcbcf165908dd18a9e49f7ff", +"67:orders_model_2.edge_count": "6b86b273ff34fce19d6b804e", +"68:orders_model_2.targeting": "ab366fc8e364e0827653c9de", +"69:orders_model_2.sourced": "414698d284dfb6c4759e3907", +"6:orders_model_12.has_star": "fcbcf165908dd18a9e49f7ff", +"70:orders_model_5.has_model": "b5bea41b6c623f7c09f1bf24", +"71:orders_model_5.has_star": "fcbcf165908dd18a9e49f7ff", +"72:orders_model_5.edge_count": "d4735e3a265e16eee03f5971", +"73:orders_model_5.targeting": "415c0d50fd79d684f7e738ac", +"74:orders_model_5.sourced": "6786f18f6ff42aa577c99d86", +"75:orders_model_8.has_model": "b5bea41b6c623f7c09f1bf24", +"76:orders_model_8.has_star": "b5bea41b6c623f7c09f1bf24", +"77:orders_model_8.edge_count": "6b86b273ff34fce19d6b804e", +"78:orders_model_8.targeting": "bd62b4f2d8abfbc93f9a9d9b", +"79:orders_model_8.sourced": "6786f18f6ff42aa577c99d86", +"7:orders_model_12.edge_count": "d4735e3a265e16eee03f5971", +"80:models": "8076db03c4b29af16b33b043", +"81:edges": "7c6782de6171aee87a5c63ca", +"8:orders_model_12.targeting": "de72923afa7d269dec06170d", +"9:orders_model_12.sourced": "6786f18f6ff42aa577c99d86" +} +], +[ +"lineage", +{ +"0:orders_model_0.has_model": "fcbcf165908dd18a9e49f7ff", +"10:orders_model_15.has_model": "b5bea41b6c623f7c09f1bf24", +"11:orders_model_15.has_star": "fcbcf165908dd18a9e49f7ff", +"12:orders_model_15.edge_count": "4e07408562bedb8b60ce05c1", +"13:orders_model_15.targeting": "8fe2f3d0a303eca5503031b5", +"14:orders_model_15.sourced": "6786f18f6ff42aa577c99d86", +"15:orders_model_3.has_model": "fcbcf165908dd18a9e49f7ff", +"16:orders_model_3.has_star": "fcbcf165908dd18a9e49f7ff", +"17:orders_model_3.edge_count": "5feceb66ffc86f38d952786c", +"18:orders_model_3.targeting": "6786f18f6ff42aa577c99d86", +"19:orders_model_3.sourced": "6786f18f6ff42aa577c99d86", +"1:orders_model_0.has_star": "fcbcf165908dd18a9e49f7ff", +"20:orders_model_6.has_model": "fcbcf165908dd18a9e49f7ff", +"21:orders_model_6.has_star": "fcbcf165908dd18a9e49f7ff", +"22:orders_model_6.edge_count": "5feceb66ffc86f38d952786c", +"23:orders_model_6.targeting": "6786f18f6ff42aa577c99d86", +"24:orders_model_6.sourced": "c1aee4a42103a082541c19b7", +"25:orders_model_9.has_model": "b5bea41b6c623f7c09f1bf24", +"26:orders_model_9.has_star": "b5bea41b6c623f7c09f1bf24", +"27:orders_model_9.edge_count": "ef2d127de37b942baad06145", +"28:orders_model_9.targeting": "c1aee4a42103a082541c19b7", +"29:orders_model_9.sourced": "6bbb8ae1c03cae3174007e24", +"2:orders_model_0.edge_count": "5feceb66ffc86f38d952786c", +"30:orders_model_1.has_model": "b5bea41b6c623f7c09f1bf24", +"31:orders_model_1.has_star": "b5bea41b6c623f7c09f1bf24", +"32:orders_model_1.edge_count": "4b227777d4dd1fc61c6f884f", +"33:orders_model_1.targeting": "3bcfcc6ee82a411e69515125", +"34:orders_model_1.sourced": "98471e4c377a8d5d7068e4ec", +"35:orders_model_10.has_model": "fcbcf165908dd18a9e49f7ff", +"36:orders_model_10.has_star": "fcbcf165908dd18a9e49f7ff", +"37:orders_model_10.edge_count": "5feceb66ffc86f38d952786c", +"38:orders_model_10.targeting": "6786f18f6ff42aa577c99d86", +"39:orders_model_10.sourced": "6786f18f6ff42aa577c99d86", +"3:orders_model_0.targeting": "6786f18f6ff42aa577c99d86", +"40:orders_model_13.has_model": "fcbcf165908dd18a9e49f7ff", +"41:orders_model_13.has_star": "fcbcf165908dd18a9e49f7ff", +"42:orders_model_13.edge_count": "5feceb66ffc86f38d952786c", +"43:orders_model_13.targeting": "6786f18f6ff42aa577c99d86", +"44:orders_model_13.sourced": "6786f18f6ff42aa577c99d86", +"45:orders_model_4.has_model": "fcbcf165908dd18a9e49f7ff", +"46:orders_model_4.has_star": "fcbcf165908dd18a9e49f7ff", +"47:orders_model_4.edge_count": "5feceb66ffc86f38d952786c", +"48:orders_model_4.targeting": "6786f18f6ff42aa577c99d86", +"49:orders_model_4.sourced": "415c0d50fd79d684f7e738ac", +"4:orders_model_0.sourced": "0a51338d2cf0b7f4b891db04", +"50:orders_model_7.has_model": "fcbcf165908dd18a9e49f7ff", +"51:orders_model_7.has_star": "fcbcf165908dd18a9e49f7ff", +"52:orders_model_7.edge_count": "5feceb66ffc86f38d952786c", +"53:orders_model_7.targeting": "6786f18f6ff42aa577c99d86", +"54:orders_model_7.sourced": "6786f18f6ff42aa577c99d86", +"55:orders_model_11.has_model": "b5bea41b6c623f7c09f1bf24", +"56:orders_model_11.has_star": "fcbcf165908dd18a9e49f7ff", +"57:orders_model_11.edge_count": "6b86b273ff34fce19d6b804e", +"58:orders_model_11.targeting": "71a6cc1ef787af00586cdf2e", +"59:orders_model_11.sourced": "6786f18f6ff42aa577c99d86", +"5:orders_model_12.has_model": "b5bea41b6c623f7c09f1bf24", +"60:orders_model_14.has_model": "fcbcf165908dd18a9e49f7ff", +"61:orders_model_14.has_star": "fcbcf165908dd18a9e49f7ff", +"62:orders_model_14.edge_count": "5feceb66ffc86f38d952786c", +"63:orders_model_14.targeting": "6786f18f6ff42aa577c99d86", +"64:orders_model_14.sourced": "6786f18f6ff42aa577c99d86", +"65:orders_model_2.has_model": "b5bea41b6c623f7c09f1bf24", +"66:orders_model_2.has_star": "fcbcf165908dd18a9e49f7ff", +"67:orders_model_2.edge_count": "6b86b273ff34fce19d6b804e", +"68:orders_model_2.targeting": "ab366fc8e364e0827653c9de", +"69:orders_model_2.sourced": "bd62b4f2d8abfbc93f9a9d9b", +"6:orders_model_12.has_star": "fcbcf165908dd18a9e49f7ff", +"70:orders_model_5.has_model": "b5bea41b6c623f7c09f1bf24", +"71:orders_model_5.has_star": "fcbcf165908dd18a9e49f7ff", +"72:orders_model_5.edge_count": "d4735e3a265e16eee03f5971", +"73:orders_model_5.targeting": "415c0d50fd79d684f7e738ac", +"74:orders_model_5.sourced": "6786f18f6ff42aa577c99d86", +"75:orders_model_8.has_model": "b5bea41b6c623f7c09f1bf24", +"76:orders_model_8.has_star": "b5bea41b6c623f7c09f1bf24", +"77:orders_model_8.edge_count": "6b86b273ff34fce19d6b804e", +"78:orders_model_8.targeting": "bd62b4f2d8abfbc93f9a9d9b", +"79:orders_model_8.sourced": "6786f18f6ff42aa577c99d86", +"7:orders_model_12.edge_count": "d4735e3a265e16eee03f5971", +"80:models": "6c2eb1c2dab2a62dcfe944fe", +"81:edges": "59aa1a7bc998bf685d690875", +"8:orders_model_12.targeting": "de72923afa7d269dec06170d", +"9:orders_model_12.sourced": "6786f18f6ff42aa577c99d86" +} +], +[ +"lineage", +{ +"0:orders_model_0.has_model": "b5bea41b6c623f7c09f1bf24", +"10:orders_model_15.has_model": "b5bea41b6c623f7c09f1bf24", +"11:orders_model_15.has_star": "fcbcf165908dd18a9e49f7ff", +"12:orders_model_15.edge_count": "4e07408562bedb8b60ce05c1", +"13:orders_model_15.targeting": "8fe2f3d0a303eca5503031b5", +"14:orders_model_15.sourced": "6786f18f6ff42aa577c99d86", +"15:orders_model_3.has_model": "b5bea41b6c623f7c09f1bf24", +"16:orders_model_3.has_star": "fcbcf165908dd18a9e49f7ff", +"17:orders_model_3.edge_count": "d4735e3a265e16eee03f5971", +"18:orders_model_3.targeting": "857c83e64739100814d8f497", +"19:orders_model_3.sourced": "6786f18f6ff42aa577c99d86", +"1:orders_model_0.has_star": "b5bea41b6c623f7c09f1bf24", +"20:orders_model_6.has_model": "b5bea41b6c623f7c09f1bf24", +"21:orders_model_6.has_star": "fcbcf165908dd18a9e49f7ff", +"22:orders_model_6.edge_count": "4e07408562bedb8b60ce05c1", +"23:orders_model_6.targeting": "e875a603bb4eaac6f28aef6b", +"24:orders_model_6.sourced": "c1aee4a42103a082541c19b7", +"25:orders_model_9.has_model": "b5bea41b6c623f7c09f1bf24", +"26:orders_model_9.has_star": "b5bea41b6c623f7c09f1bf24", +"27:orders_model_9.edge_count": "ef2d127de37b942baad06145", +"28:orders_model_9.targeting": "c1aee4a42103a082541c19b7", +"29:orders_model_9.sourced": "6bbb8ae1c03cae3174007e24", +"2:orders_model_0.edge_count": "4e07408562bedb8b60ce05c1", +"30:orders_model_1.has_model": "b5bea41b6c623f7c09f1bf24", +"31:orders_model_1.has_star": "b5bea41b6c623f7c09f1bf24", +"32:orders_model_1.edge_count": "4b227777d4dd1fc61c6f884f", +"33:orders_model_1.targeting": "3bcfcc6ee82a411e69515125", +"34:orders_model_1.sourced": "833e3ae8571732e99d47e0fc", +"35:orders_model_10.has_model": "b5bea41b6c623f7c09f1bf24", +"36:orders_model_10.has_star": "b5bea41b6c623f7c09f1bf24", +"37:orders_model_10.edge_count": "4e07408562bedb8b60ce05c1", +"38:orders_model_10.targeting": "c66d9a109cb01d45dd1a86a4", +"39:orders_model_10.sourced": "6786f18f6ff42aa577c99d86", +"3:orders_model_0.targeting": "4654ad70130bf45723d2b8e6", +"40:orders_model_13.has_model": "b5bea41b6c623f7c09f1bf24", +"41:orders_model_13.has_star": "b5bea41b6c623f7c09f1bf24", +"42:orders_model_13.edge_count": "4b227777d4dd1fc61c6f884f", +"43:orders_model_13.targeting": "15745747c1d507b3b5c6d94e", +"44:orders_model_13.sourced": "6786f18f6ff42aa577c99d86", +"45:orders_model_4.has_model": "b5bea41b6c623f7c09f1bf24", +"46:orders_model_4.has_star": "b5bea41b6c623f7c09f1bf24", +"47:orders_model_4.edge_count": "4e07408562bedb8b60ce05c1", +"48:orders_model_4.targeting": "e84cca707b52fbf7a63726fd", +"49:orders_model_4.sourced": "64ca73dda13db25820ee20e0", +"4:orders_model_0.sourced": "1990f5d01e632714338d0160", +"50:orders_model_7.has_model": "b5bea41b6c623f7c09f1bf24", +"51:orders_model_7.has_star": "fcbcf165908dd18a9e49f7ff", +"52:orders_model_7.edge_count": "7902699be42c8a8e46fbbb45", +"53:orders_model_7.targeting": "79896e5d232604aea741ec1b", +"54:orders_model_7.sourced": "6786f18f6ff42aa577c99d86", +"55:orders_model_11.has_model": "b5bea41b6c623f7c09f1bf24", +"56:orders_model_11.has_star": "fcbcf165908dd18a9e49f7ff", +"57:orders_model_11.edge_count": "6b86b273ff34fce19d6b804e", +"58:orders_model_11.targeting": "71a6cc1ef787af00586cdf2e", +"59:orders_model_11.sourced": "6786f18f6ff42aa577c99d86", +"5:orders_model_12.has_model": "b5bea41b6c623f7c09f1bf24", +"60:orders_model_14.has_model": "b5bea41b6c623f7c09f1bf24", +"61:orders_model_14.has_star": "fcbcf165908dd18a9e49f7ff", +"62:orders_model_14.edge_count": "d4735e3a265e16eee03f5971", +"63:orders_model_14.targeting": "906c9537cb6a0320a5145beb", +"64:orders_model_14.sourced": "6786f18f6ff42aa577c99d86", +"65:orders_model_2.has_model": "b5bea41b6c623f7c09f1bf24", +"66:orders_model_2.has_star": "fcbcf165908dd18a9e49f7ff", +"67:orders_model_2.edge_count": "6b86b273ff34fce19d6b804e", +"68:orders_model_2.targeting": "ab366fc8e364e0827653c9de", +"69:orders_model_2.sourced": "414698d284dfb6c4759e3907", +"6:orders_model_12.has_star": "fcbcf165908dd18a9e49f7ff", +"70:orders_model_5.has_model": "b5bea41b6c623f7c09f1bf24", +"71:orders_model_5.has_star": "fcbcf165908dd18a9e49f7ff", +"72:orders_model_5.edge_count": "d4735e3a265e16eee03f5971", +"73:orders_model_5.targeting": "415c0d50fd79d684f7e738ac", +"74:orders_model_5.sourced": "6786f18f6ff42aa577c99d86", +"75:orders_model_8.has_model": "b5bea41b6c623f7c09f1bf24", +"76:orders_model_8.has_star": "b5bea41b6c623f7c09f1bf24", +"77:orders_model_8.edge_count": "6b86b273ff34fce19d6b804e", +"78:orders_model_8.targeting": "bd62b4f2d8abfbc93f9a9d9b", +"79:orders_model_8.sourced": "6786f18f6ff42aa577c99d86", +"7:orders_model_12.edge_count": "d4735e3a265e16eee03f5971", +"80:models": "8076db03c4b29af16b33b043", +"81:edges": "7c6782de6171aee87a5c63ca", +"8:orders_model_12.targeting": "de72923afa7d269dec06170d", +"9:orders_model_12.sourced": "6786f18f6ff42aa577c99d86" +} +], +[ +"lineage", +{ +"0:orders_model_0.has_model": "fcbcf165908dd18a9e49f7ff", +"10:orders_model_15.has_model": "b5bea41b6c623f7c09f1bf24", +"11:orders_model_15.has_star": "fcbcf165908dd18a9e49f7ff", +"12:orders_model_15.edge_count": "4e07408562bedb8b60ce05c1", +"13:orders_model_15.targeting": "8fe2f3d0a303eca5503031b5", +"14:orders_model_15.sourced": "6786f18f6ff42aa577c99d86", +"15:orders_model_3.has_model": "fcbcf165908dd18a9e49f7ff", +"16:orders_model_3.has_star": "fcbcf165908dd18a9e49f7ff", +"17:orders_model_3.edge_count": "5feceb66ffc86f38d952786c", +"18:orders_model_3.targeting": "6786f18f6ff42aa577c99d86", +"19:orders_model_3.sourced": "6786f18f6ff42aa577c99d86", +"1:orders_model_0.has_star": "fcbcf165908dd18a9e49f7ff", +"20:orders_model_6.has_model": "fcbcf165908dd18a9e49f7ff", +"21:orders_model_6.has_star": "fcbcf165908dd18a9e49f7ff", +"22:orders_model_6.edge_count": "5feceb66ffc86f38d952786c", +"23:orders_model_6.targeting": "6786f18f6ff42aa577c99d86", +"24:orders_model_6.sourced": "c1aee4a42103a082541c19b7", +"25:orders_model_9.has_model": "b5bea41b6c623f7c09f1bf24", +"26:orders_model_9.has_star": "b5bea41b6c623f7c09f1bf24", +"27:orders_model_9.edge_count": "ef2d127de37b942baad06145", +"28:orders_model_9.targeting": "c1aee4a42103a082541c19b7", +"29:orders_model_9.sourced": "6bbb8ae1c03cae3174007e24", +"2:orders_model_0.edge_count": "5feceb66ffc86f38d952786c", +"30:orders_model_1.has_model": "b5bea41b6c623f7c09f1bf24", +"31:orders_model_1.has_star": "b5bea41b6c623f7c09f1bf24", +"32:orders_model_1.edge_count": "4b227777d4dd1fc61c6f884f", +"33:orders_model_1.targeting": "3bcfcc6ee82a411e69515125", +"34:orders_model_1.sourced": "98471e4c377a8d5d7068e4ec", +"35:orders_model_10.has_model": "fcbcf165908dd18a9e49f7ff", +"36:orders_model_10.has_star": "fcbcf165908dd18a9e49f7ff", +"37:orders_model_10.edge_count": "5feceb66ffc86f38d952786c", +"38:orders_model_10.targeting": "6786f18f6ff42aa577c99d86", +"39:orders_model_10.sourced": "6786f18f6ff42aa577c99d86", +"3:orders_model_0.targeting": "6786f18f6ff42aa577c99d86", +"40:orders_model_13.has_model": "fcbcf165908dd18a9e49f7ff", +"41:orders_model_13.has_star": "fcbcf165908dd18a9e49f7ff", +"42:orders_model_13.edge_count": "5feceb66ffc86f38d952786c", +"43:orders_model_13.targeting": "6786f18f6ff42aa577c99d86", +"44:orders_model_13.sourced": "6786f18f6ff42aa577c99d86", +"45:orders_model_4.has_model": "fcbcf165908dd18a9e49f7ff", +"46:orders_model_4.has_star": "fcbcf165908dd18a9e49f7ff", +"47:orders_model_4.edge_count": "5feceb66ffc86f38d952786c", +"48:orders_model_4.targeting": "6786f18f6ff42aa577c99d86", +"49:orders_model_4.sourced": "415c0d50fd79d684f7e738ac", +"4:orders_model_0.sourced": "0a51338d2cf0b7f4b891db04", +"50:orders_model_7.has_model": "fcbcf165908dd18a9e49f7ff", +"51:orders_model_7.has_star": "fcbcf165908dd18a9e49f7ff", +"52:orders_model_7.edge_count": "5feceb66ffc86f38d952786c", +"53:orders_model_7.targeting": "6786f18f6ff42aa577c99d86", +"54:orders_model_7.sourced": "6786f18f6ff42aa577c99d86", +"55:orders_model_11.has_model": "b5bea41b6c623f7c09f1bf24", +"56:orders_model_11.has_star": "fcbcf165908dd18a9e49f7ff", +"57:orders_model_11.edge_count": "6b86b273ff34fce19d6b804e", +"58:orders_model_11.targeting": "71a6cc1ef787af00586cdf2e", +"59:orders_model_11.sourced": "6786f18f6ff42aa577c99d86", +"5:orders_model_12.has_model": "b5bea41b6c623f7c09f1bf24", +"60:orders_model_14.has_model": "fcbcf165908dd18a9e49f7ff", +"61:orders_model_14.has_star": "fcbcf165908dd18a9e49f7ff", +"62:orders_model_14.edge_count": "5feceb66ffc86f38d952786c", +"63:orders_model_14.targeting": "6786f18f6ff42aa577c99d86", +"64:orders_model_14.sourced": "6786f18f6ff42aa577c99d86", +"65:orders_model_2.has_model": "b5bea41b6c623f7c09f1bf24", +"66:orders_model_2.has_star": "fcbcf165908dd18a9e49f7ff", +"67:orders_model_2.edge_count": "6b86b273ff34fce19d6b804e", +"68:orders_model_2.targeting": "ab366fc8e364e0827653c9de", +"69:orders_model_2.sourced": "bd62b4f2d8abfbc93f9a9d9b", +"6:orders_model_12.has_star": "fcbcf165908dd18a9e49f7ff", +"70:orders_model_5.has_model": "b5bea41b6c623f7c09f1bf24", +"71:orders_model_5.has_star": "fcbcf165908dd18a9e49f7ff", +"72:orders_model_5.edge_count": "d4735e3a265e16eee03f5971", +"73:orders_model_5.targeting": "415c0d50fd79d684f7e738ac", +"74:orders_model_5.sourced": "6786f18f6ff42aa577c99d86", +"75:orders_model_8.has_model": "b5bea41b6c623f7c09f1bf24", +"76:orders_model_8.has_star": "b5bea41b6c623f7c09f1bf24", +"77:orders_model_8.edge_count": "6b86b273ff34fce19d6b804e", +"78:orders_model_8.targeting": "bd62b4f2d8abfbc93f9a9d9b", +"79:orders_model_8.sourced": "6786f18f6ff42aa577c99d86", +"7:orders_model_12.edge_count": "d4735e3a265e16eee03f5971", +"80:models": "6c2eb1c2dab2a62dcfe944fe", +"81:edges": "59aa1a7bc998bf685d690875", +"8:orders_model_12.targeting": "de72923afa7d269dec06170d", +"9:orders_model_12.sourced": "6786f18f6ff42aa577c99d86" +} +], +[ +"lineage", +{ +"0:orders_model_0.has_model": "b5bea41b6c623f7c09f1bf24", +"10:orders_model_15.has_model": "b5bea41b6c623f7c09f1bf24", +"11:orders_model_15.has_star": "fcbcf165908dd18a9e49f7ff", +"12:orders_model_15.edge_count": "4e07408562bedb8b60ce05c1", +"13:orders_model_15.targeting": "8fe2f3d0a303eca5503031b5", +"14:orders_model_15.sourced": "6786f18f6ff42aa577c99d86", +"15:orders_model_3.has_model": "b5bea41b6c623f7c09f1bf24", +"16:orders_model_3.has_star": "fcbcf165908dd18a9e49f7ff", +"17:orders_model_3.edge_count": "d4735e3a265e16eee03f5971", +"18:orders_model_3.targeting": "1ff64b327984da82f76cce2e", +"19:orders_model_3.sourced": "6786f18f6ff42aa577c99d86", +"1:orders_model_0.has_star": "b5bea41b6c623f7c09f1bf24", +"20:orders_model_6.has_model": "b5bea41b6c623f7c09f1bf24", +"21:orders_model_6.has_star": "fcbcf165908dd18a9e49f7ff", +"22:orders_model_6.edge_count": "4e07408562bedb8b60ce05c1", +"23:orders_model_6.targeting": "0fcf4ef01f4ca62bb77c3d80", +"24:orders_model_6.sourced": "a967e822b57213ec858768ca", +"25:orders_model_9.has_model": "b5bea41b6c623f7c09f1bf24", +"26:orders_model_9.has_star": "b5bea41b6c623f7c09f1bf24", +"27:orders_model_9.edge_count": "ef2d127de37b942baad06145", +"28:orders_model_9.targeting": "a967e822b57213ec858768ca", +"29:orders_model_9.sourced": "6bbb8ae1c03cae3174007e24", +"2:orders_model_0.edge_count": "4e07408562bedb8b60ce05c1", +"30:orders_model_1.has_model": "b5bea41b6c623f7c09f1bf24", +"31:orders_model_1.has_star": "b5bea41b6c623f7c09f1bf24", +"32:orders_model_1.edge_count": "ef2d127de37b942baad06145", +"33:orders_model_1.targeting": "bbedd18bce59f23468d191c5", +"34:orders_model_1.sourced": "0c1d78a57ca6b9e16bcd6266", +"35:orders_model_10.has_model": "b5bea41b6c623f7c09f1bf24", +"36:orders_model_10.has_star": "b5bea41b6c623f7c09f1bf24", +"37:orders_model_10.edge_count": "ef2d127de37b942baad06145", +"38:orders_model_10.targeting": "2591b6af4aaafcb322150ab2", +"39:orders_model_10.sourced": "6786f18f6ff42aa577c99d86", +"3:orders_model_0.targeting": "d11526ad01eb59472574a2a3", +"40:orders_model_13.has_model": "b5bea41b6c623f7c09f1bf24", +"41:orders_model_13.has_star": "b5bea41b6c623f7c09f1bf24", +"42:orders_model_13.edge_count": "4e07408562bedb8b60ce05c1", +"43:orders_model_13.targeting": "c5bd06cf3f6a094d7fb244f2", +"44:orders_model_13.sourced": "6786f18f6ff42aa577c99d86", +"45:orders_model_4.has_model": "b5bea41b6c623f7c09f1bf24", +"46:orders_model_4.has_star": "b5bea41b6c623f7c09f1bf24", +"47:orders_model_4.edge_count": "d4735e3a265e16eee03f5971", +"48:orders_model_4.targeting": "1aa2dcab73d2bc39dc008009", +"49:orders_model_4.sourced": "64ca73dda13db25820ee20e0", +"4:orders_model_0.sourced": "8bcc9afb9b2508beebd187ed", +"50:orders_model_7.has_model": "b5bea41b6c623f7c09f1bf24", +"51:orders_model_7.has_star": "fcbcf165908dd18a9e49f7ff", +"52:orders_model_7.edge_count": "7902699be42c8a8e46fbbb45", +"53:orders_model_7.targeting": "79896e5d232604aea741ec1b", +"54:orders_model_7.sourced": "6786f18f6ff42aa577c99d86", +"55:orders_model_11.has_model": "b5bea41b6c623f7c09f1bf24", +"56:orders_model_11.has_star": "fcbcf165908dd18a9e49f7ff", +"57:orders_model_11.edge_count": "6b86b273ff34fce19d6b804e", +"58:orders_model_11.targeting": "71a6cc1ef787af00586cdf2e", +"59:orders_model_11.sourced": "6786f18f6ff42aa577c99d86", +"5:orders_model_12.has_model": "b5bea41b6c623f7c09f1bf24", +"60:orders_model_14.has_model": "b5bea41b6c623f7c09f1bf24", +"61:orders_model_14.has_star": "fcbcf165908dd18a9e49f7ff", +"62:orders_model_14.edge_count": "d4735e3a265e16eee03f5971", +"63:orders_model_14.targeting": "906c9537cb6a0320a5145beb", +"64:orders_model_14.sourced": "6786f18f6ff42aa577c99d86", +"65:orders_model_2.has_model": "b5bea41b6c623f7c09f1bf24", +"66:orders_model_2.has_star": "fcbcf165908dd18a9e49f7ff", +"67:orders_model_2.edge_count": "6b86b273ff34fce19d6b804e", +"68:orders_model_2.targeting": "ab366fc8e364e0827653c9de", +"69:orders_model_2.sourced": "9fd9dbb60bf071aa3417a06f", +"6:orders_model_12.has_star": "fcbcf165908dd18a9e49f7ff", +"70:orders_model_5.has_model": "b5bea41b6c623f7c09f1bf24", +"71:orders_model_5.has_star": "fcbcf165908dd18a9e49f7ff", +"72:orders_model_5.edge_count": "d4735e3a265e16eee03f5971", +"73:orders_model_5.targeting": "415c0d50fd79d684f7e738ac", +"74:orders_model_5.sourced": "6786f18f6ff42aa577c99d86", +"75:orders_model_8.has_model": "b5bea41b6c623f7c09f1bf24", +"76:orders_model_8.has_star": "b5bea41b6c623f7c09f1bf24", +"77:orders_model_8.edge_count": "6b86b273ff34fce19d6b804e", +"78:orders_model_8.targeting": "bd62b4f2d8abfbc93f9a9d9b", +"79:orders_model_8.sourced": "6786f18f6ff42aa577c99d86", +"7:orders_model_12.edge_count": "d4735e3a265e16eee03f5971", +"80:models": "92046d27e611a2b8961bfcc5", +"81:edges": "9c2ff0e1313dd442bb1ac017", +"8:orders_model_12.targeting": "de72923afa7d269dec06170d", +"9:orders_model_12.sourced": "6786f18f6ff42aa577c99d86" +} +], +[ +"lineage", +{ +"0:orders_model_0.has_model": "fcbcf165908dd18a9e49f7ff", +"10:orders_model_15.has_model": "b5bea41b6c623f7c09f1bf24", +"11:orders_model_15.has_star": "fcbcf165908dd18a9e49f7ff", +"12:orders_model_15.edge_count": "4e07408562bedb8b60ce05c1", +"13:orders_model_15.targeting": "8fe2f3d0a303eca5503031b5", +"14:orders_model_15.sourced": "6786f18f6ff42aa577c99d86", +"15:orders_model_3.has_model": "fcbcf165908dd18a9e49f7ff", +"16:orders_model_3.has_star": "fcbcf165908dd18a9e49f7ff", +"17:orders_model_3.edge_count": "5feceb66ffc86f38d952786c", +"18:orders_model_3.targeting": "6786f18f6ff42aa577c99d86", +"19:orders_model_3.sourced": "6786f18f6ff42aa577c99d86", +"1:orders_model_0.has_star": "fcbcf165908dd18a9e49f7ff", +"20:orders_model_6.has_model": "fcbcf165908dd18a9e49f7ff", +"21:orders_model_6.has_star": "fcbcf165908dd18a9e49f7ff", +"22:orders_model_6.edge_count": "5feceb66ffc86f38d952786c", +"23:orders_model_6.targeting": "6786f18f6ff42aa577c99d86", +"24:orders_model_6.sourced": "a967e822b57213ec858768ca", +"25:orders_model_9.has_model": "b5bea41b6c623f7c09f1bf24", +"26:orders_model_9.has_star": "b5bea41b6c623f7c09f1bf24", +"27:orders_model_9.edge_count": "ef2d127de37b942baad06145", +"28:orders_model_9.targeting": "a967e822b57213ec858768ca", +"29:orders_model_9.sourced": "6bbb8ae1c03cae3174007e24", +"2:orders_model_0.edge_count": "5feceb66ffc86f38d952786c", +"30:orders_model_1.has_model": "b5bea41b6c623f7c09f1bf24", +"31:orders_model_1.has_star": "b5bea41b6c623f7c09f1bf24", +"32:orders_model_1.edge_count": "ef2d127de37b942baad06145", +"33:orders_model_1.targeting": "bbedd18bce59f23468d191c5", +"34:orders_model_1.sourced": "98471e4c377a8d5d7068e4ec", +"35:orders_model_10.has_model": "fcbcf165908dd18a9e49f7ff", +"36:orders_model_10.has_star": "fcbcf165908dd18a9e49f7ff", +"37:orders_model_10.edge_count": "5feceb66ffc86f38d952786c", +"38:orders_model_10.targeting": "6786f18f6ff42aa577c99d86", +"39:orders_model_10.sourced": "6786f18f6ff42aa577c99d86", +"3:orders_model_0.targeting": "6786f18f6ff42aa577c99d86", +"40:orders_model_13.has_model": "fcbcf165908dd18a9e49f7ff", +"41:orders_model_13.has_star": "fcbcf165908dd18a9e49f7ff", +"42:orders_model_13.edge_count": "5feceb66ffc86f38d952786c", +"43:orders_model_13.targeting": "6786f18f6ff42aa577c99d86", +"44:orders_model_13.sourced": "6786f18f6ff42aa577c99d86", +"45:orders_model_4.has_model": "fcbcf165908dd18a9e49f7ff", +"46:orders_model_4.has_star": "fcbcf165908dd18a9e49f7ff", +"47:orders_model_4.edge_count": "5feceb66ffc86f38d952786c", +"48:orders_model_4.targeting": "6786f18f6ff42aa577c99d86", +"49:orders_model_4.sourced": "415c0d50fd79d684f7e738ac", +"4:orders_model_0.sourced": "dee9dc3632e9c38c6ba815ac", +"50:orders_model_7.has_model": "fcbcf165908dd18a9e49f7ff", +"51:orders_model_7.has_star": "fcbcf165908dd18a9e49f7ff", +"52:orders_model_7.edge_count": "5feceb66ffc86f38d952786c", +"53:orders_model_7.targeting": "6786f18f6ff42aa577c99d86", +"54:orders_model_7.sourced": "6786f18f6ff42aa577c99d86", +"55:orders_model_11.has_model": "b5bea41b6c623f7c09f1bf24", +"56:orders_model_11.has_star": "fcbcf165908dd18a9e49f7ff", +"57:orders_model_11.edge_count": "6b86b273ff34fce19d6b804e", +"58:orders_model_11.targeting": "71a6cc1ef787af00586cdf2e", +"59:orders_model_11.sourced": "6786f18f6ff42aa577c99d86", +"5:orders_model_12.has_model": "b5bea41b6c623f7c09f1bf24", +"60:orders_model_14.has_model": "fcbcf165908dd18a9e49f7ff", +"61:orders_model_14.has_star": "fcbcf165908dd18a9e49f7ff", +"62:orders_model_14.edge_count": "5feceb66ffc86f38d952786c", +"63:orders_model_14.targeting": "6786f18f6ff42aa577c99d86", +"64:orders_model_14.sourced": "6786f18f6ff42aa577c99d86", +"65:orders_model_2.has_model": "b5bea41b6c623f7c09f1bf24", +"66:orders_model_2.has_star": "fcbcf165908dd18a9e49f7ff", +"67:orders_model_2.edge_count": "6b86b273ff34fce19d6b804e", +"68:orders_model_2.targeting": "ab366fc8e364e0827653c9de", +"69:orders_model_2.sourced": "bd62b4f2d8abfbc93f9a9d9b", +"6:orders_model_12.has_star": "fcbcf165908dd18a9e49f7ff", +"70:orders_model_5.has_model": "b5bea41b6c623f7c09f1bf24", +"71:orders_model_5.has_star": "fcbcf165908dd18a9e49f7ff", +"72:orders_model_5.edge_count": "d4735e3a265e16eee03f5971", +"73:orders_model_5.targeting": "415c0d50fd79d684f7e738ac", +"74:orders_model_5.sourced": "6786f18f6ff42aa577c99d86", +"75:orders_model_8.has_model": "b5bea41b6c623f7c09f1bf24", +"76:orders_model_8.has_star": "b5bea41b6c623f7c09f1bf24", +"77:orders_model_8.edge_count": "6b86b273ff34fce19d6b804e", +"78:orders_model_8.targeting": "bd62b4f2d8abfbc93f9a9d9b", +"79:orders_model_8.sourced": "6786f18f6ff42aa577c99d86", +"7:orders_model_12.edge_count": "d4735e3a265e16eee03f5971", +"80:models": "9cc5472deaed036c6f68e314", +"81:edges": "1960382314765257e21dd758", +"8:orders_model_12.targeting": "de72923afa7d269dec06170d", +"9:orders_model_12.sourced": "6786f18f6ff42aa577c99d86" +} +], +[ +"lineage", +{ +"0:orders_model_0.has_model": "b5bea41b6c623f7c09f1bf24", +"10:orders_model_15.has_model": "b5bea41b6c623f7c09f1bf24", +"11:orders_model_15.has_star": "fcbcf165908dd18a9e49f7ff", +"12:orders_model_15.edge_count": "4e07408562bedb8b60ce05c1", +"13:orders_model_15.targeting": "8fe2f3d0a303eca5503031b5", +"14:orders_model_15.sourced": "6786f18f6ff42aa577c99d86", +"15:orders_model_3.has_model": "b5bea41b6c623f7c09f1bf24", +"16:orders_model_3.has_star": "fcbcf165908dd18a9e49f7ff", +"17:orders_model_3.edge_count": "d4735e3a265e16eee03f5971", +"18:orders_model_3.targeting": "1ff64b327984da82f76cce2e", +"19:orders_model_3.sourced": "6786f18f6ff42aa577c99d86", +"1:orders_model_0.has_star": "b5bea41b6c623f7c09f1bf24", +"20:orders_model_6.has_model": "b5bea41b6c623f7c09f1bf24", +"21:orders_model_6.has_star": "fcbcf165908dd18a9e49f7ff", +"22:orders_model_6.edge_count": "4e07408562bedb8b60ce05c1", +"23:orders_model_6.targeting": "0fcf4ef01f4ca62bb77c3d80", +"24:orders_model_6.sourced": "a967e822b57213ec858768ca", +"25:orders_model_9.has_model": "b5bea41b6c623f7c09f1bf24", +"26:orders_model_9.has_star": "b5bea41b6c623f7c09f1bf24", +"27:orders_model_9.edge_count": "ef2d127de37b942baad06145", +"28:orders_model_9.targeting": "a967e822b57213ec858768ca", +"29:orders_model_9.sourced": "6bbb8ae1c03cae3174007e24", +"2:orders_model_0.edge_count": "4e07408562bedb8b60ce05c1", +"30:orders_model_1.has_model": "b5bea41b6c623f7c09f1bf24", +"31:orders_model_1.has_star": "b5bea41b6c623f7c09f1bf24", +"32:orders_model_1.edge_count": "ef2d127de37b942baad06145", +"33:orders_model_1.targeting": "bbedd18bce59f23468d191c5", +"34:orders_model_1.sourced": "0c1d78a57ca6b9e16bcd6266", +"35:orders_model_10.has_model": "b5bea41b6c623f7c09f1bf24", +"36:orders_model_10.has_star": "b5bea41b6c623f7c09f1bf24", +"37:orders_model_10.edge_count": "ef2d127de37b942baad06145", +"38:orders_model_10.targeting": "2591b6af4aaafcb322150ab2", +"39:orders_model_10.sourced": "6786f18f6ff42aa577c99d86", +"3:orders_model_0.targeting": "d11526ad01eb59472574a2a3", +"40:orders_model_13.has_model": "b5bea41b6c623f7c09f1bf24", +"41:orders_model_13.has_star": "b5bea41b6c623f7c09f1bf24", +"42:orders_model_13.edge_count": "4e07408562bedb8b60ce05c1", +"43:orders_model_13.targeting": "c5bd06cf3f6a094d7fb244f2", +"44:orders_model_13.sourced": "6786f18f6ff42aa577c99d86", +"45:orders_model_4.has_model": "b5bea41b6c623f7c09f1bf24", +"46:orders_model_4.has_star": "b5bea41b6c623f7c09f1bf24", +"47:orders_model_4.edge_count": "d4735e3a265e16eee03f5971", +"48:orders_model_4.targeting": "1aa2dcab73d2bc39dc008009", +"49:orders_model_4.sourced": "64ca73dda13db25820ee20e0", +"4:orders_model_0.sourced": "8bcc9afb9b2508beebd187ed", +"50:orders_model_7.has_model": "b5bea41b6c623f7c09f1bf24", +"51:orders_model_7.has_star": "fcbcf165908dd18a9e49f7ff", +"52:orders_model_7.edge_count": "7902699be42c8a8e46fbbb45", +"53:orders_model_7.targeting": "79896e5d232604aea741ec1b", +"54:orders_model_7.sourced": "6786f18f6ff42aa577c99d86", +"55:orders_model_11.has_model": "b5bea41b6c623f7c09f1bf24", +"56:orders_model_11.has_star": "fcbcf165908dd18a9e49f7ff", +"57:orders_model_11.edge_count": "6b86b273ff34fce19d6b804e", +"58:orders_model_11.targeting": "71a6cc1ef787af00586cdf2e", +"59:orders_model_11.sourced": "6786f18f6ff42aa577c99d86", +"5:orders_model_12.has_model": "b5bea41b6c623f7c09f1bf24", +"60:orders_model_14.has_model": "b5bea41b6c623f7c09f1bf24", +"61:orders_model_14.has_star": "fcbcf165908dd18a9e49f7ff", +"62:orders_model_14.edge_count": "d4735e3a265e16eee03f5971", +"63:orders_model_14.targeting": "906c9537cb6a0320a5145beb", +"64:orders_model_14.sourced": "6786f18f6ff42aa577c99d86", +"65:orders_model_2.has_model": "b5bea41b6c623f7c09f1bf24", +"66:orders_model_2.has_star": "fcbcf165908dd18a9e49f7ff", +"67:orders_model_2.edge_count": "6b86b273ff34fce19d6b804e", +"68:orders_model_2.targeting": "ab366fc8e364e0827653c9de", +"69:orders_model_2.sourced": "9fd9dbb60bf071aa3417a06f", +"6:orders_model_12.has_star": "fcbcf165908dd18a9e49f7ff", +"70:orders_model_5.has_model": "b5bea41b6c623f7c09f1bf24", +"71:orders_model_5.has_star": "fcbcf165908dd18a9e49f7ff", +"72:orders_model_5.edge_count": "d4735e3a265e16eee03f5971", +"73:orders_model_5.targeting": "415c0d50fd79d684f7e738ac", +"74:orders_model_5.sourced": "6786f18f6ff42aa577c99d86", +"75:orders_model_8.has_model": "b5bea41b6c623f7c09f1bf24", +"76:orders_model_8.has_star": "b5bea41b6c623f7c09f1bf24", +"77:orders_model_8.edge_count": "6b86b273ff34fce19d6b804e", +"78:orders_model_8.targeting": "bd62b4f2d8abfbc93f9a9d9b", +"79:orders_model_8.sourced": "6786f18f6ff42aa577c99d86", +"7:orders_model_12.edge_count": "d4735e3a265e16eee03f5971", +"80:models": "92046d27e611a2b8961bfcc5", +"81:edges": "9c2ff0e1313dd442bb1ac017", +"8:orders_model_12.targeting": "de72923afa7d269dec06170d", +"9:orders_model_12.sourced": "6786f18f6ff42aa577c99d86" +} +], +[ +"lineage", +{ +"0:orders_model_0.has_model": "fcbcf165908dd18a9e49f7ff", +"10:orders_model_15.has_model": "b5bea41b6c623f7c09f1bf24", +"11:orders_model_15.has_star": "fcbcf165908dd18a9e49f7ff", +"12:orders_model_15.edge_count": "4e07408562bedb8b60ce05c1", +"13:orders_model_15.targeting": "8fe2f3d0a303eca5503031b5", +"14:orders_model_15.sourced": "6786f18f6ff42aa577c99d86", +"15:orders_model_3.has_model": "fcbcf165908dd18a9e49f7ff", +"16:orders_model_3.has_star": "fcbcf165908dd18a9e49f7ff", +"17:orders_model_3.edge_count": "5feceb66ffc86f38d952786c", +"18:orders_model_3.targeting": "6786f18f6ff42aa577c99d86", +"19:orders_model_3.sourced": "6786f18f6ff42aa577c99d86", +"1:orders_model_0.has_star": "fcbcf165908dd18a9e49f7ff", +"20:orders_model_6.has_model": "fcbcf165908dd18a9e49f7ff", +"21:orders_model_6.has_star": "fcbcf165908dd18a9e49f7ff", +"22:orders_model_6.edge_count": "5feceb66ffc86f38d952786c", +"23:orders_model_6.targeting": "6786f18f6ff42aa577c99d86", +"24:orders_model_6.sourced": "a967e822b57213ec858768ca", +"25:orders_model_9.has_model": "b5bea41b6c623f7c09f1bf24", +"26:orders_model_9.has_star": "b5bea41b6c623f7c09f1bf24", +"27:orders_model_9.edge_count": "ef2d127de37b942baad06145", +"28:orders_model_9.targeting": "a967e822b57213ec858768ca", +"29:orders_model_9.sourced": "6bbb8ae1c03cae3174007e24", +"2:orders_model_0.edge_count": "5feceb66ffc86f38d952786c", +"30:orders_model_1.has_model": "b5bea41b6c623f7c09f1bf24", +"31:orders_model_1.has_star": "b5bea41b6c623f7c09f1bf24", +"32:orders_model_1.edge_count": "ef2d127de37b942baad06145", +"33:orders_model_1.targeting": "bbedd18bce59f23468d191c5", +"34:orders_model_1.sourced": "98471e4c377a8d5d7068e4ec", +"35:orders_model_10.has_model": "fcbcf165908dd18a9e49f7ff", +"36:orders_model_10.has_star": "fcbcf165908dd18a9e49f7ff", +"37:orders_model_10.edge_count": "5feceb66ffc86f38d952786c", +"38:orders_model_10.targeting": "6786f18f6ff42aa577c99d86", +"39:orders_model_10.sourced": "6786f18f6ff42aa577c99d86", +"3:orders_model_0.targeting": "6786f18f6ff42aa577c99d86", +"40:orders_model_13.has_model": "fcbcf165908dd18a9e49f7ff", +"41:orders_model_13.has_star": "fcbcf165908dd18a9e49f7ff", +"42:orders_model_13.edge_count": "5feceb66ffc86f38d952786c", +"43:orders_model_13.targeting": "6786f18f6ff42aa577c99d86", +"44:orders_model_13.sourced": "6786f18f6ff42aa577c99d86", +"45:orders_model_4.has_model": "fcbcf165908dd18a9e49f7ff", +"46:orders_model_4.has_star": "fcbcf165908dd18a9e49f7ff", +"47:orders_model_4.edge_count": "5feceb66ffc86f38d952786c", +"48:orders_model_4.targeting": "6786f18f6ff42aa577c99d86", +"49:orders_model_4.sourced": "415c0d50fd79d684f7e738ac", +"4:orders_model_0.sourced": "dee9dc3632e9c38c6ba815ac", +"50:orders_model_7.has_model": "fcbcf165908dd18a9e49f7ff", +"51:orders_model_7.has_star": "fcbcf165908dd18a9e49f7ff", +"52:orders_model_7.edge_count": "5feceb66ffc86f38d952786c", +"53:orders_model_7.targeting": "6786f18f6ff42aa577c99d86", +"54:orders_model_7.sourced": "6786f18f6ff42aa577c99d86", +"55:orders_model_11.has_model": "b5bea41b6c623f7c09f1bf24", +"56:orders_model_11.has_star": "fcbcf165908dd18a9e49f7ff", +"57:orders_model_11.edge_count": "6b86b273ff34fce19d6b804e", +"58:orders_model_11.targeting": "71a6cc1ef787af00586cdf2e", +"59:orders_model_11.sourced": "6786f18f6ff42aa577c99d86", +"5:orders_model_12.has_model": "b5bea41b6c623f7c09f1bf24", +"60:orders_model_14.has_model": "fcbcf165908dd18a9e49f7ff", +"61:orders_model_14.has_star": "fcbcf165908dd18a9e49f7ff", +"62:orders_model_14.edge_count": "5feceb66ffc86f38d952786c", +"63:orders_model_14.targeting": "6786f18f6ff42aa577c99d86", +"64:orders_model_14.sourced": "6786f18f6ff42aa577c99d86", +"65:orders_model_2.has_model": "b5bea41b6c623f7c09f1bf24", +"66:orders_model_2.has_star": "fcbcf165908dd18a9e49f7ff", +"67:orders_model_2.edge_count": "6b86b273ff34fce19d6b804e", +"68:orders_model_2.targeting": "ab366fc8e364e0827653c9de", +"69:orders_model_2.sourced": "bd62b4f2d8abfbc93f9a9d9b", +"6:orders_model_12.has_star": "fcbcf165908dd18a9e49f7ff", +"70:orders_model_5.has_model": "b5bea41b6c623f7c09f1bf24", +"71:orders_model_5.has_star": "fcbcf165908dd18a9e49f7ff", +"72:orders_model_5.edge_count": "d4735e3a265e16eee03f5971", +"73:orders_model_5.targeting": "415c0d50fd79d684f7e738ac", +"74:orders_model_5.sourced": "6786f18f6ff42aa577c99d86", +"75:orders_model_8.has_model": "b5bea41b6c623f7c09f1bf24", +"76:orders_model_8.has_star": "b5bea41b6c623f7c09f1bf24", +"77:orders_model_8.edge_count": "6b86b273ff34fce19d6b804e", +"78:orders_model_8.targeting": "bd62b4f2d8abfbc93f9a9d9b", +"79:orders_model_8.sourced": "6786f18f6ff42aa577c99d86", +"7:orders_model_12.edge_count": "d4735e3a265e16eee03f5971", +"80:models": "9cc5472deaed036c6f68e314", +"81:edges": "1960382314765257e21dd758", +"8:orders_model_12.targeting": "de72923afa7d269dec06170d", +"9:orders_model_12.sourced": "6786f18f6ff42aa577c99d86" +} +], +[ +"lineage", +{ +"0:orders_model_0.has_model": "b5bea41b6c623f7c09f1bf24", +"10:orders_model_15.has_model": "b5bea41b6c623f7c09f1bf24", +"11:orders_model_15.has_star": "fcbcf165908dd18a9e49f7ff", +"12:orders_model_15.edge_count": "4e07408562bedb8b60ce05c1", +"13:orders_model_15.targeting": "8fe2f3d0a303eca5503031b5", +"14:orders_model_15.sourced": "6786f18f6ff42aa577c99d86", +"15:orders_model_3.has_model": "b5bea41b6c623f7c09f1bf24", +"16:orders_model_3.has_star": "fcbcf165908dd18a9e49f7ff", +"17:orders_model_3.edge_count": "d4735e3a265e16eee03f5971", +"18:orders_model_3.targeting": "1ff64b327984da82f76cce2e", +"19:orders_model_3.sourced": "6786f18f6ff42aa577c99d86", +"1:orders_model_0.has_star": "b5bea41b6c623f7c09f1bf24", +"20:orders_model_6.has_model": "b5bea41b6c623f7c09f1bf24", +"21:orders_model_6.has_star": "fcbcf165908dd18a9e49f7ff", +"22:orders_model_6.edge_count": "4e07408562bedb8b60ce05c1", +"23:orders_model_6.targeting": "0fcf4ef01f4ca62bb77c3d80", +"24:orders_model_6.sourced": "a967e822b57213ec858768ca", +"25:orders_model_9.has_model": "b5bea41b6c623f7c09f1bf24", +"26:orders_model_9.has_star": "b5bea41b6c623f7c09f1bf24", +"27:orders_model_9.edge_count": "ef2d127de37b942baad06145", +"28:orders_model_9.targeting": "a967e822b57213ec858768ca", +"29:orders_model_9.sourced": "6bbb8ae1c03cae3174007e24", +"2:orders_model_0.edge_count": "4e07408562bedb8b60ce05c1", +"30:orders_model_1.has_model": "b5bea41b6c623f7c09f1bf24", +"31:orders_model_1.has_star": "b5bea41b6c623f7c09f1bf24", +"32:orders_model_1.edge_count": "ef2d127de37b942baad06145", +"33:orders_model_1.targeting": "bbedd18bce59f23468d191c5", +"34:orders_model_1.sourced": "0c1d78a57ca6b9e16bcd6266", +"35:orders_model_10.has_model": "b5bea41b6c623f7c09f1bf24", +"36:orders_model_10.has_star": "b5bea41b6c623f7c09f1bf24", +"37:orders_model_10.edge_count": "ef2d127de37b942baad06145", +"38:orders_model_10.targeting": "2591b6af4aaafcb322150ab2", +"39:orders_model_10.sourced": "6786f18f6ff42aa577c99d86", +"3:orders_model_0.targeting": "d11526ad01eb59472574a2a3", +"40:orders_model_13.has_model": "b5bea41b6c623f7c09f1bf24", +"41:orders_model_13.has_star": "b5bea41b6c623f7c09f1bf24", +"42:orders_model_13.edge_count": "4e07408562bedb8b60ce05c1", +"43:orders_model_13.targeting": "c5bd06cf3f6a094d7fb244f2", +"44:orders_model_13.sourced": "6786f18f6ff42aa577c99d86", +"45:orders_model_4.has_model": "b5bea41b6c623f7c09f1bf24", +"46:orders_model_4.has_star": "b5bea41b6c623f7c09f1bf24", +"47:orders_model_4.edge_count": "d4735e3a265e16eee03f5971", +"48:orders_model_4.targeting": "1aa2dcab73d2bc39dc008009", +"49:orders_model_4.sourced": "64ca73dda13db25820ee20e0", +"4:orders_model_0.sourced": "8bcc9afb9b2508beebd187ed", +"50:orders_model_7.has_model": "b5bea41b6c623f7c09f1bf24", +"51:orders_model_7.has_star": "fcbcf165908dd18a9e49f7ff", +"52:orders_model_7.edge_count": "7902699be42c8a8e46fbbb45", +"53:orders_model_7.targeting": "79896e5d232604aea741ec1b", +"54:orders_model_7.sourced": "6786f18f6ff42aa577c99d86", +"55:orders_model_11.has_model": "b5bea41b6c623f7c09f1bf24", +"56:orders_model_11.has_star": "fcbcf165908dd18a9e49f7ff", +"57:orders_model_11.edge_count": "6b86b273ff34fce19d6b804e", +"58:orders_model_11.targeting": "71a6cc1ef787af00586cdf2e", +"59:orders_model_11.sourced": "6786f18f6ff42aa577c99d86", +"5:orders_model_12.has_model": "b5bea41b6c623f7c09f1bf24", +"60:orders_model_14.has_model": "b5bea41b6c623f7c09f1bf24", +"61:orders_model_14.has_star": "fcbcf165908dd18a9e49f7ff", +"62:orders_model_14.edge_count": "d4735e3a265e16eee03f5971", +"63:orders_model_14.targeting": "906c9537cb6a0320a5145beb", +"64:orders_model_14.sourced": "6786f18f6ff42aa577c99d86", +"65:orders_model_2.has_model": "b5bea41b6c623f7c09f1bf24", +"66:orders_model_2.has_star": "fcbcf165908dd18a9e49f7ff", +"67:orders_model_2.edge_count": "6b86b273ff34fce19d6b804e", +"68:orders_model_2.targeting": "ab366fc8e364e0827653c9de", +"69:orders_model_2.sourced": "9fd9dbb60bf071aa3417a06f", +"6:orders_model_12.has_star": "fcbcf165908dd18a9e49f7ff", +"70:orders_model_5.has_model": "b5bea41b6c623f7c09f1bf24", +"71:orders_model_5.has_star": "fcbcf165908dd18a9e49f7ff", +"72:orders_model_5.edge_count": "d4735e3a265e16eee03f5971", +"73:orders_model_5.targeting": "415c0d50fd79d684f7e738ac", +"74:orders_model_5.sourced": "6786f18f6ff42aa577c99d86", +"75:orders_model_8.has_model": "b5bea41b6c623f7c09f1bf24", +"76:orders_model_8.has_star": "b5bea41b6c623f7c09f1bf24", +"77:orders_model_8.edge_count": "6b86b273ff34fce19d6b804e", +"78:orders_model_8.targeting": "bd62b4f2d8abfbc93f9a9d9b", +"79:orders_model_8.sourced": "6786f18f6ff42aa577c99d86", +"7:orders_model_12.edge_count": "d4735e3a265e16eee03f5971", +"80:models": "92046d27e611a2b8961bfcc5", +"81:edges": "9c2ff0e1313dd442bb1ac017", +"8:orders_model_12.targeting": "de72923afa7d269dec06170d", +"9:orders_model_12.sourced": "6786f18f6ff42aa577c99d86" +} +], +[ +"lineage", +{ +"0:orders_model_0.has_model": "fcbcf165908dd18a9e49f7ff", +"10:orders_model_15.has_model": "b5bea41b6c623f7c09f1bf24", +"11:orders_model_15.has_star": "fcbcf165908dd18a9e49f7ff", +"12:orders_model_15.edge_count": "4e07408562bedb8b60ce05c1", +"13:orders_model_15.targeting": "8fe2f3d0a303eca5503031b5", +"14:orders_model_15.sourced": "6786f18f6ff42aa577c99d86", +"15:orders_model_3.has_model": "fcbcf165908dd18a9e49f7ff", +"16:orders_model_3.has_star": "fcbcf165908dd18a9e49f7ff", +"17:orders_model_3.edge_count": "5feceb66ffc86f38d952786c", +"18:orders_model_3.targeting": "6786f18f6ff42aa577c99d86", +"19:orders_model_3.sourced": "6786f18f6ff42aa577c99d86", +"1:orders_model_0.has_star": "fcbcf165908dd18a9e49f7ff", +"20:orders_model_6.has_model": "fcbcf165908dd18a9e49f7ff", +"21:orders_model_6.has_star": "fcbcf165908dd18a9e49f7ff", +"22:orders_model_6.edge_count": "5feceb66ffc86f38d952786c", +"23:orders_model_6.targeting": "6786f18f6ff42aa577c99d86", +"24:orders_model_6.sourced": "a967e822b57213ec858768ca", +"25:orders_model_9.has_model": "b5bea41b6c623f7c09f1bf24", +"26:orders_model_9.has_star": "b5bea41b6c623f7c09f1bf24", +"27:orders_model_9.edge_count": "ef2d127de37b942baad06145", +"28:orders_model_9.targeting": "a967e822b57213ec858768ca", +"29:orders_model_9.sourced": "6bbb8ae1c03cae3174007e24", +"2:orders_model_0.edge_count": "5feceb66ffc86f38d952786c", +"30:orders_model_1.has_model": "b5bea41b6c623f7c09f1bf24", +"31:orders_model_1.has_star": "b5bea41b6c623f7c09f1bf24", +"32:orders_model_1.edge_count": "ef2d127de37b942baad06145", +"33:orders_model_1.targeting": "bbedd18bce59f23468d191c5", +"34:orders_model_1.sourced": "98471e4c377a8d5d7068e4ec", +"35:orders_model_10.has_model": "fcbcf165908dd18a9e49f7ff", +"36:orders_model_10.has_star": "fcbcf165908dd18a9e49f7ff", +"37:orders_model_10.edge_count": "5feceb66ffc86f38d952786c", +"38:orders_model_10.targeting": "6786f18f6ff42aa577c99d86", +"39:orders_model_10.sourced": "6786f18f6ff42aa577c99d86", +"3:orders_model_0.targeting": "6786f18f6ff42aa577c99d86", +"40:orders_model_13.has_model": "fcbcf165908dd18a9e49f7ff", +"41:orders_model_13.has_star": "fcbcf165908dd18a9e49f7ff", +"42:orders_model_13.edge_count": "5feceb66ffc86f38d952786c", +"43:orders_model_13.targeting": "6786f18f6ff42aa577c99d86", +"44:orders_model_13.sourced": "6786f18f6ff42aa577c99d86", +"45:orders_model_4.has_model": "fcbcf165908dd18a9e49f7ff", +"46:orders_model_4.has_star": "fcbcf165908dd18a9e49f7ff", +"47:orders_model_4.edge_count": "5feceb66ffc86f38d952786c", +"48:orders_model_4.targeting": "6786f18f6ff42aa577c99d86", +"49:orders_model_4.sourced": "415c0d50fd79d684f7e738ac", +"4:orders_model_0.sourced": "dee9dc3632e9c38c6ba815ac", +"50:orders_model_7.has_model": "fcbcf165908dd18a9e49f7ff", +"51:orders_model_7.has_star": "fcbcf165908dd18a9e49f7ff", +"52:orders_model_7.edge_count": "5feceb66ffc86f38d952786c", +"53:orders_model_7.targeting": "6786f18f6ff42aa577c99d86", +"54:orders_model_7.sourced": "6786f18f6ff42aa577c99d86", +"55:orders_model_11.has_model": "b5bea41b6c623f7c09f1bf24", +"56:orders_model_11.has_star": "fcbcf165908dd18a9e49f7ff", +"57:orders_model_11.edge_count": "6b86b273ff34fce19d6b804e", +"58:orders_model_11.targeting": "71a6cc1ef787af00586cdf2e", +"59:orders_model_11.sourced": "6786f18f6ff42aa577c99d86", +"5:orders_model_12.has_model": "b5bea41b6c623f7c09f1bf24", +"60:orders_model_14.has_model": "fcbcf165908dd18a9e49f7ff", +"61:orders_model_14.has_star": "fcbcf165908dd18a9e49f7ff", +"62:orders_model_14.edge_count": "5feceb66ffc86f38d952786c", +"63:orders_model_14.targeting": "6786f18f6ff42aa577c99d86", +"64:orders_model_14.sourced": "6786f18f6ff42aa577c99d86", +"65:orders_model_2.has_model": "b5bea41b6c623f7c09f1bf24", +"66:orders_model_2.has_star": "fcbcf165908dd18a9e49f7ff", +"67:orders_model_2.edge_count": "6b86b273ff34fce19d6b804e", +"68:orders_model_2.targeting": "ab366fc8e364e0827653c9de", +"69:orders_model_2.sourced": "bd62b4f2d8abfbc93f9a9d9b", +"6:orders_model_12.has_star": "fcbcf165908dd18a9e49f7ff", +"70:orders_model_5.has_model": "b5bea41b6c623f7c09f1bf24", +"71:orders_model_5.has_star": "fcbcf165908dd18a9e49f7ff", +"72:orders_model_5.edge_count": "d4735e3a265e16eee03f5971", +"73:orders_model_5.targeting": "415c0d50fd79d684f7e738ac", +"74:orders_model_5.sourced": "6786f18f6ff42aa577c99d86", +"75:orders_model_8.has_model": "b5bea41b6c623f7c09f1bf24", +"76:orders_model_8.has_star": "b5bea41b6c623f7c09f1bf24", +"77:orders_model_8.edge_count": "6b86b273ff34fce19d6b804e", +"78:orders_model_8.targeting": "bd62b4f2d8abfbc93f9a9d9b", +"79:orders_model_8.sourced": "6786f18f6ff42aa577c99d86", +"7:orders_model_12.edge_count": "d4735e3a265e16eee03f5971", +"80:models": "9cc5472deaed036c6f68e314", +"81:edges": "1960382314765257e21dd758", +"8:orders_model_12.targeting": "de72923afa7d269dec06170d", +"9:orders_model_12.sourced": "6786f18f6ff42aa577c99d86" +} +], +[ +"lineage", +{ +"0:orders_model_0.has_model": "b5bea41b6c623f7c09f1bf24", +"10:orders_model_15.has_model": "b5bea41b6c623f7c09f1bf24", +"11:orders_model_15.has_star": "fcbcf165908dd18a9e49f7ff", +"12:orders_model_15.edge_count": "4e07408562bedb8b60ce05c1", +"13:orders_model_15.targeting": "8fe2f3d0a303eca5503031b5", +"14:orders_model_15.sourced": "6786f18f6ff42aa577c99d86", +"15:orders_model_3.has_model": "b5bea41b6c623f7c09f1bf24", +"16:orders_model_3.has_star": "fcbcf165908dd18a9e49f7ff", +"17:orders_model_3.edge_count": "d4735e3a265e16eee03f5971", +"18:orders_model_3.targeting": "1ff64b327984da82f76cce2e", +"19:orders_model_3.sourced": "6786f18f6ff42aa577c99d86", +"1:orders_model_0.has_star": "b5bea41b6c623f7c09f1bf24", +"20:orders_model_6.has_model": "b5bea41b6c623f7c09f1bf24", +"21:orders_model_6.has_star": "fcbcf165908dd18a9e49f7ff", +"22:orders_model_6.edge_count": "4e07408562bedb8b60ce05c1", +"23:orders_model_6.targeting": "0fcf4ef01f4ca62bb77c3d80", +"24:orders_model_6.sourced": "a967e822b57213ec858768ca", +"25:orders_model_9.has_model": "b5bea41b6c623f7c09f1bf24", +"26:orders_model_9.has_star": "b5bea41b6c623f7c09f1bf24", +"27:orders_model_9.edge_count": "ef2d127de37b942baad06145", +"28:orders_model_9.targeting": "a967e822b57213ec858768ca", +"29:orders_model_9.sourced": "6bbb8ae1c03cae3174007e24", +"2:orders_model_0.edge_count": "4e07408562bedb8b60ce05c1", +"30:orders_model_1.has_model": "b5bea41b6c623f7c09f1bf24", +"31:orders_model_1.has_star": "b5bea41b6c623f7c09f1bf24", +"32:orders_model_1.edge_count": "ef2d127de37b942baad06145", +"33:orders_model_1.targeting": "bbedd18bce59f23468d191c5", +"34:orders_model_1.sourced": "0c1d78a57ca6b9e16bcd6266", +"35:orders_model_10.has_model": "b5bea41b6c623f7c09f1bf24", +"36:orders_model_10.has_star": "b5bea41b6c623f7c09f1bf24", +"37:orders_model_10.edge_count": "ef2d127de37b942baad06145", +"38:orders_model_10.targeting": "2591b6af4aaafcb322150ab2", +"39:orders_model_10.sourced": "6786f18f6ff42aa577c99d86", +"3:orders_model_0.targeting": "d11526ad01eb59472574a2a3", +"40:orders_model_13.has_model": "b5bea41b6c623f7c09f1bf24", +"41:orders_model_13.has_star": "b5bea41b6c623f7c09f1bf24", +"42:orders_model_13.edge_count": "4e07408562bedb8b60ce05c1", +"43:orders_model_13.targeting": "c5bd06cf3f6a094d7fb244f2", +"44:orders_model_13.sourced": "6786f18f6ff42aa577c99d86", +"45:orders_model_4.has_model": "b5bea41b6c623f7c09f1bf24", +"46:orders_model_4.has_star": "b5bea41b6c623f7c09f1bf24", +"47:orders_model_4.edge_count": "d4735e3a265e16eee03f5971", +"48:orders_model_4.targeting": "1aa2dcab73d2bc39dc008009", +"49:orders_model_4.sourced": "64ca73dda13db25820ee20e0", +"4:orders_model_0.sourced": "8bcc9afb9b2508beebd187ed", +"50:orders_model_7.has_model": "b5bea41b6c623f7c09f1bf24", +"51:orders_model_7.has_star": "fcbcf165908dd18a9e49f7ff", +"52:orders_model_7.edge_count": "7902699be42c8a8e46fbbb45", +"53:orders_model_7.targeting": "79896e5d232604aea741ec1b", +"54:orders_model_7.sourced": "6786f18f6ff42aa577c99d86", +"55:orders_model_11.has_model": "b5bea41b6c623f7c09f1bf24", +"56:orders_model_11.has_star": "fcbcf165908dd18a9e49f7ff", +"57:orders_model_11.edge_count": "6b86b273ff34fce19d6b804e", +"58:orders_model_11.targeting": "71a6cc1ef787af00586cdf2e", +"59:orders_model_11.sourced": "6786f18f6ff42aa577c99d86", +"5:orders_model_12.has_model": "b5bea41b6c623f7c09f1bf24", +"60:orders_model_14.has_model": "b5bea41b6c623f7c09f1bf24", +"61:orders_model_14.has_star": "fcbcf165908dd18a9e49f7ff", +"62:orders_model_14.edge_count": "d4735e3a265e16eee03f5971", +"63:orders_model_14.targeting": "906c9537cb6a0320a5145beb", +"64:orders_model_14.sourced": "6786f18f6ff42aa577c99d86", +"65:orders_model_2.has_model": "b5bea41b6c623f7c09f1bf24", +"66:orders_model_2.has_star": "fcbcf165908dd18a9e49f7ff", +"67:orders_model_2.edge_count": "6b86b273ff34fce19d6b804e", +"68:orders_model_2.targeting": "ab366fc8e364e0827653c9de", +"69:orders_model_2.sourced": "9fd9dbb60bf071aa3417a06f", +"6:orders_model_12.has_star": "fcbcf165908dd18a9e49f7ff", +"70:orders_model_5.has_model": "b5bea41b6c623f7c09f1bf24", +"71:orders_model_5.has_star": "fcbcf165908dd18a9e49f7ff", +"72:orders_model_5.edge_count": "d4735e3a265e16eee03f5971", +"73:orders_model_5.targeting": "415c0d50fd79d684f7e738ac", +"74:orders_model_5.sourced": "6786f18f6ff42aa577c99d86", +"75:orders_model_8.has_model": "b5bea41b6c623f7c09f1bf24", +"76:orders_model_8.has_star": "b5bea41b6c623f7c09f1bf24", +"77:orders_model_8.edge_count": "6b86b273ff34fce19d6b804e", +"78:orders_model_8.targeting": "bd62b4f2d8abfbc93f9a9d9b", +"79:orders_model_8.sourced": "6786f18f6ff42aa577c99d86", +"7:orders_model_12.edge_count": "d4735e3a265e16eee03f5971", +"80:models": "92046d27e611a2b8961bfcc5", +"81:edges": "9c2ff0e1313dd442bb1ac017", +"8:orders_model_12.targeting": "de72923afa7d269dec06170d", +"9:orders_model_12.sourced": "6786f18f6ff42aa577c99d86" +} +], +[ +"lineage", +{ +"0:orders_model_0.has_model": "fcbcf165908dd18a9e49f7ff", +"10:orders_model_15.has_model": "b5bea41b6c623f7c09f1bf24", +"11:orders_model_15.has_star": "fcbcf165908dd18a9e49f7ff", +"12:orders_model_15.edge_count": "4e07408562bedb8b60ce05c1", +"13:orders_model_15.targeting": "8fe2f3d0a303eca5503031b5", +"14:orders_model_15.sourced": "6786f18f6ff42aa577c99d86", +"15:orders_model_3.has_model": "fcbcf165908dd18a9e49f7ff", +"16:orders_model_3.has_star": "fcbcf165908dd18a9e49f7ff", +"17:orders_model_3.edge_count": "5feceb66ffc86f38d952786c", +"18:orders_model_3.targeting": "6786f18f6ff42aa577c99d86", +"19:orders_model_3.sourced": "6786f18f6ff42aa577c99d86", +"1:orders_model_0.has_star": "fcbcf165908dd18a9e49f7ff", +"20:orders_model_6.has_model": "fcbcf165908dd18a9e49f7ff", +"21:orders_model_6.has_star": "fcbcf165908dd18a9e49f7ff", +"22:orders_model_6.edge_count": "5feceb66ffc86f38d952786c", +"23:orders_model_6.targeting": "6786f18f6ff42aa577c99d86", +"24:orders_model_6.sourced": "a967e822b57213ec858768ca", +"25:orders_model_9.has_model": "b5bea41b6c623f7c09f1bf24", +"26:orders_model_9.has_star": "b5bea41b6c623f7c09f1bf24", +"27:orders_model_9.edge_count": "ef2d127de37b942baad06145", +"28:orders_model_9.targeting": "a967e822b57213ec858768ca", +"29:orders_model_9.sourced": "6bbb8ae1c03cae3174007e24", +"2:orders_model_0.edge_count": "5feceb66ffc86f38d952786c", +"30:orders_model_1.has_model": "b5bea41b6c623f7c09f1bf24", +"31:orders_model_1.has_star": "b5bea41b6c623f7c09f1bf24", +"32:orders_model_1.edge_count": "ef2d127de37b942baad06145", +"33:orders_model_1.targeting": "bbedd18bce59f23468d191c5", +"34:orders_model_1.sourced": "98471e4c377a8d5d7068e4ec", +"35:orders_model_10.has_model": "fcbcf165908dd18a9e49f7ff", +"36:orders_model_10.has_star": "fcbcf165908dd18a9e49f7ff", +"37:orders_model_10.edge_count": "5feceb66ffc86f38d952786c", +"38:orders_model_10.targeting": "6786f18f6ff42aa577c99d86", +"39:orders_model_10.sourced": "6786f18f6ff42aa577c99d86", +"3:orders_model_0.targeting": "6786f18f6ff42aa577c99d86", +"40:orders_model_13.has_model": "fcbcf165908dd18a9e49f7ff", +"41:orders_model_13.has_star": "fcbcf165908dd18a9e49f7ff", +"42:orders_model_13.edge_count": "5feceb66ffc86f38d952786c", +"43:orders_model_13.targeting": "6786f18f6ff42aa577c99d86", +"44:orders_model_13.sourced": "6786f18f6ff42aa577c99d86", +"45:orders_model_4.has_model": "fcbcf165908dd18a9e49f7ff", +"46:orders_model_4.has_star": "fcbcf165908dd18a9e49f7ff", +"47:orders_model_4.edge_count": "5feceb66ffc86f38d952786c", +"48:orders_model_4.targeting": "6786f18f6ff42aa577c99d86", +"49:orders_model_4.sourced": "415c0d50fd79d684f7e738ac", +"4:orders_model_0.sourced": "dee9dc3632e9c38c6ba815ac", +"50:orders_model_7.has_model": "fcbcf165908dd18a9e49f7ff", +"51:orders_model_7.has_star": "fcbcf165908dd18a9e49f7ff", +"52:orders_model_7.edge_count": "5feceb66ffc86f38d952786c", +"53:orders_model_7.targeting": "6786f18f6ff42aa577c99d86", +"54:orders_model_7.sourced": "6786f18f6ff42aa577c99d86", +"55:orders_model_11.has_model": "b5bea41b6c623f7c09f1bf24", +"56:orders_model_11.has_star": "fcbcf165908dd18a9e49f7ff", +"57:orders_model_11.edge_count": "6b86b273ff34fce19d6b804e", +"58:orders_model_11.targeting": "71a6cc1ef787af00586cdf2e", +"59:orders_model_11.sourced": "6786f18f6ff42aa577c99d86", +"5:orders_model_12.has_model": "b5bea41b6c623f7c09f1bf24", +"60:orders_model_14.has_model": "fcbcf165908dd18a9e49f7ff", +"61:orders_model_14.has_star": "fcbcf165908dd18a9e49f7ff", +"62:orders_model_14.edge_count": "5feceb66ffc86f38d952786c", +"63:orders_model_14.targeting": "6786f18f6ff42aa577c99d86", +"64:orders_model_14.sourced": "6786f18f6ff42aa577c99d86", +"65:orders_model_2.has_model": "b5bea41b6c623f7c09f1bf24", +"66:orders_model_2.has_star": "fcbcf165908dd18a9e49f7ff", +"67:orders_model_2.edge_count": "6b86b273ff34fce19d6b804e", +"68:orders_model_2.targeting": "ab366fc8e364e0827653c9de", +"69:orders_model_2.sourced": "bd62b4f2d8abfbc93f9a9d9b", +"6:orders_model_12.has_star": "fcbcf165908dd18a9e49f7ff", +"70:orders_model_5.has_model": "b5bea41b6c623f7c09f1bf24", +"71:orders_model_5.has_star": "fcbcf165908dd18a9e49f7ff", +"72:orders_model_5.edge_count": "d4735e3a265e16eee03f5971", +"73:orders_model_5.targeting": "415c0d50fd79d684f7e738ac", +"74:orders_model_5.sourced": "6786f18f6ff42aa577c99d86", +"75:orders_model_8.has_model": "b5bea41b6c623f7c09f1bf24", +"76:orders_model_8.has_star": "b5bea41b6c623f7c09f1bf24", +"77:orders_model_8.edge_count": "6b86b273ff34fce19d6b804e", +"78:orders_model_8.targeting": "bd62b4f2d8abfbc93f9a9d9b", +"79:orders_model_8.sourced": "6786f18f6ff42aa577c99d86", +"7:orders_model_12.edge_count": "d4735e3a265e16eee03f5971", +"80:models": "9cc5472deaed036c6f68e314", +"81:edges": "1960382314765257e21dd758", +"8:orders_model_12.targeting": "de72923afa7d269dec06170d", +"9:orders_model_12.sourced": "6786f18f6ff42aa577c99d86" +} +], +[ +"lineage", +{ +"0:orders_model_0.has_model": "b5bea41b6c623f7c09f1bf24", +"10:orders_model_15.has_model": "b5bea41b6c623f7c09f1bf24", +"11:orders_model_15.has_star": "fcbcf165908dd18a9e49f7ff", +"12:orders_model_15.edge_count": "4e07408562bedb8b60ce05c1", +"13:orders_model_15.targeting": "1964126d46cdab65c924dd1a", +"14:orders_model_15.sourced": "6786f18f6ff42aa577c99d86", +"15:orders_model_3.has_model": "b5bea41b6c623f7c09f1bf24", +"16:orders_model_3.has_star": "fcbcf165908dd18a9e49f7ff", +"17:orders_model_3.edge_count": "d4735e3a265e16eee03f5971", +"18:orders_model_3.targeting": "844829a9cd0c4a620ba890aa", +"19:orders_model_3.sourced": "7f655ae63057e87b3fa79c3c", +"1:orders_model_0.has_star": "b5bea41b6c623f7c09f1bf24", +"20:orders_model_6.has_model": "b5bea41b6c623f7c09f1bf24", +"21:orders_model_6.has_star": "fcbcf165908dd18a9e49f7ff", +"22:orders_model_6.edge_count": "4e07408562bedb8b60ce05c1", +"23:orders_model_6.targeting": "e38eef92273ee4afe348ad87", +"24:orders_model_6.sourced": "1964126d46cdab65c924dd1a", +"25:orders_model_9.has_model": "b5bea41b6c623f7c09f1bf24", +"26:orders_model_9.has_star": "b5bea41b6c623f7c09f1bf24", +"27:orders_model_9.edge_count": "4e07408562bedb8b60ce05c1", +"28:orders_model_9.targeting": "6ec77a263392a2e5ea8ee05a", +"29:orders_model_9.sourced": "69251b0e05822c5fbcc9d552", +"2:orders_model_0.edge_count": "4e07408562bedb8b60ce05c1", +"30:orders_model_1.has_model": "b5bea41b6c623f7c09f1bf24", +"31:orders_model_1.has_star": "b5bea41b6c623f7c09f1bf24", +"32:orders_model_1.edge_count": "7902699be42c8a8e46fbbb45", +"33:orders_model_1.targeting": "c9904eaf37f8410c86a5700e", +"34:orders_model_1.sourced": "79fe2d0a0a77035de3d04db1", +"35:orders_model_10.has_model": "b5bea41b6c623f7c09f1bf24", +"36:orders_model_10.has_star": "b5bea41b6c623f7c09f1bf24", +"37:orders_model_10.edge_count": "4b227777d4dd1fc61c6f884f", +"38:orders_model_10.targeting": "37bf1d6a9739dac6c07b8f77", +"39:orders_model_10.sourced": "71858f9d94fda04aed071aa0", +"3:orders_model_0.targeting": "4654ad70130bf45723d2b8e6", +"40:orders_model_13.has_model": "b5bea41b6c623f7c09f1bf24", +"41:orders_model_13.has_star": "b5bea41b6c623f7c09f1bf24", +"42:orders_model_13.edge_count": "4e07408562bedb8b60ce05c1", +"43:orders_model_13.targeting": "99579faa128e6c8875362de3", +"44:orders_model_13.sourced": "6786f18f6ff42aa577c99d86", +"45:orders_model_4.has_model": "b5bea41b6c623f7c09f1bf24", +"46:orders_model_4.has_star": "b5bea41b6c623f7c09f1bf24", +"47:orders_model_4.edge_count": "4e07408562bedb8b60ce05c1", +"48:orders_model_4.targeting": "2d45ce46fb153f6a59805da3", +"49:orders_model_4.sourced": "6786f18f6ff42aa577c99d86", +"4:orders_model_0.sourced": "b390008e1f822c92bd0b26de", +"50:orders_model_7.has_model": "b5bea41b6c623f7c09f1bf24", +"51:orders_model_7.has_star": "fcbcf165908dd18a9e49f7ff", +"52:orders_model_7.edge_count": "19581e27de7ced00ff1ce50b", +"53:orders_model_7.targeting": "79fe2d0a0a77035de3d04db1", +"54:orders_model_7.sourced": "6786f18f6ff42aa577c99d86", +"55:orders_model_11.has_model": "b5bea41b6c623f7c09f1bf24", +"56:orders_model_11.has_star": "fcbcf165908dd18a9e49f7ff", +"57:orders_model_11.edge_count": "6b86b273ff34fce19d6b804e", +"58:orders_model_11.targeting": "71858f9d94fda04aed071aa0", +"59:orders_model_11.sourced": "6786f18f6ff42aa577c99d86", +"5:orders_model_12.has_model": "b5bea41b6c623f7c09f1bf24", +"60:orders_model_14.has_model": "b5bea41b6c623f7c09f1bf24", +"61:orders_model_14.has_star": "fcbcf165908dd18a9e49f7ff", +"62:orders_model_14.edge_count": "d4735e3a265e16eee03f5971", +"63:orders_model_14.targeting": "7f655ae63057e87b3fa79c3c", +"64:orders_model_14.sourced": "6786f18f6ff42aa577c99d86", +"65:orders_model_2.has_model": "b5bea41b6c623f7c09f1bf24", +"66:orders_model_2.has_star": "fcbcf165908dd18a9e49f7ff", +"67:orders_model_2.edge_count": "6b86b273ff34fce19d6b804e", +"68:orders_model_2.targeting": "944516a2d4e18b4cc263aa14", +"69:orders_model_2.sourced": "5c53070d70386db96f97a69e", +"6:orders_model_12.has_star": "fcbcf165908dd18a9e49f7ff", +"70:orders_model_5.has_model": "b5bea41b6c623f7c09f1bf24", +"71:orders_model_5.has_star": "fcbcf165908dd18a9e49f7ff", +"72:orders_model_5.edge_count": "d4735e3a265e16eee03f5971", +"73:orders_model_5.targeting": "2a6f7207b52f1b1ffe6d2ca0", +"74:orders_model_5.sourced": "e38eef92273ee4afe348ad87", +"75:orders_model_8.has_model": "b5bea41b6c623f7c09f1bf24", +"76:orders_model_8.has_star": "b5bea41b6c623f7c09f1bf24", +"77:orders_model_8.edge_count": "4e07408562bedb8b60ce05c1", +"78:orders_model_8.targeting": "46d90f7d3dfc791867204a4c", +"79:orders_model_8.sourced": "6786f18f6ff42aa577c99d86", +"7:orders_model_12.edge_count": "d4735e3a265e16eee03f5971", +"80:models": "37d91f3ee68d4dc24cff6ae3", +"81:edges": "13f3bb62cb14932238e532fe", +"8:orders_model_12.targeting": "235f9bd1bde8e82fc2f4a84f", +"9:orders_model_12.sourced": "6786f18f6ff42aa577c99d86" +} +], +[ +"lineage", +{ +"0:orders_model_0.has_model": "b5bea41b6c623f7c09f1bf24", +"10:orders_model_15.has_model": "b5bea41b6c623f7c09f1bf24", +"11:orders_model_15.has_star": "fcbcf165908dd18a9e49f7ff", +"12:orders_model_15.edge_count": "4e07408562bedb8b60ce05c1", +"13:orders_model_15.targeting": "1964126d46cdab65c924dd1a", +"14:orders_model_15.sourced": "6786f18f6ff42aa577c99d86", +"15:orders_model_3.has_model": "b5bea41b6c623f7c09f1bf24", +"16:orders_model_3.has_star": "fcbcf165908dd18a9e49f7ff", +"17:orders_model_3.edge_count": "d4735e3a265e16eee03f5971", +"18:orders_model_3.targeting": "844829a9cd0c4a620ba890aa", +"19:orders_model_3.sourced": "6786f18f6ff42aa577c99d86", +"1:orders_model_0.has_star": "b5bea41b6c623f7c09f1bf24", +"20:orders_model_6.has_model": "fcbcf165908dd18a9e49f7ff", +"21:orders_model_6.has_star": "fcbcf165908dd18a9e49f7ff", +"22:orders_model_6.edge_count": "5feceb66ffc86f38d952786c", +"23:orders_model_6.targeting": "6786f18f6ff42aa577c99d86", +"24:orders_model_6.sourced": "1964126d46cdab65c924dd1a", +"25:orders_model_9.has_model": "fcbcf165908dd18a9e49f7ff", +"26:orders_model_9.has_star": "fcbcf165908dd18a9e49f7ff", +"27:orders_model_9.edge_count": "5feceb66ffc86f38d952786c", +"28:orders_model_9.targeting": "6786f18f6ff42aa577c99d86", +"29:orders_model_9.sourced": "69251b0e05822c5fbcc9d552", +"2:orders_model_0.edge_count": "4e07408562bedb8b60ce05c1", +"30:orders_model_1.has_model": "fcbcf165908dd18a9e49f7ff", +"31:orders_model_1.has_star": "fcbcf165908dd18a9e49f7ff", +"32:orders_model_1.edge_count": "5feceb66ffc86f38d952786c", +"33:orders_model_1.targeting": "6786f18f6ff42aa577c99d86", +"34:orders_model_1.sourced": "6786f18f6ff42aa577c99d86", +"35:orders_model_10.has_model": "b5bea41b6c623f7c09f1bf24", +"36:orders_model_10.has_star": "b5bea41b6c623f7c09f1bf24", +"37:orders_model_10.edge_count": "4b227777d4dd1fc61c6f884f", +"38:orders_model_10.targeting": "37bf1d6a9739dac6c07b8f77", +"39:orders_model_10.sourced": "6786f18f6ff42aa577c99d86", +"3:orders_model_0.targeting": "4654ad70130bf45723d2b8e6", +"40:orders_model_13.has_model": "b5bea41b6c623f7c09f1bf24", +"41:orders_model_13.has_star": "b5bea41b6c623f7c09f1bf24", +"42:orders_model_13.edge_count": "4e07408562bedb8b60ce05c1", +"43:orders_model_13.targeting": "99579faa128e6c8875362de3", +"44:orders_model_13.sourced": "6786f18f6ff42aa577c99d86", +"45:orders_model_4.has_model": "b5bea41b6c623f7c09f1bf24", +"46:orders_model_4.has_star": "b5bea41b6c623f7c09f1bf24", +"47:orders_model_4.edge_count": "4e07408562bedb8b60ce05c1", +"48:orders_model_4.targeting": "2d45ce46fb153f6a59805da3", +"49:orders_model_4.sourced": "6786f18f6ff42aa577c99d86", +"4:orders_model_0.sourced": "a65b23ca24a1df85b7ea6b02", +"50:orders_model_7.has_model": "fcbcf165908dd18a9e49f7ff", +"51:orders_model_7.has_star": "fcbcf165908dd18a9e49f7ff", +"52:orders_model_7.edge_count": "5feceb66ffc86f38d952786c", +"53:orders_model_7.targeting": "6786f18f6ff42aa577c99d86", +"54:orders_model_7.sourced": "6786f18f6ff42aa577c99d86", +"55:orders_model_11.has_model": "fcbcf165908dd18a9e49f7ff", +"56:orders_model_11.has_star": "fcbcf165908dd18a9e49f7ff", +"57:orders_model_11.edge_count": "5feceb66ffc86f38d952786c", +"58:orders_model_11.targeting": "6786f18f6ff42aa577c99d86", +"59:orders_model_11.sourced": "6786f18f6ff42aa577c99d86", +"5:orders_model_12.has_model": "b5bea41b6c623f7c09f1bf24", +"60:orders_model_14.has_model": "fcbcf165908dd18a9e49f7ff", +"61:orders_model_14.has_star": "fcbcf165908dd18a9e49f7ff", +"62:orders_model_14.edge_count": "5feceb66ffc86f38d952786c", +"63:orders_model_14.targeting": "6786f18f6ff42aa577c99d86", +"64:orders_model_14.sourced": "6786f18f6ff42aa577c99d86", +"65:orders_model_2.has_model": "b5bea41b6c623f7c09f1bf24", +"66:orders_model_2.has_star": "fcbcf165908dd18a9e49f7ff", +"67:orders_model_2.edge_count": "6b86b273ff34fce19d6b804e", +"68:orders_model_2.targeting": "944516a2d4e18b4cc263aa14", +"69:orders_model_2.sourced": "5c53070d70386db96f97a69e", +"6:orders_model_12.has_star": "fcbcf165908dd18a9e49f7ff", +"70:orders_model_5.has_model": "fcbcf165908dd18a9e49f7ff", +"71:orders_model_5.has_star": "fcbcf165908dd18a9e49f7ff", +"72:orders_model_5.edge_count": "5feceb66ffc86f38d952786c", +"73:orders_model_5.targeting": "6786f18f6ff42aa577c99d86", +"74:orders_model_5.sourced": "6786f18f6ff42aa577c99d86", +"75:orders_model_8.has_model": "fcbcf165908dd18a9e49f7ff", +"76:orders_model_8.has_star": "fcbcf165908dd18a9e49f7ff", +"77:orders_model_8.edge_count": "5feceb66ffc86f38d952786c", +"78:orders_model_8.targeting": "6786f18f6ff42aa577c99d86", +"79:orders_model_8.sourced": "6786f18f6ff42aa577c99d86", +"7:orders_model_12.edge_count": "d4735e3a265e16eee03f5971", +"80:models": "2d7de32bd10b12e919c42b4e", +"81:edges": "2309dd07ea524a7832a2e342", +"8:orders_model_12.targeting": "235f9bd1bde8e82fc2f4a84f", +"9:orders_model_12.sourced": "6786f18f6ff42aa577c99d86" +} +], +[ +"lineage", +{ +"0:orders_model_0.has_model": "b5bea41b6c623f7c09f1bf24", +"10:orders_model_15.has_model": "b5bea41b6c623f7c09f1bf24", +"11:orders_model_15.has_star": "fcbcf165908dd18a9e49f7ff", +"12:orders_model_15.edge_count": "4e07408562bedb8b60ce05c1", +"13:orders_model_15.targeting": "1964126d46cdab65c924dd1a", +"14:orders_model_15.sourced": "6786f18f6ff42aa577c99d86", +"15:orders_model_3.has_model": "b5bea41b6c623f7c09f1bf24", +"16:orders_model_3.has_star": "fcbcf165908dd18a9e49f7ff", +"17:orders_model_3.edge_count": "d4735e3a265e16eee03f5971", +"18:orders_model_3.targeting": "844829a9cd0c4a620ba890aa", +"19:orders_model_3.sourced": "7f655ae63057e87b3fa79c3c", +"1:orders_model_0.has_star": "b5bea41b6c623f7c09f1bf24", +"20:orders_model_6.has_model": "b5bea41b6c623f7c09f1bf24", +"21:orders_model_6.has_star": "fcbcf165908dd18a9e49f7ff", +"22:orders_model_6.edge_count": "4e07408562bedb8b60ce05c1", +"23:orders_model_6.targeting": "e38eef92273ee4afe348ad87", +"24:orders_model_6.sourced": "1964126d46cdab65c924dd1a", +"25:orders_model_9.has_model": "b5bea41b6c623f7c09f1bf24", +"26:orders_model_9.has_star": "b5bea41b6c623f7c09f1bf24", +"27:orders_model_9.edge_count": "4e07408562bedb8b60ce05c1", +"28:orders_model_9.targeting": "6ec77a263392a2e5ea8ee05a", +"29:orders_model_9.sourced": "69251b0e05822c5fbcc9d552", +"2:orders_model_0.edge_count": "4e07408562bedb8b60ce05c1", +"30:orders_model_1.has_model": "b5bea41b6c623f7c09f1bf24", +"31:orders_model_1.has_star": "b5bea41b6c623f7c09f1bf24", +"32:orders_model_1.edge_count": "7902699be42c8a8e46fbbb45", +"33:orders_model_1.targeting": "c9904eaf37f8410c86a5700e", +"34:orders_model_1.sourced": "79fe2d0a0a77035de3d04db1", +"35:orders_model_10.has_model": "b5bea41b6c623f7c09f1bf24", +"36:orders_model_10.has_star": "b5bea41b6c623f7c09f1bf24", +"37:orders_model_10.edge_count": "4b227777d4dd1fc61c6f884f", +"38:orders_model_10.targeting": "37bf1d6a9739dac6c07b8f77", +"39:orders_model_10.sourced": "71858f9d94fda04aed071aa0", +"3:orders_model_0.targeting": "4654ad70130bf45723d2b8e6", +"40:orders_model_13.has_model": "b5bea41b6c623f7c09f1bf24", +"41:orders_model_13.has_star": "b5bea41b6c623f7c09f1bf24", +"42:orders_model_13.edge_count": "4e07408562bedb8b60ce05c1", +"43:orders_model_13.targeting": "99579faa128e6c8875362de3", +"44:orders_model_13.sourced": "6786f18f6ff42aa577c99d86", +"45:orders_model_4.has_model": "b5bea41b6c623f7c09f1bf24", +"46:orders_model_4.has_star": "b5bea41b6c623f7c09f1bf24", +"47:orders_model_4.edge_count": "4e07408562bedb8b60ce05c1", +"48:orders_model_4.targeting": "2d45ce46fb153f6a59805da3", +"49:orders_model_4.sourced": "6786f18f6ff42aa577c99d86", +"4:orders_model_0.sourced": "b390008e1f822c92bd0b26de", +"50:orders_model_7.has_model": "b5bea41b6c623f7c09f1bf24", +"51:orders_model_7.has_star": "fcbcf165908dd18a9e49f7ff", +"52:orders_model_7.edge_count": "19581e27de7ced00ff1ce50b", +"53:orders_model_7.targeting": "79fe2d0a0a77035de3d04db1", +"54:orders_model_7.sourced": "6786f18f6ff42aa577c99d86", +"55:orders_model_11.has_model": "b5bea41b6c623f7c09f1bf24", +"56:orders_model_11.has_star": "fcbcf165908dd18a9e49f7ff", +"57:orders_model_11.edge_count": "6b86b273ff34fce19d6b804e", +"58:orders_model_11.targeting": "71858f9d94fda04aed071aa0", +"59:orders_model_11.sourced": "6786f18f6ff42aa577c99d86", +"5:orders_model_12.has_model": "b5bea41b6c623f7c09f1bf24", +"60:orders_model_14.has_model": "b5bea41b6c623f7c09f1bf24", +"61:orders_model_14.has_star": "fcbcf165908dd18a9e49f7ff", +"62:orders_model_14.edge_count": "d4735e3a265e16eee03f5971", +"63:orders_model_14.targeting": "7f655ae63057e87b3fa79c3c", +"64:orders_model_14.sourced": "6786f18f6ff42aa577c99d86", +"65:orders_model_2.has_model": "b5bea41b6c623f7c09f1bf24", +"66:orders_model_2.has_star": "fcbcf165908dd18a9e49f7ff", +"67:orders_model_2.edge_count": "6b86b273ff34fce19d6b804e", +"68:orders_model_2.targeting": "944516a2d4e18b4cc263aa14", +"69:orders_model_2.sourced": "5c53070d70386db96f97a69e", +"6:orders_model_12.has_star": "fcbcf165908dd18a9e49f7ff", +"70:orders_model_5.has_model": "b5bea41b6c623f7c09f1bf24", +"71:orders_model_5.has_star": "fcbcf165908dd18a9e49f7ff", +"72:orders_model_5.edge_count": "d4735e3a265e16eee03f5971", +"73:orders_model_5.targeting": "2a6f7207b52f1b1ffe6d2ca0", +"74:orders_model_5.sourced": "e38eef92273ee4afe348ad87", +"75:orders_model_8.has_model": "b5bea41b6c623f7c09f1bf24", +"76:orders_model_8.has_star": "b5bea41b6c623f7c09f1bf24", +"77:orders_model_8.edge_count": "4e07408562bedb8b60ce05c1", +"78:orders_model_8.targeting": "46d90f7d3dfc791867204a4c", +"79:orders_model_8.sourced": "6786f18f6ff42aa577c99d86", +"7:orders_model_12.edge_count": "d4735e3a265e16eee03f5971", +"80:models": "37d91f3ee68d4dc24cff6ae3", +"81:edges": "13f3bb62cb14932238e532fe", +"8:orders_model_12.targeting": "235f9bd1bde8e82fc2f4a84f", +"9:orders_model_12.sourced": "6786f18f6ff42aa577c99d86" +} +], +[ +"lineage", +{ +"0:orders_model_0.has_model": "b5bea41b6c623f7c09f1bf24", +"10:orders_model_15.has_model": "b5bea41b6c623f7c09f1bf24", +"11:orders_model_15.has_star": "fcbcf165908dd18a9e49f7ff", +"12:orders_model_15.edge_count": "4e07408562bedb8b60ce05c1", +"13:orders_model_15.targeting": "1964126d46cdab65c924dd1a", +"14:orders_model_15.sourced": "6786f18f6ff42aa577c99d86", +"15:orders_model_3.has_model": "b5bea41b6c623f7c09f1bf24", +"16:orders_model_3.has_star": "fcbcf165908dd18a9e49f7ff", +"17:orders_model_3.edge_count": "d4735e3a265e16eee03f5971", +"18:orders_model_3.targeting": "844829a9cd0c4a620ba890aa", +"19:orders_model_3.sourced": "6786f18f6ff42aa577c99d86", +"1:orders_model_0.has_star": "b5bea41b6c623f7c09f1bf24", +"20:orders_model_6.has_model": "fcbcf165908dd18a9e49f7ff", +"21:orders_model_6.has_star": "fcbcf165908dd18a9e49f7ff", +"22:orders_model_6.edge_count": "5feceb66ffc86f38d952786c", +"23:orders_model_6.targeting": "6786f18f6ff42aa577c99d86", +"24:orders_model_6.sourced": "1964126d46cdab65c924dd1a", +"25:orders_model_9.has_model": "fcbcf165908dd18a9e49f7ff", +"26:orders_model_9.has_star": "fcbcf165908dd18a9e49f7ff", +"27:orders_model_9.edge_count": "5feceb66ffc86f38d952786c", +"28:orders_model_9.targeting": "6786f18f6ff42aa577c99d86", +"29:orders_model_9.sourced": "69251b0e05822c5fbcc9d552", +"2:orders_model_0.edge_count": "4e07408562bedb8b60ce05c1", +"30:orders_model_1.has_model": "fcbcf165908dd18a9e49f7ff", +"31:orders_model_1.has_star": "fcbcf165908dd18a9e49f7ff", +"32:orders_model_1.edge_count": "5feceb66ffc86f38d952786c", +"33:orders_model_1.targeting": "6786f18f6ff42aa577c99d86", +"34:orders_model_1.sourced": "6786f18f6ff42aa577c99d86", +"35:orders_model_10.has_model": "b5bea41b6c623f7c09f1bf24", +"36:orders_model_10.has_star": "b5bea41b6c623f7c09f1bf24", +"37:orders_model_10.edge_count": "4b227777d4dd1fc61c6f884f", +"38:orders_model_10.targeting": "37bf1d6a9739dac6c07b8f77", +"39:orders_model_10.sourced": "6786f18f6ff42aa577c99d86", +"3:orders_model_0.targeting": "4654ad70130bf45723d2b8e6", +"40:orders_model_13.has_model": "b5bea41b6c623f7c09f1bf24", +"41:orders_model_13.has_star": "b5bea41b6c623f7c09f1bf24", +"42:orders_model_13.edge_count": "4e07408562bedb8b60ce05c1", +"43:orders_model_13.targeting": "99579faa128e6c8875362de3", +"44:orders_model_13.sourced": "6786f18f6ff42aa577c99d86", +"45:orders_model_4.has_model": "b5bea41b6c623f7c09f1bf24", +"46:orders_model_4.has_star": "b5bea41b6c623f7c09f1bf24", +"47:orders_model_4.edge_count": "4e07408562bedb8b60ce05c1", +"48:orders_model_4.targeting": "2d45ce46fb153f6a59805da3", +"49:orders_model_4.sourced": "6786f18f6ff42aa577c99d86", +"4:orders_model_0.sourced": "a65b23ca24a1df85b7ea6b02", +"50:orders_model_7.has_model": "fcbcf165908dd18a9e49f7ff", +"51:orders_model_7.has_star": "fcbcf165908dd18a9e49f7ff", +"52:orders_model_7.edge_count": "5feceb66ffc86f38d952786c", +"53:orders_model_7.targeting": "6786f18f6ff42aa577c99d86", +"54:orders_model_7.sourced": "6786f18f6ff42aa577c99d86", +"55:orders_model_11.has_model": "fcbcf165908dd18a9e49f7ff", +"56:orders_model_11.has_star": "fcbcf165908dd18a9e49f7ff", +"57:orders_model_11.edge_count": "5feceb66ffc86f38d952786c", +"58:orders_model_11.targeting": "6786f18f6ff42aa577c99d86", +"59:orders_model_11.sourced": "6786f18f6ff42aa577c99d86", +"5:orders_model_12.has_model": "b5bea41b6c623f7c09f1bf24", +"60:orders_model_14.has_model": "fcbcf165908dd18a9e49f7ff", +"61:orders_model_14.has_star": "fcbcf165908dd18a9e49f7ff", +"62:orders_model_14.edge_count": "5feceb66ffc86f38d952786c", +"63:orders_model_14.targeting": "6786f18f6ff42aa577c99d86", +"64:orders_model_14.sourced": "6786f18f6ff42aa577c99d86", +"65:orders_model_2.has_model": "b5bea41b6c623f7c09f1bf24", +"66:orders_model_2.has_star": "fcbcf165908dd18a9e49f7ff", +"67:orders_model_2.edge_count": "6b86b273ff34fce19d6b804e", +"68:orders_model_2.targeting": "944516a2d4e18b4cc263aa14", +"69:orders_model_2.sourced": "5c53070d70386db96f97a69e", +"6:orders_model_12.has_star": "fcbcf165908dd18a9e49f7ff", +"70:orders_model_5.has_model": "fcbcf165908dd18a9e49f7ff", +"71:orders_model_5.has_star": "fcbcf165908dd18a9e49f7ff", +"72:orders_model_5.edge_count": "5feceb66ffc86f38d952786c", +"73:orders_model_5.targeting": "6786f18f6ff42aa577c99d86", +"74:orders_model_5.sourced": "6786f18f6ff42aa577c99d86", +"75:orders_model_8.has_model": "fcbcf165908dd18a9e49f7ff", +"76:orders_model_8.has_star": "fcbcf165908dd18a9e49f7ff", +"77:orders_model_8.edge_count": "5feceb66ffc86f38d952786c", +"78:orders_model_8.targeting": "6786f18f6ff42aa577c99d86", +"79:orders_model_8.sourced": "6786f18f6ff42aa577c99d86", +"7:orders_model_12.edge_count": "d4735e3a265e16eee03f5971", +"80:models": "2d7de32bd10b12e919c42b4e", +"81:edges": "2309dd07ea524a7832a2e342", +"8:orders_model_12.targeting": "235f9bd1bde8e82fc2f4a84f", +"9:orders_model_12.sourced": "6786f18f6ff42aa577c99d86" +} +], +[ +"lineage", +{ +"0:orders_model_0.has_model": "b5bea41b6c623f7c09f1bf24", +"10:orders_model_15.has_model": "b5bea41b6c623f7c09f1bf24", +"11:orders_model_15.has_star": "fcbcf165908dd18a9e49f7ff", +"12:orders_model_15.edge_count": "4e07408562bedb8b60ce05c1", +"13:orders_model_15.targeting": "1964126d46cdab65c924dd1a", +"14:orders_model_15.sourced": "6786f18f6ff42aa577c99d86", +"15:orders_model_3.has_model": "b5bea41b6c623f7c09f1bf24", +"16:orders_model_3.has_star": "fcbcf165908dd18a9e49f7ff", +"17:orders_model_3.edge_count": "d4735e3a265e16eee03f5971", +"18:orders_model_3.targeting": "844829a9cd0c4a620ba890aa", +"19:orders_model_3.sourced": "7f655ae63057e87b3fa79c3c", +"1:orders_model_0.has_star": "b5bea41b6c623f7c09f1bf24", +"20:orders_model_6.has_model": "b5bea41b6c623f7c09f1bf24", +"21:orders_model_6.has_star": "fcbcf165908dd18a9e49f7ff", +"22:orders_model_6.edge_count": "4e07408562bedb8b60ce05c1", +"23:orders_model_6.targeting": "e38eef92273ee4afe348ad87", +"24:orders_model_6.sourced": "1964126d46cdab65c924dd1a", +"25:orders_model_9.has_model": "b5bea41b6c623f7c09f1bf24", +"26:orders_model_9.has_star": "b5bea41b6c623f7c09f1bf24", +"27:orders_model_9.edge_count": "4e07408562bedb8b60ce05c1", +"28:orders_model_9.targeting": "6ec77a263392a2e5ea8ee05a", +"29:orders_model_9.sourced": "69251b0e05822c5fbcc9d552", +"2:orders_model_0.edge_count": "4e07408562bedb8b60ce05c1", +"30:orders_model_1.has_model": "b5bea41b6c623f7c09f1bf24", +"31:orders_model_1.has_star": "b5bea41b6c623f7c09f1bf24", +"32:orders_model_1.edge_count": "7902699be42c8a8e46fbbb45", +"33:orders_model_1.targeting": "c9904eaf37f8410c86a5700e", +"34:orders_model_1.sourced": "79fe2d0a0a77035de3d04db1", +"35:orders_model_10.has_model": "b5bea41b6c623f7c09f1bf24", +"36:orders_model_10.has_star": "b5bea41b6c623f7c09f1bf24", +"37:orders_model_10.edge_count": "4b227777d4dd1fc61c6f884f", +"38:orders_model_10.targeting": "37bf1d6a9739dac6c07b8f77", +"39:orders_model_10.sourced": "71858f9d94fda04aed071aa0", +"3:orders_model_0.targeting": "4654ad70130bf45723d2b8e6", +"40:orders_model_13.has_model": "b5bea41b6c623f7c09f1bf24", +"41:orders_model_13.has_star": "b5bea41b6c623f7c09f1bf24", +"42:orders_model_13.edge_count": "4e07408562bedb8b60ce05c1", +"43:orders_model_13.targeting": "99579faa128e6c8875362de3", +"44:orders_model_13.sourced": "6786f18f6ff42aa577c99d86", +"45:orders_model_4.has_model": "b5bea41b6c623f7c09f1bf24", +"46:orders_model_4.has_star": "b5bea41b6c623f7c09f1bf24", +"47:orders_model_4.edge_count": "4e07408562bedb8b60ce05c1", +"48:orders_model_4.targeting": "2d45ce46fb153f6a59805da3", +"49:orders_model_4.sourced": "6786f18f6ff42aa577c99d86", +"4:orders_model_0.sourced": "b390008e1f822c92bd0b26de", +"50:orders_model_7.has_model": "b5bea41b6c623f7c09f1bf24", +"51:orders_model_7.has_star": "fcbcf165908dd18a9e49f7ff", +"52:orders_model_7.edge_count": "19581e27de7ced00ff1ce50b", +"53:orders_model_7.targeting": "79fe2d0a0a77035de3d04db1", +"54:orders_model_7.sourced": "6786f18f6ff42aa577c99d86", +"55:orders_model_11.has_model": "b5bea41b6c623f7c09f1bf24", +"56:orders_model_11.has_star": "fcbcf165908dd18a9e49f7ff", +"57:orders_model_11.edge_count": "6b86b273ff34fce19d6b804e", +"58:orders_model_11.targeting": "71858f9d94fda04aed071aa0", +"59:orders_model_11.sourced": "6786f18f6ff42aa577c99d86", +"5:orders_model_12.has_model": "b5bea41b6c623f7c09f1bf24", +"60:orders_model_14.has_model": "b5bea41b6c623f7c09f1bf24", +"61:orders_model_14.has_star": "fcbcf165908dd18a9e49f7ff", +"62:orders_model_14.edge_count": "d4735e3a265e16eee03f5971", +"63:orders_model_14.targeting": "7f655ae63057e87b3fa79c3c", +"64:orders_model_14.sourced": "6786f18f6ff42aa577c99d86", +"65:orders_model_2.has_model": "b5bea41b6c623f7c09f1bf24", +"66:orders_model_2.has_star": "fcbcf165908dd18a9e49f7ff", +"67:orders_model_2.edge_count": "6b86b273ff34fce19d6b804e", +"68:orders_model_2.targeting": "944516a2d4e18b4cc263aa14", +"69:orders_model_2.sourced": "5c53070d70386db96f97a69e", +"6:orders_model_12.has_star": "fcbcf165908dd18a9e49f7ff", +"70:orders_model_5.has_model": "b5bea41b6c623f7c09f1bf24", +"71:orders_model_5.has_star": "fcbcf165908dd18a9e49f7ff", +"72:orders_model_5.edge_count": "d4735e3a265e16eee03f5971", +"73:orders_model_5.targeting": "2a6f7207b52f1b1ffe6d2ca0", +"74:orders_model_5.sourced": "e38eef92273ee4afe348ad87", +"75:orders_model_8.has_model": "b5bea41b6c623f7c09f1bf24", +"76:orders_model_8.has_star": "b5bea41b6c623f7c09f1bf24", +"77:orders_model_8.edge_count": "4e07408562bedb8b60ce05c1", +"78:orders_model_8.targeting": "46d90f7d3dfc791867204a4c", +"79:orders_model_8.sourced": "6786f18f6ff42aa577c99d86", +"7:orders_model_12.edge_count": "d4735e3a265e16eee03f5971", +"80:models": "37d91f3ee68d4dc24cff6ae3", +"81:edges": "13f3bb62cb14932238e532fe", +"8:orders_model_12.targeting": "235f9bd1bde8e82fc2f4a84f", +"9:orders_model_12.sourced": "6786f18f6ff42aa577c99d86" +} +], +[ +"lineage", +{ +"0:orders_model_0.has_model": "b5bea41b6c623f7c09f1bf24", +"10:orders_model_15.has_model": "b5bea41b6c623f7c09f1bf24", +"11:orders_model_15.has_star": "fcbcf165908dd18a9e49f7ff", +"12:orders_model_15.edge_count": "4e07408562bedb8b60ce05c1", +"13:orders_model_15.targeting": "1964126d46cdab65c924dd1a", +"14:orders_model_15.sourced": "6786f18f6ff42aa577c99d86", +"15:orders_model_3.has_model": "b5bea41b6c623f7c09f1bf24", +"16:orders_model_3.has_star": "fcbcf165908dd18a9e49f7ff", +"17:orders_model_3.edge_count": "d4735e3a265e16eee03f5971", +"18:orders_model_3.targeting": "844829a9cd0c4a620ba890aa", +"19:orders_model_3.sourced": "6786f18f6ff42aa577c99d86", +"1:orders_model_0.has_star": "b5bea41b6c623f7c09f1bf24", +"20:orders_model_6.has_model": "fcbcf165908dd18a9e49f7ff", +"21:orders_model_6.has_star": "fcbcf165908dd18a9e49f7ff", +"22:orders_model_6.edge_count": "5feceb66ffc86f38d952786c", +"23:orders_model_6.targeting": "6786f18f6ff42aa577c99d86", +"24:orders_model_6.sourced": "1964126d46cdab65c924dd1a", +"25:orders_model_9.has_model": "fcbcf165908dd18a9e49f7ff", +"26:orders_model_9.has_star": "fcbcf165908dd18a9e49f7ff", +"27:orders_model_9.edge_count": "5feceb66ffc86f38d952786c", +"28:orders_model_9.targeting": "6786f18f6ff42aa577c99d86", +"29:orders_model_9.sourced": "69251b0e05822c5fbcc9d552", +"2:orders_model_0.edge_count": "4e07408562bedb8b60ce05c1", +"30:orders_model_1.has_model": "fcbcf165908dd18a9e49f7ff", +"31:orders_model_1.has_star": "fcbcf165908dd18a9e49f7ff", +"32:orders_model_1.edge_count": "5feceb66ffc86f38d952786c", +"33:orders_model_1.targeting": "6786f18f6ff42aa577c99d86", +"34:orders_model_1.sourced": "6786f18f6ff42aa577c99d86", +"35:orders_model_10.has_model": "b5bea41b6c623f7c09f1bf24", +"36:orders_model_10.has_star": "b5bea41b6c623f7c09f1bf24", +"37:orders_model_10.edge_count": "4b227777d4dd1fc61c6f884f", +"38:orders_model_10.targeting": "37bf1d6a9739dac6c07b8f77", +"39:orders_model_10.sourced": "6786f18f6ff42aa577c99d86", +"3:orders_model_0.targeting": "4654ad70130bf45723d2b8e6", +"40:orders_model_13.has_model": "b5bea41b6c623f7c09f1bf24", +"41:orders_model_13.has_star": "b5bea41b6c623f7c09f1bf24", +"42:orders_model_13.edge_count": "4e07408562bedb8b60ce05c1", +"43:orders_model_13.targeting": "99579faa128e6c8875362de3", +"44:orders_model_13.sourced": "6786f18f6ff42aa577c99d86", +"45:orders_model_4.has_model": "b5bea41b6c623f7c09f1bf24", +"46:orders_model_4.has_star": "b5bea41b6c623f7c09f1bf24", +"47:orders_model_4.edge_count": "4e07408562bedb8b60ce05c1", +"48:orders_model_4.targeting": "2d45ce46fb153f6a59805da3", +"49:orders_model_4.sourced": "6786f18f6ff42aa577c99d86", +"4:orders_model_0.sourced": "a65b23ca24a1df85b7ea6b02", +"50:orders_model_7.has_model": "fcbcf165908dd18a9e49f7ff", +"51:orders_model_7.has_star": "fcbcf165908dd18a9e49f7ff", +"52:orders_model_7.edge_count": "5feceb66ffc86f38d952786c", +"53:orders_model_7.targeting": "6786f18f6ff42aa577c99d86", +"54:orders_model_7.sourced": "6786f18f6ff42aa577c99d86", +"55:orders_model_11.has_model": "fcbcf165908dd18a9e49f7ff", +"56:orders_model_11.has_star": "fcbcf165908dd18a9e49f7ff", +"57:orders_model_11.edge_count": "5feceb66ffc86f38d952786c", +"58:orders_model_11.targeting": "6786f18f6ff42aa577c99d86", +"59:orders_model_11.sourced": "6786f18f6ff42aa577c99d86", +"5:orders_model_12.has_model": "b5bea41b6c623f7c09f1bf24", +"60:orders_model_14.has_model": "fcbcf165908dd18a9e49f7ff", +"61:orders_model_14.has_star": "fcbcf165908dd18a9e49f7ff", +"62:orders_model_14.edge_count": "5feceb66ffc86f38d952786c", +"63:orders_model_14.targeting": "6786f18f6ff42aa577c99d86", +"64:orders_model_14.sourced": "6786f18f6ff42aa577c99d86", +"65:orders_model_2.has_model": "b5bea41b6c623f7c09f1bf24", +"66:orders_model_2.has_star": "fcbcf165908dd18a9e49f7ff", +"67:orders_model_2.edge_count": "6b86b273ff34fce19d6b804e", +"68:orders_model_2.targeting": "944516a2d4e18b4cc263aa14", +"69:orders_model_2.sourced": "5c53070d70386db96f97a69e", +"6:orders_model_12.has_star": "fcbcf165908dd18a9e49f7ff", +"70:orders_model_5.has_model": "fcbcf165908dd18a9e49f7ff", +"71:orders_model_5.has_star": "fcbcf165908dd18a9e49f7ff", +"72:orders_model_5.edge_count": "5feceb66ffc86f38d952786c", +"73:orders_model_5.targeting": "6786f18f6ff42aa577c99d86", +"74:orders_model_5.sourced": "6786f18f6ff42aa577c99d86", +"75:orders_model_8.has_model": "fcbcf165908dd18a9e49f7ff", +"76:orders_model_8.has_star": "fcbcf165908dd18a9e49f7ff", +"77:orders_model_8.edge_count": "5feceb66ffc86f38d952786c", +"78:orders_model_8.targeting": "6786f18f6ff42aa577c99d86", +"79:orders_model_8.sourced": "6786f18f6ff42aa577c99d86", +"7:orders_model_12.edge_count": "d4735e3a265e16eee03f5971", +"80:models": "2d7de32bd10b12e919c42b4e", +"81:edges": "2309dd07ea524a7832a2e342", +"8:orders_model_12.targeting": "235f9bd1bde8e82fc2f4a84f", +"9:orders_model_12.sourced": "6786f18f6ff42aa577c99d86" +} +], +[ +"lineage", +{ +"0:orders_model_0.has_model": "b5bea41b6c623f7c09f1bf24", +"10:orders_model_15.has_model": "b5bea41b6c623f7c09f1bf24", +"11:orders_model_15.has_star": "fcbcf165908dd18a9e49f7ff", +"12:orders_model_15.edge_count": "4e07408562bedb8b60ce05c1", +"13:orders_model_15.targeting": "1964126d46cdab65c924dd1a", +"14:orders_model_15.sourced": "6786f18f6ff42aa577c99d86", +"15:orders_model_3.has_model": "b5bea41b6c623f7c09f1bf24", +"16:orders_model_3.has_star": "fcbcf165908dd18a9e49f7ff", +"17:orders_model_3.edge_count": "d4735e3a265e16eee03f5971", +"18:orders_model_3.targeting": "844829a9cd0c4a620ba890aa", +"19:orders_model_3.sourced": "7f655ae63057e87b3fa79c3c", +"1:orders_model_0.has_star": "b5bea41b6c623f7c09f1bf24", +"20:orders_model_6.has_model": "b5bea41b6c623f7c09f1bf24", +"21:orders_model_6.has_star": "fcbcf165908dd18a9e49f7ff", +"22:orders_model_6.edge_count": "4e07408562bedb8b60ce05c1", +"23:orders_model_6.targeting": "e38eef92273ee4afe348ad87", +"24:orders_model_6.sourced": "1964126d46cdab65c924dd1a", +"25:orders_model_9.has_model": "b5bea41b6c623f7c09f1bf24", +"26:orders_model_9.has_star": "b5bea41b6c623f7c09f1bf24", +"27:orders_model_9.edge_count": "4e07408562bedb8b60ce05c1", +"28:orders_model_9.targeting": "6ec77a263392a2e5ea8ee05a", +"29:orders_model_9.sourced": "69251b0e05822c5fbcc9d552", +"2:orders_model_0.edge_count": "4e07408562bedb8b60ce05c1", +"30:orders_model_1.has_model": "b5bea41b6c623f7c09f1bf24", +"31:orders_model_1.has_star": "b5bea41b6c623f7c09f1bf24", +"32:orders_model_1.edge_count": "7902699be42c8a8e46fbbb45", +"33:orders_model_1.targeting": "c9904eaf37f8410c86a5700e", +"34:orders_model_1.sourced": "79fe2d0a0a77035de3d04db1", +"35:orders_model_10.has_model": "b5bea41b6c623f7c09f1bf24", +"36:orders_model_10.has_star": "b5bea41b6c623f7c09f1bf24", +"37:orders_model_10.edge_count": "4b227777d4dd1fc61c6f884f", +"38:orders_model_10.targeting": "37bf1d6a9739dac6c07b8f77", +"39:orders_model_10.sourced": "71858f9d94fda04aed071aa0", +"3:orders_model_0.targeting": "4654ad70130bf45723d2b8e6", +"40:orders_model_13.has_model": "b5bea41b6c623f7c09f1bf24", +"41:orders_model_13.has_star": "b5bea41b6c623f7c09f1bf24", +"42:orders_model_13.edge_count": "4e07408562bedb8b60ce05c1", +"43:orders_model_13.targeting": "99579faa128e6c8875362de3", +"44:orders_model_13.sourced": "6786f18f6ff42aa577c99d86", +"45:orders_model_4.has_model": "b5bea41b6c623f7c09f1bf24", +"46:orders_model_4.has_star": "b5bea41b6c623f7c09f1bf24", +"47:orders_model_4.edge_count": "4e07408562bedb8b60ce05c1", +"48:orders_model_4.targeting": "2d45ce46fb153f6a59805da3", +"49:orders_model_4.sourced": "6786f18f6ff42aa577c99d86", +"4:orders_model_0.sourced": "b390008e1f822c92bd0b26de", +"50:orders_model_7.has_model": "b5bea41b6c623f7c09f1bf24", +"51:orders_model_7.has_star": "fcbcf165908dd18a9e49f7ff", +"52:orders_model_7.edge_count": "19581e27de7ced00ff1ce50b", +"53:orders_model_7.targeting": "79fe2d0a0a77035de3d04db1", +"54:orders_model_7.sourced": "6786f18f6ff42aa577c99d86", +"55:orders_model_11.has_model": "b5bea41b6c623f7c09f1bf24", +"56:orders_model_11.has_star": "fcbcf165908dd18a9e49f7ff", +"57:orders_model_11.edge_count": "6b86b273ff34fce19d6b804e", +"58:orders_model_11.targeting": "71858f9d94fda04aed071aa0", +"59:orders_model_11.sourced": "6786f18f6ff42aa577c99d86", +"5:orders_model_12.has_model": "b5bea41b6c623f7c09f1bf24", +"60:orders_model_14.has_model": "b5bea41b6c623f7c09f1bf24", +"61:orders_model_14.has_star": "fcbcf165908dd18a9e49f7ff", +"62:orders_model_14.edge_count": "d4735e3a265e16eee03f5971", +"63:orders_model_14.targeting": "7f655ae63057e87b3fa79c3c", +"64:orders_model_14.sourced": "6786f18f6ff42aa577c99d86", +"65:orders_model_2.has_model": "b5bea41b6c623f7c09f1bf24", +"66:orders_model_2.has_star": "fcbcf165908dd18a9e49f7ff", +"67:orders_model_2.edge_count": "6b86b273ff34fce19d6b804e", +"68:orders_model_2.targeting": "944516a2d4e18b4cc263aa14", +"69:orders_model_2.sourced": "5c53070d70386db96f97a69e", +"6:orders_model_12.has_star": "fcbcf165908dd18a9e49f7ff", +"70:orders_model_5.has_model": "b5bea41b6c623f7c09f1bf24", +"71:orders_model_5.has_star": "fcbcf165908dd18a9e49f7ff", +"72:orders_model_5.edge_count": "d4735e3a265e16eee03f5971", +"73:orders_model_5.targeting": "2a6f7207b52f1b1ffe6d2ca0", +"74:orders_model_5.sourced": "e38eef92273ee4afe348ad87", +"75:orders_model_8.has_model": "b5bea41b6c623f7c09f1bf24", +"76:orders_model_8.has_star": "b5bea41b6c623f7c09f1bf24", +"77:orders_model_8.edge_count": "4e07408562bedb8b60ce05c1", +"78:orders_model_8.targeting": "46d90f7d3dfc791867204a4c", +"79:orders_model_8.sourced": "6786f18f6ff42aa577c99d86", +"7:orders_model_12.edge_count": "d4735e3a265e16eee03f5971", +"80:models": "37d91f3ee68d4dc24cff6ae3", +"81:edges": "13f3bb62cb14932238e532fe", +"8:orders_model_12.targeting": "235f9bd1bde8e82fc2f4a84f", +"9:orders_model_12.sourced": "6786f18f6ff42aa577c99d86" +} +], +[ +"lineage", +{ +"0:orders_model_0.has_model": "b5bea41b6c623f7c09f1bf24", +"10:orders_model_15.has_model": "b5bea41b6c623f7c09f1bf24", +"11:orders_model_15.has_star": "fcbcf165908dd18a9e49f7ff", +"12:orders_model_15.edge_count": "4e07408562bedb8b60ce05c1", +"13:orders_model_15.targeting": "1964126d46cdab65c924dd1a", +"14:orders_model_15.sourced": "6786f18f6ff42aa577c99d86", +"15:orders_model_3.has_model": "b5bea41b6c623f7c09f1bf24", +"16:orders_model_3.has_star": "fcbcf165908dd18a9e49f7ff", +"17:orders_model_3.edge_count": "d4735e3a265e16eee03f5971", +"18:orders_model_3.targeting": "844829a9cd0c4a620ba890aa", +"19:orders_model_3.sourced": "6786f18f6ff42aa577c99d86", +"1:orders_model_0.has_star": "b5bea41b6c623f7c09f1bf24", +"20:orders_model_6.has_model": "fcbcf165908dd18a9e49f7ff", +"21:orders_model_6.has_star": "fcbcf165908dd18a9e49f7ff", +"22:orders_model_6.edge_count": "5feceb66ffc86f38d952786c", +"23:orders_model_6.targeting": "6786f18f6ff42aa577c99d86", +"24:orders_model_6.sourced": "1964126d46cdab65c924dd1a", +"25:orders_model_9.has_model": "fcbcf165908dd18a9e49f7ff", +"26:orders_model_9.has_star": "fcbcf165908dd18a9e49f7ff", +"27:orders_model_9.edge_count": "5feceb66ffc86f38d952786c", +"28:orders_model_9.targeting": "6786f18f6ff42aa577c99d86", +"29:orders_model_9.sourced": "69251b0e05822c5fbcc9d552", +"2:orders_model_0.edge_count": "4e07408562bedb8b60ce05c1", +"30:orders_model_1.has_model": "fcbcf165908dd18a9e49f7ff", +"31:orders_model_1.has_star": "fcbcf165908dd18a9e49f7ff", +"32:orders_model_1.edge_count": "5feceb66ffc86f38d952786c", +"33:orders_model_1.targeting": "6786f18f6ff42aa577c99d86", +"34:orders_model_1.sourced": "6786f18f6ff42aa577c99d86", +"35:orders_model_10.has_model": "b5bea41b6c623f7c09f1bf24", +"36:orders_model_10.has_star": "b5bea41b6c623f7c09f1bf24", +"37:orders_model_10.edge_count": "4b227777d4dd1fc61c6f884f", +"38:orders_model_10.targeting": "37bf1d6a9739dac6c07b8f77", +"39:orders_model_10.sourced": "6786f18f6ff42aa577c99d86", +"3:orders_model_0.targeting": "4654ad70130bf45723d2b8e6", +"40:orders_model_13.has_model": "b5bea41b6c623f7c09f1bf24", +"41:orders_model_13.has_star": "b5bea41b6c623f7c09f1bf24", +"42:orders_model_13.edge_count": "4e07408562bedb8b60ce05c1", +"43:orders_model_13.targeting": "99579faa128e6c8875362de3", +"44:orders_model_13.sourced": "6786f18f6ff42aa577c99d86", +"45:orders_model_4.has_model": "b5bea41b6c623f7c09f1bf24", +"46:orders_model_4.has_star": "b5bea41b6c623f7c09f1bf24", +"47:orders_model_4.edge_count": "4e07408562bedb8b60ce05c1", +"48:orders_model_4.targeting": "2d45ce46fb153f6a59805da3", +"49:orders_model_4.sourced": "6786f18f6ff42aa577c99d86", +"4:orders_model_0.sourced": "a65b23ca24a1df85b7ea6b02", +"50:orders_model_7.has_model": "fcbcf165908dd18a9e49f7ff", +"51:orders_model_7.has_star": "fcbcf165908dd18a9e49f7ff", +"52:orders_model_7.edge_count": "5feceb66ffc86f38d952786c", +"53:orders_model_7.targeting": "6786f18f6ff42aa577c99d86", +"54:orders_model_7.sourced": "6786f18f6ff42aa577c99d86", +"55:orders_model_11.has_model": "fcbcf165908dd18a9e49f7ff", +"56:orders_model_11.has_star": "fcbcf165908dd18a9e49f7ff", +"57:orders_model_11.edge_count": "5feceb66ffc86f38d952786c", +"58:orders_model_11.targeting": "6786f18f6ff42aa577c99d86", +"59:orders_model_11.sourced": "6786f18f6ff42aa577c99d86", +"5:orders_model_12.has_model": "b5bea41b6c623f7c09f1bf24", +"60:orders_model_14.has_model": "fcbcf165908dd18a9e49f7ff", +"61:orders_model_14.has_star": "fcbcf165908dd18a9e49f7ff", +"62:orders_model_14.edge_count": "5feceb66ffc86f38d952786c", +"63:orders_model_14.targeting": "6786f18f6ff42aa577c99d86", +"64:orders_model_14.sourced": "6786f18f6ff42aa577c99d86", +"65:orders_model_2.has_model": "b5bea41b6c623f7c09f1bf24", +"66:orders_model_2.has_star": "fcbcf165908dd18a9e49f7ff", +"67:orders_model_2.edge_count": "6b86b273ff34fce19d6b804e", +"68:orders_model_2.targeting": "944516a2d4e18b4cc263aa14", +"69:orders_model_2.sourced": "5c53070d70386db96f97a69e", +"6:orders_model_12.has_star": "fcbcf165908dd18a9e49f7ff", +"70:orders_model_5.has_model": "fcbcf165908dd18a9e49f7ff", +"71:orders_model_5.has_star": "fcbcf165908dd18a9e49f7ff", +"72:orders_model_5.edge_count": "5feceb66ffc86f38d952786c", +"73:orders_model_5.targeting": "6786f18f6ff42aa577c99d86", +"74:orders_model_5.sourced": "6786f18f6ff42aa577c99d86", +"75:orders_model_8.has_model": "fcbcf165908dd18a9e49f7ff", +"76:orders_model_8.has_star": "fcbcf165908dd18a9e49f7ff", +"77:orders_model_8.edge_count": "5feceb66ffc86f38d952786c", +"78:orders_model_8.targeting": "6786f18f6ff42aa577c99d86", +"79:orders_model_8.sourced": "6786f18f6ff42aa577c99d86", +"7:orders_model_12.edge_count": "d4735e3a265e16eee03f5971", +"80:models": "2d7de32bd10b12e919c42b4e", +"81:edges": "2309dd07ea524a7832a2e342", +"8:orders_model_12.targeting": "235f9bd1bde8e82fc2f4a84f", +"9:orders_model_12.sourced": "6786f18f6ff42aa577c99d86" +} +], +[ +"lineage", +{ +"0:orders_model_0.has_model": "b5bea41b6c623f7c09f1bf24", +"10:orders_model_15.has_model": "b5bea41b6c623f7c09f1bf24", +"11:orders_model_15.has_star": "fcbcf165908dd18a9e49f7ff", +"12:orders_model_15.edge_count": "4e07408562bedb8b60ce05c1", +"13:orders_model_15.targeting": "2670c877f940c332e0ed75b6", +"14:orders_model_15.sourced": "6786f18f6ff42aa577c99d86", +"15:orders_model_3.has_model": "b5bea41b6c623f7c09f1bf24", +"16:orders_model_3.has_star": "fcbcf165908dd18a9e49f7ff", +"17:orders_model_3.edge_count": "d4735e3a265e16eee03f5971", +"18:orders_model_3.targeting": "76047432b32c8034e32c2670", +"19:orders_model_3.sourced": "9402db7a493e80bca6d9bf8c", +"1:orders_model_0.has_star": "b5bea41b6c623f7c09f1bf24", +"20:orders_model_6.has_model": "b5bea41b6c623f7c09f1bf24", +"21:orders_model_6.has_star": "fcbcf165908dd18a9e49f7ff", +"22:orders_model_6.edge_count": "4e07408562bedb8b60ce05c1", +"23:orders_model_6.targeting": "2380b94a2203ebdd80fee91b", +"24:orders_model_6.sourced": "2670c877f940c332e0ed75b6", +"25:orders_model_9.has_model": "b5bea41b6c623f7c09f1bf24", +"26:orders_model_9.has_star": "b5bea41b6c623f7c09f1bf24", +"27:orders_model_9.edge_count": "4e07408562bedb8b60ce05c1", +"28:orders_model_9.targeting": "09930b7e9d1880a7b1ca2490", +"29:orders_model_9.sourced": "ba772cfacb11c32601e27380", +"2:orders_model_0.edge_count": "4e07408562bedb8b60ce05c1", +"30:orders_model_1.has_model": "b5bea41b6c623f7c09f1bf24", +"31:orders_model_1.has_star": "b5bea41b6c623f7c09f1bf24", +"32:orders_model_1.edge_count": "7902699be42c8a8e46fbbb45", +"33:orders_model_1.targeting": "c9904eaf37f8410c86a5700e", +"34:orders_model_1.sourced": "67bc1693660f805fe71b8562", +"35:orders_model_10.has_model": "b5bea41b6c623f7c09f1bf24", +"36:orders_model_10.has_star": "b5bea41b6c623f7c09f1bf24", +"37:orders_model_10.edge_count": "e7f6c011776e8db7cd330b54", +"38:orders_model_10.targeting": "86484ebd52c56f5232097531", +"39:orders_model_10.sourced": "71858f9d94fda04aed071aa0", +"3:orders_model_0.targeting": "d11526ad01eb59472574a2a3", +"40:orders_model_13.has_model": "b5bea41b6c623f7c09f1bf24", +"41:orders_model_13.has_star": "b5bea41b6c623f7c09f1bf24", +"42:orders_model_13.edge_count": "d4735e3a265e16eee03f5971", +"43:orders_model_13.targeting": "a7fe2c291b441e90fb5a61b8", +"44:orders_model_13.sourced": "6786f18f6ff42aa577c99d86", +"45:orders_model_4.has_model": "b5bea41b6c623f7c09f1bf24", +"46:orders_model_4.has_star": "b5bea41b6c623f7c09f1bf24", +"47:orders_model_4.edge_count": "4e07408562bedb8b60ce05c1", +"48:orders_model_4.targeting": "2d45ce46fb153f6a59805da3", +"49:orders_model_4.sourced": "6786f18f6ff42aa577c99d86", +"4:orders_model_0.sourced": "0cf680b6627d425d75523b70", +"50:orders_model_7.has_model": "b5bea41b6c623f7c09f1bf24", +"51:orders_model_7.has_star": "fcbcf165908dd18a9e49f7ff", +"52:orders_model_7.edge_count": "7902699be42c8a8e46fbbb45", +"53:orders_model_7.targeting": "67bc1693660f805fe71b8562", +"54:orders_model_7.sourced": "6786f18f6ff42aa577c99d86", +"55:orders_model_11.has_model": "b5bea41b6c623f7c09f1bf24", +"56:orders_model_11.has_star": "fcbcf165908dd18a9e49f7ff", +"57:orders_model_11.edge_count": "6b86b273ff34fce19d6b804e", +"58:orders_model_11.targeting": "71858f9d94fda04aed071aa0", +"59:orders_model_11.sourced": "6786f18f6ff42aa577c99d86", +"5:orders_model_12.has_model": "fcbcf165908dd18a9e49f7ff", +"60:orders_model_14.has_model": "b5bea41b6c623f7c09f1bf24", +"61:orders_model_14.has_star": "fcbcf165908dd18a9e49f7ff", +"62:orders_model_14.edge_count": "d4735e3a265e16eee03f5971", +"63:orders_model_14.targeting": "9402db7a493e80bca6d9bf8c", +"64:orders_model_14.sourced": "6786f18f6ff42aa577c99d86", +"65:orders_model_2.has_model": "b5bea41b6c623f7c09f1bf24", +"66:orders_model_2.has_star": "fcbcf165908dd18a9e49f7ff", +"67:orders_model_2.edge_count": "6b86b273ff34fce19d6b804e", +"68:orders_model_2.targeting": "944516a2d4e18b4cc263aa14", +"69:orders_model_2.sourced": "0be757d135da1c02bdf86760", +"6:orders_model_12.has_star": "fcbcf165908dd18a9e49f7ff", +"70:orders_model_5.has_model": "b5bea41b6c623f7c09f1bf24", +"71:orders_model_5.has_star": "fcbcf165908dd18a9e49f7ff", +"72:orders_model_5.edge_count": "d4735e3a265e16eee03f5971", +"73:orders_model_5.targeting": "eeeef68a0473424e96f4b55e", +"74:orders_model_5.sourced": "2380b94a2203ebdd80fee91b", +"75:orders_model_8.has_model": "b5bea41b6c623f7c09f1bf24", +"76:orders_model_8.has_star": "b5bea41b6c623f7c09f1bf24", +"77:orders_model_8.edge_count": "4e07408562bedb8b60ce05c1", +"78:orders_model_8.targeting": "46d90f7d3dfc791867204a4c", +"79:orders_model_8.sourced": "6786f18f6ff42aa577c99d86", +"7:orders_model_12.edge_count": "5feceb66ffc86f38d952786c", +"80:models": "cd078ceff6e73868a0930f57", +"81:edges": "1e08d370da3b775c6f1f8cec", +"8:orders_model_12.targeting": "6786f18f6ff42aa577c99d86", +"9:orders_model_12.sourced": "6786f18f6ff42aa577c99d86" +} +], +[ +"lineage", +{ +"0:orders_model_0.has_model": "b5bea41b6c623f7c09f1bf24", +"10:orders_model_15.has_model": "b5bea41b6c623f7c09f1bf24", +"11:orders_model_15.has_star": "fcbcf165908dd18a9e49f7ff", +"12:orders_model_15.edge_count": "4e07408562bedb8b60ce05c1", +"13:orders_model_15.targeting": "2670c877f940c332e0ed75b6", +"14:orders_model_15.sourced": "6786f18f6ff42aa577c99d86", +"15:orders_model_3.has_model": "b5bea41b6c623f7c09f1bf24", +"16:orders_model_3.has_star": "fcbcf165908dd18a9e49f7ff", +"17:orders_model_3.edge_count": "d4735e3a265e16eee03f5971", +"18:orders_model_3.targeting": "76047432b32c8034e32c2670", +"19:orders_model_3.sourced": "6786f18f6ff42aa577c99d86", +"1:orders_model_0.has_star": "b5bea41b6c623f7c09f1bf24", +"20:orders_model_6.has_model": "fcbcf165908dd18a9e49f7ff", +"21:orders_model_6.has_star": "fcbcf165908dd18a9e49f7ff", +"22:orders_model_6.edge_count": "5feceb66ffc86f38d952786c", +"23:orders_model_6.targeting": "6786f18f6ff42aa577c99d86", +"24:orders_model_6.sourced": "2670c877f940c332e0ed75b6", +"25:orders_model_9.has_model": "fcbcf165908dd18a9e49f7ff", +"26:orders_model_9.has_star": "fcbcf165908dd18a9e49f7ff", +"27:orders_model_9.edge_count": "5feceb66ffc86f38d952786c", +"28:orders_model_9.targeting": "6786f18f6ff42aa577c99d86", +"29:orders_model_9.sourced": "ba772cfacb11c32601e27380", +"2:orders_model_0.edge_count": "4e07408562bedb8b60ce05c1", +"30:orders_model_1.has_model": "fcbcf165908dd18a9e49f7ff", +"31:orders_model_1.has_star": "fcbcf165908dd18a9e49f7ff", +"32:orders_model_1.edge_count": "5feceb66ffc86f38d952786c", +"33:orders_model_1.targeting": "6786f18f6ff42aa577c99d86", +"34:orders_model_1.sourced": "6786f18f6ff42aa577c99d86", +"35:orders_model_10.has_model": "b5bea41b6c623f7c09f1bf24", +"36:orders_model_10.has_star": "b5bea41b6c623f7c09f1bf24", +"37:orders_model_10.edge_count": "e7f6c011776e8db7cd330b54", +"38:orders_model_10.targeting": "86484ebd52c56f5232097531", +"39:orders_model_10.sourced": "6786f18f6ff42aa577c99d86", +"3:orders_model_0.targeting": "d11526ad01eb59472574a2a3", +"40:orders_model_13.has_model": "b5bea41b6c623f7c09f1bf24", +"41:orders_model_13.has_star": "b5bea41b6c623f7c09f1bf24", +"42:orders_model_13.edge_count": "d4735e3a265e16eee03f5971", +"43:orders_model_13.targeting": "a7fe2c291b441e90fb5a61b8", +"44:orders_model_13.sourced": "6786f18f6ff42aa577c99d86", +"45:orders_model_4.has_model": "b5bea41b6c623f7c09f1bf24", +"46:orders_model_4.has_star": "b5bea41b6c623f7c09f1bf24", +"47:orders_model_4.edge_count": "4e07408562bedb8b60ce05c1", +"48:orders_model_4.targeting": "2d45ce46fb153f6a59805da3", +"49:orders_model_4.sourced": "6786f18f6ff42aa577c99d86", +"4:orders_model_0.sourced": "2d45ce46fb153f6a59805da3", +"50:orders_model_7.has_model": "fcbcf165908dd18a9e49f7ff", +"51:orders_model_7.has_star": "fcbcf165908dd18a9e49f7ff", +"52:orders_model_7.edge_count": "5feceb66ffc86f38d952786c", +"53:orders_model_7.targeting": "6786f18f6ff42aa577c99d86", +"54:orders_model_7.sourced": "6786f18f6ff42aa577c99d86", +"55:orders_model_11.has_model": "fcbcf165908dd18a9e49f7ff", +"56:orders_model_11.has_star": "fcbcf165908dd18a9e49f7ff", +"57:orders_model_11.edge_count": "5feceb66ffc86f38d952786c", +"58:orders_model_11.targeting": "6786f18f6ff42aa577c99d86", +"59:orders_model_11.sourced": "6786f18f6ff42aa577c99d86", +"5:orders_model_12.has_model": "fcbcf165908dd18a9e49f7ff", +"60:orders_model_14.has_model": "fcbcf165908dd18a9e49f7ff", +"61:orders_model_14.has_star": "fcbcf165908dd18a9e49f7ff", +"62:orders_model_14.edge_count": "5feceb66ffc86f38d952786c", +"63:orders_model_14.targeting": "6786f18f6ff42aa577c99d86", +"64:orders_model_14.sourced": "6786f18f6ff42aa577c99d86", +"65:orders_model_2.has_model": "b5bea41b6c623f7c09f1bf24", +"66:orders_model_2.has_star": "fcbcf165908dd18a9e49f7ff", +"67:orders_model_2.edge_count": "6b86b273ff34fce19d6b804e", +"68:orders_model_2.targeting": "944516a2d4e18b4cc263aa14", +"69:orders_model_2.sourced": "0be757d135da1c02bdf86760", +"6:orders_model_12.has_star": "fcbcf165908dd18a9e49f7ff", +"70:orders_model_5.has_model": "fcbcf165908dd18a9e49f7ff", +"71:orders_model_5.has_star": "fcbcf165908dd18a9e49f7ff", +"72:orders_model_5.edge_count": "5feceb66ffc86f38d952786c", +"73:orders_model_5.targeting": "6786f18f6ff42aa577c99d86", +"74:orders_model_5.sourced": "6786f18f6ff42aa577c99d86", +"75:orders_model_8.has_model": "fcbcf165908dd18a9e49f7ff", +"76:orders_model_8.has_star": "fcbcf165908dd18a9e49f7ff", +"77:orders_model_8.edge_count": "5feceb66ffc86f38d952786c", +"78:orders_model_8.targeting": "6786f18f6ff42aa577c99d86", +"79:orders_model_8.sourced": "6786f18f6ff42aa577c99d86", +"7:orders_model_12.edge_count": "5feceb66ffc86f38d952786c", +"80:models": "42d3866a260676aa81413170", +"81:edges": "d40d2911f4142b96d5bebfc1", +"8:orders_model_12.targeting": "6786f18f6ff42aa577c99d86", +"9:orders_model_12.sourced": "6786f18f6ff42aa577c99d86" +} +], +[ +"lineage", +{ +"0:orders_model_0.has_model": "b5bea41b6c623f7c09f1bf24", +"10:orders_model_15.has_model": "b5bea41b6c623f7c09f1bf24", +"11:orders_model_15.has_star": "fcbcf165908dd18a9e49f7ff", +"12:orders_model_15.edge_count": "4e07408562bedb8b60ce05c1", +"13:orders_model_15.targeting": "2670c877f940c332e0ed75b6", +"14:orders_model_15.sourced": "6786f18f6ff42aa577c99d86", +"15:orders_model_3.has_model": "b5bea41b6c623f7c09f1bf24", +"16:orders_model_3.has_star": "fcbcf165908dd18a9e49f7ff", +"17:orders_model_3.edge_count": "d4735e3a265e16eee03f5971", +"18:orders_model_3.targeting": "76047432b32c8034e32c2670", +"19:orders_model_3.sourced": "9402db7a493e80bca6d9bf8c", +"1:orders_model_0.has_star": "b5bea41b6c623f7c09f1bf24", +"20:orders_model_6.has_model": "b5bea41b6c623f7c09f1bf24", +"21:orders_model_6.has_star": "fcbcf165908dd18a9e49f7ff", +"22:orders_model_6.edge_count": "4e07408562bedb8b60ce05c1", +"23:orders_model_6.targeting": "2380b94a2203ebdd80fee91b", +"24:orders_model_6.sourced": "2670c877f940c332e0ed75b6", +"25:orders_model_9.has_model": "b5bea41b6c623f7c09f1bf24", +"26:orders_model_9.has_star": "b5bea41b6c623f7c09f1bf24", +"27:orders_model_9.edge_count": "4e07408562bedb8b60ce05c1", +"28:orders_model_9.targeting": "09930b7e9d1880a7b1ca2490", +"29:orders_model_9.sourced": "ba772cfacb11c32601e27380", +"2:orders_model_0.edge_count": "4e07408562bedb8b60ce05c1", +"30:orders_model_1.has_model": "b5bea41b6c623f7c09f1bf24", +"31:orders_model_1.has_star": "b5bea41b6c623f7c09f1bf24", +"32:orders_model_1.edge_count": "7902699be42c8a8e46fbbb45", +"33:orders_model_1.targeting": "c9904eaf37f8410c86a5700e", +"34:orders_model_1.sourced": "67bc1693660f805fe71b8562", +"35:orders_model_10.has_model": "b5bea41b6c623f7c09f1bf24", +"36:orders_model_10.has_star": "b5bea41b6c623f7c09f1bf24", +"37:orders_model_10.edge_count": "e7f6c011776e8db7cd330b54", +"38:orders_model_10.targeting": "86484ebd52c56f5232097531", +"39:orders_model_10.sourced": "71858f9d94fda04aed071aa0", +"3:orders_model_0.targeting": "d11526ad01eb59472574a2a3", +"40:orders_model_13.has_model": "b5bea41b6c623f7c09f1bf24", +"41:orders_model_13.has_star": "b5bea41b6c623f7c09f1bf24", +"42:orders_model_13.edge_count": "d4735e3a265e16eee03f5971", +"43:orders_model_13.targeting": "a7fe2c291b441e90fb5a61b8", +"44:orders_model_13.sourced": "6786f18f6ff42aa577c99d86", +"45:orders_model_4.has_model": "b5bea41b6c623f7c09f1bf24", +"46:orders_model_4.has_star": "b5bea41b6c623f7c09f1bf24", +"47:orders_model_4.edge_count": "4e07408562bedb8b60ce05c1", +"48:orders_model_4.targeting": "2d45ce46fb153f6a59805da3", +"49:orders_model_4.sourced": "6786f18f6ff42aa577c99d86", +"4:orders_model_0.sourced": "0cf680b6627d425d75523b70", +"50:orders_model_7.has_model": "b5bea41b6c623f7c09f1bf24", +"51:orders_model_7.has_star": "fcbcf165908dd18a9e49f7ff", +"52:orders_model_7.edge_count": "7902699be42c8a8e46fbbb45", +"53:orders_model_7.targeting": "67bc1693660f805fe71b8562", +"54:orders_model_7.sourced": "6786f18f6ff42aa577c99d86", +"55:orders_model_11.has_model": "b5bea41b6c623f7c09f1bf24", +"56:orders_model_11.has_star": "fcbcf165908dd18a9e49f7ff", +"57:orders_model_11.edge_count": "6b86b273ff34fce19d6b804e", +"58:orders_model_11.targeting": "71858f9d94fda04aed071aa0", +"59:orders_model_11.sourced": "6786f18f6ff42aa577c99d86", +"5:orders_model_12.has_model": "fcbcf165908dd18a9e49f7ff", +"60:orders_model_14.has_model": "b5bea41b6c623f7c09f1bf24", +"61:orders_model_14.has_star": "fcbcf165908dd18a9e49f7ff", +"62:orders_model_14.edge_count": "d4735e3a265e16eee03f5971", +"63:orders_model_14.targeting": "9402db7a493e80bca6d9bf8c", +"64:orders_model_14.sourced": "6786f18f6ff42aa577c99d86", +"65:orders_model_2.has_model": "b5bea41b6c623f7c09f1bf24", +"66:orders_model_2.has_star": "fcbcf165908dd18a9e49f7ff", +"67:orders_model_2.edge_count": "6b86b273ff34fce19d6b804e", +"68:orders_model_2.targeting": "944516a2d4e18b4cc263aa14", +"69:orders_model_2.sourced": "0be757d135da1c02bdf86760", +"6:orders_model_12.has_star": "fcbcf165908dd18a9e49f7ff", +"70:orders_model_5.has_model": "b5bea41b6c623f7c09f1bf24", +"71:orders_model_5.has_star": "fcbcf165908dd18a9e49f7ff", +"72:orders_model_5.edge_count": "d4735e3a265e16eee03f5971", +"73:orders_model_5.targeting": "eeeef68a0473424e96f4b55e", +"74:orders_model_5.sourced": "2380b94a2203ebdd80fee91b", +"75:orders_model_8.has_model": "b5bea41b6c623f7c09f1bf24", +"76:orders_model_8.has_star": "b5bea41b6c623f7c09f1bf24", +"77:orders_model_8.edge_count": "4e07408562bedb8b60ce05c1", +"78:orders_model_8.targeting": "46d90f7d3dfc791867204a4c", +"79:orders_model_8.sourced": "6786f18f6ff42aa577c99d86", +"7:orders_model_12.edge_count": "5feceb66ffc86f38d952786c", +"80:models": "cd078ceff6e73868a0930f57", +"81:edges": "1e08d370da3b775c6f1f8cec", +"8:orders_model_12.targeting": "6786f18f6ff42aa577c99d86", +"9:orders_model_12.sourced": "6786f18f6ff42aa577c99d86" +} +], +[ +"lineage", +{ +"0:orders_model_0.has_model": "b5bea41b6c623f7c09f1bf24", +"10:orders_model_15.has_model": "b5bea41b6c623f7c09f1bf24", +"11:orders_model_15.has_star": "fcbcf165908dd18a9e49f7ff", +"12:orders_model_15.edge_count": "4e07408562bedb8b60ce05c1", +"13:orders_model_15.targeting": "2670c877f940c332e0ed75b6", +"14:orders_model_15.sourced": "6786f18f6ff42aa577c99d86", +"15:orders_model_3.has_model": "b5bea41b6c623f7c09f1bf24", +"16:orders_model_3.has_star": "fcbcf165908dd18a9e49f7ff", +"17:orders_model_3.edge_count": "d4735e3a265e16eee03f5971", +"18:orders_model_3.targeting": "76047432b32c8034e32c2670", +"19:orders_model_3.sourced": "6786f18f6ff42aa577c99d86", +"1:orders_model_0.has_star": "b5bea41b6c623f7c09f1bf24", +"20:orders_model_6.has_model": "fcbcf165908dd18a9e49f7ff", +"21:orders_model_6.has_star": "fcbcf165908dd18a9e49f7ff", +"22:orders_model_6.edge_count": "5feceb66ffc86f38d952786c", +"23:orders_model_6.targeting": "6786f18f6ff42aa577c99d86", +"24:orders_model_6.sourced": "2670c877f940c332e0ed75b6", +"25:orders_model_9.has_model": "fcbcf165908dd18a9e49f7ff", +"26:orders_model_9.has_star": "fcbcf165908dd18a9e49f7ff", +"27:orders_model_9.edge_count": "5feceb66ffc86f38d952786c", +"28:orders_model_9.targeting": "6786f18f6ff42aa577c99d86", +"29:orders_model_9.sourced": "ba772cfacb11c32601e27380", +"2:orders_model_0.edge_count": "4e07408562bedb8b60ce05c1", +"30:orders_model_1.has_model": "fcbcf165908dd18a9e49f7ff", +"31:orders_model_1.has_star": "fcbcf165908dd18a9e49f7ff", +"32:orders_model_1.edge_count": "5feceb66ffc86f38d952786c", +"33:orders_model_1.targeting": "6786f18f6ff42aa577c99d86", +"34:orders_model_1.sourced": "6786f18f6ff42aa577c99d86", +"35:orders_model_10.has_model": "b5bea41b6c623f7c09f1bf24", +"36:orders_model_10.has_star": "b5bea41b6c623f7c09f1bf24", +"37:orders_model_10.edge_count": "e7f6c011776e8db7cd330b54", +"38:orders_model_10.targeting": "86484ebd52c56f5232097531", +"39:orders_model_10.sourced": "6786f18f6ff42aa577c99d86", +"3:orders_model_0.targeting": "d11526ad01eb59472574a2a3", +"40:orders_model_13.has_model": "b5bea41b6c623f7c09f1bf24", +"41:orders_model_13.has_star": "b5bea41b6c623f7c09f1bf24", +"42:orders_model_13.edge_count": "d4735e3a265e16eee03f5971", +"43:orders_model_13.targeting": "a7fe2c291b441e90fb5a61b8", +"44:orders_model_13.sourced": "6786f18f6ff42aa577c99d86", +"45:orders_model_4.has_model": "b5bea41b6c623f7c09f1bf24", +"46:orders_model_4.has_star": "b5bea41b6c623f7c09f1bf24", +"47:orders_model_4.edge_count": "4e07408562bedb8b60ce05c1", +"48:orders_model_4.targeting": "2d45ce46fb153f6a59805da3", +"49:orders_model_4.sourced": "6786f18f6ff42aa577c99d86", +"4:orders_model_0.sourced": "2d45ce46fb153f6a59805da3", +"50:orders_model_7.has_model": "fcbcf165908dd18a9e49f7ff", +"51:orders_model_7.has_star": "fcbcf165908dd18a9e49f7ff", +"52:orders_model_7.edge_count": "5feceb66ffc86f38d952786c", +"53:orders_model_7.targeting": "6786f18f6ff42aa577c99d86", +"54:orders_model_7.sourced": "6786f18f6ff42aa577c99d86", +"55:orders_model_11.has_model": "fcbcf165908dd18a9e49f7ff", +"56:orders_model_11.has_star": "fcbcf165908dd18a9e49f7ff", +"57:orders_model_11.edge_count": "5feceb66ffc86f38d952786c", +"58:orders_model_11.targeting": "6786f18f6ff42aa577c99d86", +"59:orders_model_11.sourced": "6786f18f6ff42aa577c99d86", +"5:orders_model_12.has_model": "fcbcf165908dd18a9e49f7ff", +"60:orders_model_14.has_model": "fcbcf165908dd18a9e49f7ff", +"61:orders_model_14.has_star": "fcbcf165908dd18a9e49f7ff", +"62:orders_model_14.edge_count": "5feceb66ffc86f38d952786c", +"63:orders_model_14.targeting": "6786f18f6ff42aa577c99d86", +"64:orders_model_14.sourced": "6786f18f6ff42aa577c99d86", +"65:orders_model_2.has_model": "b5bea41b6c623f7c09f1bf24", +"66:orders_model_2.has_star": "fcbcf165908dd18a9e49f7ff", +"67:orders_model_2.edge_count": "6b86b273ff34fce19d6b804e", +"68:orders_model_2.targeting": "944516a2d4e18b4cc263aa14", +"69:orders_model_2.sourced": "0be757d135da1c02bdf86760", +"6:orders_model_12.has_star": "fcbcf165908dd18a9e49f7ff", +"70:orders_model_5.has_model": "fcbcf165908dd18a9e49f7ff", +"71:orders_model_5.has_star": "fcbcf165908dd18a9e49f7ff", +"72:orders_model_5.edge_count": "5feceb66ffc86f38d952786c", +"73:orders_model_5.targeting": "6786f18f6ff42aa577c99d86", +"74:orders_model_5.sourced": "6786f18f6ff42aa577c99d86", +"75:orders_model_8.has_model": "fcbcf165908dd18a9e49f7ff", +"76:orders_model_8.has_star": "fcbcf165908dd18a9e49f7ff", +"77:orders_model_8.edge_count": "5feceb66ffc86f38d952786c", +"78:orders_model_8.targeting": "6786f18f6ff42aa577c99d86", +"79:orders_model_8.sourced": "6786f18f6ff42aa577c99d86", +"7:orders_model_12.edge_count": "5feceb66ffc86f38d952786c", +"80:models": "42d3866a260676aa81413170", +"81:edges": "d40d2911f4142b96d5bebfc1", +"8:orders_model_12.targeting": "6786f18f6ff42aa577c99d86", +"9:orders_model_12.sourced": "6786f18f6ff42aa577c99d86" +} +], +[ +"lineage", +{ +"0:orders_model_0.has_model": "b5bea41b6c623f7c09f1bf24", +"10:orders_model_15.has_model": "b5bea41b6c623f7c09f1bf24", +"11:orders_model_15.has_star": "fcbcf165908dd18a9e49f7ff", +"12:orders_model_15.edge_count": "4e07408562bedb8b60ce05c1", +"13:orders_model_15.targeting": "2670c877f940c332e0ed75b6", +"14:orders_model_15.sourced": "6786f18f6ff42aa577c99d86", +"15:orders_model_3.has_model": "b5bea41b6c623f7c09f1bf24", +"16:orders_model_3.has_star": "fcbcf165908dd18a9e49f7ff", +"17:orders_model_3.edge_count": "d4735e3a265e16eee03f5971", +"18:orders_model_3.targeting": "76047432b32c8034e32c2670", +"19:orders_model_3.sourced": "9402db7a493e80bca6d9bf8c", +"1:orders_model_0.has_star": "b5bea41b6c623f7c09f1bf24", +"20:orders_model_6.has_model": "b5bea41b6c623f7c09f1bf24", +"21:orders_model_6.has_star": "fcbcf165908dd18a9e49f7ff", +"22:orders_model_6.edge_count": "4e07408562bedb8b60ce05c1", +"23:orders_model_6.targeting": "2380b94a2203ebdd80fee91b", +"24:orders_model_6.sourced": "2670c877f940c332e0ed75b6", +"25:orders_model_9.has_model": "b5bea41b6c623f7c09f1bf24", +"26:orders_model_9.has_star": "b5bea41b6c623f7c09f1bf24", +"27:orders_model_9.edge_count": "4e07408562bedb8b60ce05c1", +"28:orders_model_9.targeting": "09930b7e9d1880a7b1ca2490", +"29:orders_model_9.sourced": "ba772cfacb11c32601e27380", +"2:orders_model_0.edge_count": "4e07408562bedb8b60ce05c1", +"30:orders_model_1.has_model": "b5bea41b6c623f7c09f1bf24", +"31:orders_model_1.has_star": "b5bea41b6c623f7c09f1bf24", +"32:orders_model_1.edge_count": "7902699be42c8a8e46fbbb45", +"33:orders_model_1.targeting": "c9904eaf37f8410c86a5700e", +"34:orders_model_1.sourced": "67bc1693660f805fe71b8562", +"35:orders_model_10.has_model": "b5bea41b6c623f7c09f1bf24", +"36:orders_model_10.has_star": "b5bea41b6c623f7c09f1bf24", +"37:orders_model_10.edge_count": "e7f6c011776e8db7cd330b54", +"38:orders_model_10.targeting": "86484ebd52c56f5232097531", +"39:orders_model_10.sourced": "71858f9d94fda04aed071aa0", +"3:orders_model_0.targeting": "d11526ad01eb59472574a2a3", +"40:orders_model_13.has_model": "b5bea41b6c623f7c09f1bf24", +"41:orders_model_13.has_star": "b5bea41b6c623f7c09f1bf24", +"42:orders_model_13.edge_count": "d4735e3a265e16eee03f5971", +"43:orders_model_13.targeting": "a7fe2c291b441e90fb5a61b8", +"44:orders_model_13.sourced": "6786f18f6ff42aa577c99d86", +"45:orders_model_4.has_model": "b5bea41b6c623f7c09f1bf24", +"46:orders_model_4.has_star": "b5bea41b6c623f7c09f1bf24", +"47:orders_model_4.edge_count": "4e07408562bedb8b60ce05c1", +"48:orders_model_4.targeting": "2d45ce46fb153f6a59805da3", +"49:orders_model_4.sourced": "6786f18f6ff42aa577c99d86", +"4:orders_model_0.sourced": "0cf680b6627d425d75523b70", +"50:orders_model_7.has_model": "b5bea41b6c623f7c09f1bf24", +"51:orders_model_7.has_star": "fcbcf165908dd18a9e49f7ff", +"52:orders_model_7.edge_count": "7902699be42c8a8e46fbbb45", +"53:orders_model_7.targeting": "67bc1693660f805fe71b8562", +"54:orders_model_7.sourced": "6786f18f6ff42aa577c99d86", +"55:orders_model_11.has_model": "b5bea41b6c623f7c09f1bf24", +"56:orders_model_11.has_star": "fcbcf165908dd18a9e49f7ff", +"57:orders_model_11.edge_count": "6b86b273ff34fce19d6b804e", +"58:orders_model_11.targeting": "71858f9d94fda04aed071aa0", +"59:orders_model_11.sourced": "6786f18f6ff42aa577c99d86", +"5:orders_model_12.has_model": "fcbcf165908dd18a9e49f7ff", +"60:orders_model_14.has_model": "b5bea41b6c623f7c09f1bf24", +"61:orders_model_14.has_star": "fcbcf165908dd18a9e49f7ff", +"62:orders_model_14.edge_count": "d4735e3a265e16eee03f5971", +"63:orders_model_14.targeting": "9402db7a493e80bca6d9bf8c", +"64:orders_model_14.sourced": "6786f18f6ff42aa577c99d86", +"65:orders_model_2.has_model": "b5bea41b6c623f7c09f1bf24", +"66:orders_model_2.has_star": "fcbcf165908dd18a9e49f7ff", +"67:orders_model_2.edge_count": "6b86b273ff34fce19d6b804e", +"68:orders_model_2.targeting": "944516a2d4e18b4cc263aa14", +"69:orders_model_2.sourced": "0be757d135da1c02bdf86760", +"6:orders_model_12.has_star": "fcbcf165908dd18a9e49f7ff", +"70:orders_model_5.has_model": "b5bea41b6c623f7c09f1bf24", +"71:orders_model_5.has_star": "fcbcf165908dd18a9e49f7ff", +"72:orders_model_5.edge_count": "d4735e3a265e16eee03f5971", +"73:orders_model_5.targeting": "eeeef68a0473424e96f4b55e", +"74:orders_model_5.sourced": "2380b94a2203ebdd80fee91b", +"75:orders_model_8.has_model": "b5bea41b6c623f7c09f1bf24", +"76:orders_model_8.has_star": "b5bea41b6c623f7c09f1bf24", +"77:orders_model_8.edge_count": "4e07408562bedb8b60ce05c1", +"78:orders_model_8.targeting": "46d90f7d3dfc791867204a4c", +"79:orders_model_8.sourced": "6786f18f6ff42aa577c99d86", +"7:orders_model_12.edge_count": "5feceb66ffc86f38d952786c", +"80:models": "cd078ceff6e73868a0930f57", +"81:edges": "1e08d370da3b775c6f1f8cec", +"8:orders_model_12.targeting": "6786f18f6ff42aa577c99d86", +"9:orders_model_12.sourced": "6786f18f6ff42aa577c99d86" +} +], +[ +"lineage", +{ +"0:orders_model_0.has_model": "b5bea41b6c623f7c09f1bf24", +"10:orders_model_15.has_model": "b5bea41b6c623f7c09f1bf24", +"11:orders_model_15.has_star": "fcbcf165908dd18a9e49f7ff", +"12:orders_model_15.edge_count": "4e07408562bedb8b60ce05c1", +"13:orders_model_15.targeting": "2670c877f940c332e0ed75b6", +"14:orders_model_15.sourced": "6786f18f6ff42aa577c99d86", +"15:orders_model_3.has_model": "b5bea41b6c623f7c09f1bf24", +"16:orders_model_3.has_star": "fcbcf165908dd18a9e49f7ff", +"17:orders_model_3.edge_count": "d4735e3a265e16eee03f5971", +"18:orders_model_3.targeting": "76047432b32c8034e32c2670", +"19:orders_model_3.sourced": "6786f18f6ff42aa577c99d86", +"1:orders_model_0.has_star": "b5bea41b6c623f7c09f1bf24", +"20:orders_model_6.has_model": "fcbcf165908dd18a9e49f7ff", +"21:orders_model_6.has_star": "fcbcf165908dd18a9e49f7ff", +"22:orders_model_6.edge_count": "5feceb66ffc86f38d952786c", +"23:orders_model_6.targeting": "6786f18f6ff42aa577c99d86", +"24:orders_model_6.sourced": "2670c877f940c332e0ed75b6", +"25:orders_model_9.has_model": "fcbcf165908dd18a9e49f7ff", +"26:orders_model_9.has_star": "fcbcf165908dd18a9e49f7ff", +"27:orders_model_9.edge_count": "5feceb66ffc86f38d952786c", +"28:orders_model_9.targeting": "6786f18f6ff42aa577c99d86", +"29:orders_model_9.sourced": "ba772cfacb11c32601e27380", +"2:orders_model_0.edge_count": "4e07408562bedb8b60ce05c1", +"30:orders_model_1.has_model": "fcbcf165908dd18a9e49f7ff", +"31:orders_model_1.has_star": "fcbcf165908dd18a9e49f7ff", +"32:orders_model_1.edge_count": "5feceb66ffc86f38d952786c", +"33:orders_model_1.targeting": "6786f18f6ff42aa577c99d86", +"34:orders_model_1.sourced": "6786f18f6ff42aa577c99d86", +"35:orders_model_10.has_model": "b5bea41b6c623f7c09f1bf24", +"36:orders_model_10.has_star": "b5bea41b6c623f7c09f1bf24", +"37:orders_model_10.edge_count": "e7f6c011776e8db7cd330b54", +"38:orders_model_10.targeting": "86484ebd52c56f5232097531", +"39:orders_model_10.sourced": "6786f18f6ff42aa577c99d86", +"3:orders_model_0.targeting": "d11526ad01eb59472574a2a3", +"40:orders_model_13.has_model": "b5bea41b6c623f7c09f1bf24", +"41:orders_model_13.has_star": "b5bea41b6c623f7c09f1bf24", +"42:orders_model_13.edge_count": "d4735e3a265e16eee03f5971", +"43:orders_model_13.targeting": "a7fe2c291b441e90fb5a61b8", +"44:orders_model_13.sourced": "6786f18f6ff42aa577c99d86", +"45:orders_model_4.has_model": "b5bea41b6c623f7c09f1bf24", +"46:orders_model_4.has_star": "b5bea41b6c623f7c09f1bf24", +"47:orders_model_4.edge_count": "4e07408562bedb8b60ce05c1", +"48:orders_model_4.targeting": "2d45ce46fb153f6a59805da3", +"49:orders_model_4.sourced": "6786f18f6ff42aa577c99d86", +"4:orders_model_0.sourced": "2d45ce46fb153f6a59805da3", +"50:orders_model_7.has_model": "fcbcf165908dd18a9e49f7ff", +"51:orders_model_7.has_star": "fcbcf165908dd18a9e49f7ff", +"52:orders_model_7.edge_count": "5feceb66ffc86f38d952786c", +"53:orders_model_7.targeting": "6786f18f6ff42aa577c99d86", +"54:orders_model_7.sourced": "6786f18f6ff42aa577c99d86", +"55:orders_model_11.has_model": "fcbcf165908dd18a9e49f7ff", +"56:orders_model_11.has_star": "fcbcf165908dd18a9e49f7ff", +"57:orders_model_11.edge_count": "5feceb66ffc86f38d952786c", +"58:orders_model_11.targeting": "6786f18f6ff42aa577c99d86", +"59:orders_model_11.sourced": "6786f18f6ff42aa577c99d86", +"5:orders_model_12.has_model": "fcbcf165908dd18a9e49f7ff", +"60:orders_model_14.has_model": "fcbcf165908dd18a9e49f7ff", +"61:orders_model_14.has_star": "fcbcf165908dd18a9e49f7ff", +"62:orders_model_14.edge_count": "5feceb66ffc86f38d952786c", +"63:orders_model_14.targeting": "6786f18f6ff42aa577c99d86", +"64:orders_model_14.sourced": "6786f18f6ff42aa577c99d86", +"65:orders_model_2.has_model": "b5bea41b6c623f7c09f1bf24", +"66:orders_model_2.has_star": "fcbcf165908dd18a9e49f7ff", +"67:orders_model_2.edge_count": "6b86b273ff34fce19d6b804e", +"68:orders_model_2.targeting": "944516a2d4e18b4cc263aa14", +"69:orders_model_2.sourced": "0be757d135da1c02bdf86760", +"6:orders_model_12.has_star": "fcbcf165908dd18a9e49f7ff", +"70:orders_model_5.has_model": "fcbcf165908dd18a9e49f7ff", +"71:orders_model_5.has_star": "fcbcf165908dd18a9e49f7ff", +"72:orders_model_5.edge_count": "5feceb66ffc86f38d952786c", +"73:orders_model_5.targeting": "6786f18f6ff42aa577c99d86", +"74:orders_model_5.sourced": "6786f18f6ff42aa577c99d86", +"75:orders_model_8.has_model": "fcbcf165908dd18a9e49f7ff", +"76:orders_model_8.has_star": "fcbcf165908dd18a9e49f7ff", +"77:orders_model_8.edge_count": "5feceb66ffc86f38d952786c", +"78:orders_model_8.targeting": "6786f18f6ff42aa577c99d86", +"79:orders_model_8.sourced": "6786f18f6ff42aa577c99d86", +"7:orders_model_12.edge_count": "5feceb66ffc86f38d952786c", +"80:models": "42d3866a260676aa81413170", +"81:edges": "d40d2911f4142b96d5bebfc1", +"8:orders_model_12.targeting": "6786f18f6ff42aa577c99d86", +"9:orders_model_12.sourced": "6786f18f6ff42aa577c99d86" +} +], +[ +"lineage", +{ +"0:orders_model_0.has_model": "b5bea41b6c623f7c09f1bf24", +"10:orders_model_15.has_model": "b5bea41b6c623f7c09f1bf24", +"11:orders_model_15.has_star": "fcbcf165908dd18a9e49f7ff", +"12:orders_model_15.edge_count": "4e07408562bedb8b60ce05c1", +"13:orders_model_15.targeting": "2670c877f940c332e0ed75b6", +"14:orders_model_15.sourced": "6786f18f6ff42aa577c99d86", +"15:orders_model_3.has_model": "b5bea41b6c623f7c09f1bf24", +"16:orders_model_3.has_star": "fcbcf165908dd18a9e49f7ff", +"17:orders_model_3.edge_count": "d4735e3a265e16eee03f5971", +"18:orders_model_3.targeting": "76047432b32c8034e32c2670", +"19:orders_model_3.sourced": "9402db7a493e80bca6d9bf8c", +"1:orders_model_0.has_star": "b5bea41b6c623f7c09f1bf24", +"20:orders_model_6.has_model": "b5bea41b6c623f7c09f1bf24", +"21:orders_model_6.has_star": "fcbcf165908dd18a9e49f7ff", +"22:orders_model_6.edge_count": "4e07408562bedb8b60ce05c1", +"23:orders_model_6.targeting": "2380b94a2203ebdd80fee91b", +"24:orders_model_6.sourced": "2670c877f940c332e0ed75b6", +"25:orders_model_9.has_model": "b5bea41b6c623f7c09f1bf24", +"26:orders_model_9.has_star": "b5bea41b6c623f7c09f1bf24", +"27:orders_model_9.edge_count": "4e07408562bedb8b60ce05c1", +"28:orders_model_9.targeting": "09930b7e9d1880a7b1ca2490", +"29:orders_model_9.sourced": "ba772cfacb11c32601e27380", +"2:orders_model_0.edge_count": "4e07408562bedb8b60ce05c1", +"30:orders_model_1.has_model": "b5bea41b6c623f7c09f1bf24", +"31:orders_model_1.has_star": "b5bea41b6c623f7c09f1bf24", +"32:orders_model_1.edge_count": "7902699be42c8a8e46fbbb45", +"33:orders_model_1.targeting": "c9904eaf37f8410c86a5700e", +"34:orders_model_1.sourced": "67bc1693660f805fe71b8562", +"35:orders_model_10.has_model": "b5bea41b6c623f7c09f1bf24", +"36:orders_model_10.has_star": "b5bea41b6c623f7c09f1bf24", +"37:orders_model_10.edge_count": "e7f6c011776e8db7cd330b54", +"38:orders_model_10.targeting": "86484ebd52c56f5232097531", +"39:orders_model_10.sourced": "71858f9d94fda04aed071aa0", +"3:orders_model_0.targeting": "d11526ad01eb59472574a2a3", +"40:orders_model_13.has_model": "b5bea41b6c623f7c09f1bf24", +"41:orders_model_13.has_star": "b5bea41b6c623f7c09f1bf24", +"42:orders_model_13.edge_count": "d4735e3a265e16eee03f5971", +"43:orders_model_13.targeting": "a7fe2c291b441e90fb5a61b8", +"44:orders_model_13.sourced": "6786f18f6ff42aa577c99d86", +"45:orders_model_4.has_model": "b5bea41b6c623f7c09f1bf24", +"46:orders_model_4.has_star": "b5bea41b6c623f7c09f1bf24", +"47:orders_model_4.edge_count": "4e07408562bedb8b60ce05c1", +"48:orders_model_4.targeting": "2d45ce46fb153f6a59805da3", +"49:orders_model_4.sourced": "6786f18f6ff42aa577c99d86", +"4:orders_model_0.sourced": "0cf680b6627d425d75523b70", +"50:orders_model_7.has_model": "b5bea41b6c623f7c09f1bf24", +"51:orders_model_7.has_star": "fcbcf165908dd18a9e49f7ff", +"52:orders_model_7.edge_count": "7902699be42c8a8e46fbbb45", +"53:orders_model_7.targeting": "67bc1693660f805fe71b8562", +"54:orders_model_7.sourced": "6786f18f6ff42aa577c99d86", +"55:orders_model_11.has_model": "b5bea41b6c623f7c09f1bf24", +"56:orders_model_11.has_star": "fcbcf165908dd18a9e49f7ff", +"57:orders_model_11.edge_count": "6b86b273ff34fce19d6b804e", +"58:orders_model_11.targeting": "71858f9d94fda04aed071aa0", +"59:orders_model_11.sourced": "6786f18f6ff42aa577c99d86", +"5:orders_model_12.has_model": "fcbcf165908dd18a9e49f7ff", +"60:orders_model_14.has_model": "b5bea41b6c623f7c09f1bf24", +"61:orders_model_14.has_star": "fcbcf165908dd18a9e49f7ff", +"62:orders_model_14.edge_count": "d4735e3a265e16eee03f5971", +"63:orders_model_14.targeting": "9402db7a493e80bca6d9bf8c", +"64:orders_model_14.sourced": "6786f18f6ff42aa577c99d86", +"65:orders_model_2.has_model": "b5bea41b6c623f7c09f1bf24", +"66:orders_model_2.has_star": "fcbcf165908dd18a9e49f7ff", +"67:orders_model_2.edge_count": "6b86b273ff34fce19d6b804e", +"68:orders_model_2.targeting": "944516a2d4e18b4cc263aa14", +"69:orders_model_2.sourced": "0be757d135da1c02bdf86760", +"6:orders_model_12.has_star": "fcbcf165908dd18a9e49f7ff", +"70:orders_model_5.has_model": "b5bea41b6c623f7c09f1bf24", +"71:orders_model_5.has_star": "fcbcf165908dd18a9e49f7ff", +"72:orders_model_5.edge_count": "d4735e3a265e16eee03f5971", +"73:orders_model_5.targeting": "eeeef68a0473424e96f4b55e", +"74:orders_model_5.sourced": "2380b94a2203ebdd80fee91b", +"75:orders_model_8.has_model": "b5bea41b6c623f7c09f1bf24", +"76:orders_model_8.has_star": "b5bea41b6c623f7c09f1bf24", +"77:orders_model_8.edge_count": "4e07408562bedb8b60ce05c1", +"78:orders_model_8.targeting": "46d90f7d3dfc791867204a4c", +"79:orders_model_8.sourced": "6786f18f6ff42aa577c99d86", +"7:orders_model_12.edge_count": "5feceb66ffc86f38d952786c", +"80:models": "cd078ceff6e73868a0930f57", +"81:edges": "1e08d370da3b775c6f1f8cec", +"8:orders_model_12.targeting": "6786f18f6ff42aa577c99d86", +"9:orders_model_12.sourced": "6786f18f6ff42aa577c99d86" +} +], +[ +"lineage", +{ +"0:orders_model_0.has_model": "b5bea41b6c623f7c09f1bf24", +"10:orders_model_15.has_model": "b5bea41b6c623f7c09f1bf24", +"11:orders_model_15.has_star": "fcbcf165908dd18a9e49f7ff", +"12:orders_model_15.edge_count": "4e07408562bedb8b60ce05c1", +"13:orders_model_15.targeting": "2670c877f940c332e0ed75b6", +"14:orders_model_15.sourced": "6786f18f6ff42aa577c99d86", +"15:orders_model_3.has_model": "b5bea41b6c623f7c09f1bf24", +"16:orders_model_3.has_star": "fcbcf165908dd18a9e49f7ff", +"17:orders_model_3.edge_count": "d4735e3a265e16eee03f5971", +"18:orders_model_3.targeting": "76047432b32c8034e32c2670", +"19:orders_model_3.sourced": "6786f18f6ff42aa577c99d86", +"1:orders_model_0.has_star": "b5bea41b6c623f7c09f1bf24", +"20:orders_model_6.has_model": "fcbcf165908dd18a9e49f7ff", +"21:orders_model_6.has_star": "fcbcf165908dd18a9e49f7ff", +"22:orders_model_6.edge_count": "5feceb66ffc86f38d952786c", +"23:orders_model_6.targeting": "6786f18f6ff42aa577c99d86", +"24:orders_model_6.sourced": "2670c877f940c332e0ed75b6", +"25:orders_model_9.has_model": "fcbcf165908dd18a9e49f7ff", +"26:orders_model_9.has_star": "fcbcf165908dd18a9e49f7ff", +"27:orders_model_9.edge_count": "5feceb66ffc86f38d952786c", +"28:orders_model_9.targeting": "6786f18f6ff42aa577c99d86", +"29:orders_model_9.sourced": "ba772cfacb11c32601e27380", +"2:orders_model_0.edge_count": "4e07408562bedb8b60ce05c1", +"30:orders_model_1.has_model": "fcbcf165908dd18a9e49f7ff", +"31:orders_model_1.has_star": "fcbcf165908dd18a9e49f7ff", +"32:orders_model_1.edge_count": "5feceb66ffc86f38d952786c", +"33:orders_model_1.targeting": "6786f18f6ff42aa577c99d86", +"34:orders_model_1.sourced": "6786f18f6ff42aa577c99d86", +"35:orders_model_10.has_model": "b5bea41b6c623f7c09f1bf24", +"36:orders_model_10.has_star": "b5bea41b6c623f7c09f1bf24", +"37:orders_model_10.edge_count": "e7f6c011776e8db7cd330b54", +"38:orders_model_10.targeting": "86484ebd52c56f5232097531", +"39:orders_model_10.sourced": "6786f18f6ff42aa577c99d86", +"3:orders_model_0.targeting": "d11526ad01eb59472574a2a3", +"40:orders_model_13.has_model": "b5bea41b6c623f7c09f1bf24", +"41:orders_model_13.has_star": "b5bea41b6c623f7c09f1bf24", +"42:orders_model_13.edge_count": "d4735e3a265e16eee03f5971", +"43:orders_model_13.targeting": "a7fe2c291b441e90fb5a61b8", +"44:orders_model_13.sourced": "6786f18f6ff42aa577c99d86", +"45:orders_model_4.has_model": "b5bea41b6c623f7c09f1bf24", +"46:orders_model_4.has_star": "b5bea41b6c623f7c09f1bf24", +"47:orders_model_4.edge_count": "4e07408562bedb8b60ce05c1", +"48:orders_model_4.targeting": "2d45ce46fb153f6a59805da3", +"49:orders_model_4.sourced": "6786f18f6ff42aa577c99d86", +"4:orders_model_0.sourced": "2d45ce46fb153f6a59805da3", +"50:orders_model_7.has_model": "fcbcf165908dd18a9e49f7ff", +"51:orders_model_7.has_star": "fcbcf165908dd18a9e49f7ff", +"52:orders_model_7.edge_count": "5feceb66ffc86f38d952786c", +"53:orders_model_7.targeting": "6786f18f6ff42aa577c99d86", +"54:orders_model_7.sourced": "6786f18f6ff42aa577c99d86", +"55:orders_model_11.has_model": "fcbcf165908dd18a9e49f7ff", +"56:orders_model_11.has_star": "fcbcf165908dd18a9e49f7ff", +"57:orders_model_11.edge_count": "5feceb66ffc86f38d952786c", +"58:orders_model_11.targeting": "6786f18f6ff42aa577c99d86", +"59:orders_model_11.sourced": "6786f18f6ff42aa577c99d86", +"5:orders_model_12.has_model": "fcbcf165908dd18a9e49f7ff", +"60:orders_model_14.has_model": "fcbcf165908dd18a9e49f7ff", +"61:orders_model_14.has_star": "fcbcf165908dd18a9e49f7ff", +"62:orders_model_14.edge_count": "5feceb66ffc86f38d952786c", +"63:orders_model_14.targeting": "6786f18f6ff42aa577c99d86", +"64:orders_model_14.sourced": "6786f18f6ff42aa577c99d86", +"65:orders_model_2.has_model": "b5bea41b6c623f7c09f1bf24", +"66:orders_model_2.has_star": "fcbcf165908dd18a9e49f7ff", +"67:orders_model_2.edge_count": "6b86b273ff34fce19d6b804e", +"68:orders_model_2.targeting": "944516a2d4e18b4cc263aa14", +"69:orders_model_2.sourced": "0be757d135da1c02bdf86760", +"6:orders_model_12.has_star": "fcbcf165908dd18a9e49f7ff", +"70:orders_model_5.has_model": "fcbcf165908dd18a9e49f7ff", +"71:orders_model_5.has_star": "fcbcf165908dd18a9e49f7ff", +"72:orders_model_5.edge_count": "5feceb66ffc86f38d952786c", +"73:orders_model_5.targeting": "6786f18f6ff42aa577c99d86", +"74:orders_model_5.sourced": "6786f18f6ff42aa577c99d86", +"75:orders_model_8.has_model": "fcbcf165908dd18a9e49f7ff", +"76:orders_model_8.has_star": "fcbcf165908dd18a9e49f7ff", +"77:orders_model_8.edge_count": "5feceb66ffc86f38d952786c", +"78:orders_model_8.targeting": "6786f18f6ff42aa577c99d86", +"79:orders_model_8.sourced": "6786f18f6ff42aa577c99d86", +"7:orders_model_12.edge_count": "5feceb66ffc86f38d952786c", +"80:models": "42d3866a260676aa81413170", +"81:edges": "d40d2911f4142b96d5bebfc1", +"8:orders_model_12.targeting": "6786f18f6ff42aa577c99d86", +"9:orders_model_12.sourced": "6786f18f6ff42aa577c99d86" +} +], +[ +"lineage", +{ +"0:orders_model_0.has_model": "b5bea41b6c623f7c09f1bf24", +"10:orders_model_15.has_model": "b5bea41b6c623f7c09f1bf24", +"11:orders_model_15.has_star": "fcbcf165908dd18a9e49f7ff", +"12:orders_model_15.edge_count": "4e07408562bedb8b60ce05c1", +"13:orders_model_15.targeting": "c64df03c7fbbe86c07c4c602", +"14:orders_model_15.sourced": "6786f18f6ff42aa577c99d86", +"15:orders_model_3.has_model": "b5bea41b6c623f7c09f1bf24", +"16:orders_model_3.has_star": "fcbcf165908dd18a9e49f7ff", +"17:orders_model_3.edge_count": "d4735e3a265e16eee03f5971", +"18:orders_model_3.targeting": "c6aabcf090220f68834084fb", +"19:orders_model_3.sourced": "6786f18f6ff42aa577c99d86", +"1:orders_model_0.has_star": "b5bea41b6c623f7c09f1bf24", +"20:orders_model_6.has_model": "b5bea41b6c623f7c09f1bf24", +"21:orders_model_6.has_star": "fcbcf165908dd18a9e49f7ff", +"22:orders_model_6.edge_count": "4e07408562bedb8b60ce05c1", +"23:orders_model_6.targeting": "cf6090675ae627461ef89e59", +"24:orders_model_6.sourced": "6786f18f6ff42aa577c99d86", +"25:orders_model_9.has_model": "b5bea41b6c623f7c09f1bf24", +"26:orders_model_9.has_star": "b5bea41b6c623f7c09f1bf24", +"27:orders_model_9.edge_count": "d4735e3a265e16eee03f5971", +"28:orders_model_9.targeting": "ba0aa56821a51ebc64bd22bd", +"29:orders_model_9.sourced": "1b17f70a4e68bc83fc11a319", +"2:orders_model_0.edge_count": "d4735e3a265e16eee03f5971", +"30:orders_model_1.has_model": "b5bea41b6c623f7c09f1bf24", +"31:orders_model_1.has_star": "b5bea41b6c623f7c09f1bf24", +"32:orders_model_1.edge_count": "ef2d127de37b942baad06145", +"33:orders_model_1.targeting": "a1542a5c221b33c2756c09ec", +"34:orders_model_1.sourced": "ebabe32d36bc3dcf101f953f", +"35:orders_model_10.has_model": "b5bea41b6c623f7c09f1bf24", +"36:orders_model_10.has_star": "b5bea41b6c623f7c09f1bf24", +"37:orders_model_10.edge_count": "d4735e3a265e16eee03f5971", +"38:orders_model_10.targeting": "1b17f70a4e68bc83fc11a319", +"39:orders_model_10.sourced": "6786f18f6ff42aa577c99d86", +"3:orders_model_0.targeting": "24786d0b1ed2268bbe02c10e", +"40:orders_model_13.has_model": "b5bea41b6c623f7c09f1bf24", +"41:orders_model_13.has_star": "b5bea41b6c623f7c09f1bf24", +"42:orders_model_13.edge_count": "d4735e3a265e16eee03f5971", +"43:orders_model_13.targeting": "fb2bd7475476ed8980a4ac2c", +"44:orders_model_13.sourced": "6786f18f6ff42aa577c99d86", +"45:orders_model_4.has_model": "b5bea41b6c623f7c09f1bf24", +"46:orders_model_4.has_star": "b5bea41b6c623f7c09f1bf24", +"47:orders_model_4.edge_count": "d4735e3a265e16eee03f5971", +"48:orders_model_4.targeting": "f50bdb75eee2988eed8ac15d", +"49:orders_model_4.sourced": "3c447bb413c543ef9ff9f02b", +"4:orders_model_0.sourced": "2dcc5c2c565c905a98b1f3e0", +"50:orders_model_7.has_model": "b5bea41b6c623f7c09f1bf24", +"51:orders_model_7.has_star": "fcbcf165908dd18a9e49f7ff", +"52:orders_model_7.edge_count": "19581e27de7ced00ff1ce50b", +"53:orders_model_7.targeting": "723ca453518b102baf754807", +"54:orders_model_7.sourced": "efe9b5370341db1214ac6791", +"55:orders_model_11.has_model": "b5bea41b6c623f7c09f1bf24", +"56:orders_model_11.has_star": "fcbcf165908dd18a9e49f7ff", +"57:orders_model_11.edge_count": "6b86b273ff34fce19d6b804e", +"58:orders_model_11.targeting": "8e0e0c410e143c02cde2f39d", +"59:orders_model_11.sourced": "994b51789f15903e6e3ff4f7", +"5:orders_model_12.has_model": "b5bea41b6c623f7c09f1bf24", +"60:orders_model_14.has_model": "b5bea41b6c623f7c09f1bf24", +"61:orders_model_14.has_star": "fcbcf165908dd18a9e49f7ff", +"62:orders_model_14.edge_count": "d4735e3a265e16eee03f5971", +"63:orders_model_14.targeting": "994b51789f15903e6e3ff4f7", +"64:orders_model_14.sourced": "6786f18f6ff42aa577c99d86", +"65:orders_model_2.has_model": "b5bea41b6c623f7c09f1bf24", +"66:orders_model_2.has_star": "fcbcf165908dd18a9e49f7ff", +"67:orders_model_2.edge_count": "6b86b273ff34fce19d6b804e", +"68:orders_model_2.targeting": "a1cfbb075e39a1f31cf0a389", +"69:orders_model_2.sourced": "dbcb0d17df16270e8948b6a7", +"6:orders_model_12.has_star": "fcbcf165908dd18a9e49f7ff", +"70:orders_model_5.has_model": "b5bea41b6c623f7c09f1bf24", +"71:orders_model_5.has_star": "fcbcf165908dd18a9e49f7ff", +"72:orders_model_5.edge_count": "d4735e3a265e16eee03f5971", +"73:orders_model_5.targeting": "39f9d2b502e4a51f5da00952", +"74:orders_model_5.sourced": "6786f18f6ff42aa577c99d86", +"75:orders_model_8.has_model": "b5bea41b6c623f7c09f1bf24", +"76:orders_model_8.has_star": "b5bea41b6c623f7c09f1bf24", +"77:orders_model_8.edge_count": "4b227777d4dd1fc61c6f884f", +"78:orders_model_8.targeting": "efe9b5370341db1214ac6791", +"79:orders_model_8.sourced": "6786f18f6ff42aa577c99d86", +"7:orders_model_12.edge_count": "d4735e3a265e16eee03f5971", +"80:models": "766e6cff4a7c97985d321915", +"81:edges": "66def530d7ac79c6a553f347", +"8:orders_model_12.targeting": "d7d16e7a663f8aecabea3ed6", +"9:orders_model_12.sourced": "6786f18f6ff42aa577c99d86" +} +], +[ +"lineage", +{ +"0:orders_model_0.has_model": "fcbcf165908dd18a9e49f7ff", +"10:orders_model_15.has_model": "fcbcf165908dd18a9e49f7ff", +"11:orders_model_15.has_star": "fcbcf165908dd18a9e49f7ff", +"12:orders_model_15.edge_count": "5feceb66ffc86f38d952786c", +"13:orders_model_15.targeting": "6786f18f6ff42aa577c99d86", +"14:orders_model_15.sourced": "6786f18f6ff42aa577c99d86", +"15:orders_model_3.has_model": "fcbcf165908dd18a9e49f7ff", +"16:orders_model_3.has_star": "fcbcf165908dd18a9e49f7ff", +"17:orders_model_3.edge_count": "5feceb66ffc86f38d952786c", +"18:orders_model_3.targeting": "6786f18f6ff42aa577c99d86", +"19:orders_model_3.sourced": "6786f18f6ff42aa577c99d86", +"1:orders_model_0.has_star": "fcbcf165908dd18a9e49f7ff", +"20:orders_model_6.has_model": "fcbcf165908dd18a9e49f7ff", +"21:orders_model_6.has_star": "fcbcf165908dd18a9e49f7ff", +"22:orders_model_6.edge_count": "5feceb66ffc86f38d952786c", +"23:orders_model_6.targeting": "6786f18f6ff42aa577c99d86", +"24:orders_model_6.sourced": "6786f18f6ff42aa577c99d86", +"25:orders_model_9.has_model": "b5bea41b6c623f7c09f1bf24", +"26:orders_model_9.has_star": "b5bea41b6c623f7c09f1bf24", +"27:orders_model_9.edge_count": "d4735e3a265e16eee03f5971", +"28:orders_model_9.targeting": "ba0aa56821a51ebc64bd22bd", +"29:orders_model_9.sourced": "1b17f70a4e68bc83fc11a319", +"2:orders_model_0.edge_count": "5feceb66ffc86f38d952786c", +"30:orders_model_1.has_model": "b5bea41b6c623f7c09f1bf24", +"31:orders_model_1.has_star": "b5bea41b6c623f7c09f1bf24", +"32:orders_model_1.edge_count": "ef2d127de37b942baad06145", +"33:orders_model_1.targeting": "a1542a5c221b33c2756c09ec", +"34:orders_model_1.sourced": "ebabe32d36bc3dcf101f953f", +"35:orders_model_10.has_model": "b5bea41b6c623f7c09f1bf24", +"36:orders_model_10.has_star": "b5bea41b6c623f7c09f1bf24", +"37:orders_model_10.edge_count": "d4735e3a265e16eee03f5971", +"38:orders_model_10.targeting": "1b17f70a4e68bc83fc11a319", +"39:orders_model_10.sourced": "6786f18f6ff42aa577c99d86", +"3:orders_model_0.targeting": "6786f18f6ff42aa577c99d86", +"40:orders_model_13.has_model": "fcbcf165908dd18a9e49f7ff", +"41:orders_model_13.has_star": "fcbcf165908dd18a9e49f7ff", +"42:orders_model_13.edge_count": "5feceb66ffc86f38d952786c", +"43:orders_model_13.targeting": "6786f18f6ff42aa577c99d86", +"44:orders_model_13.sourced": "6786f18f6ff42aa577c99d86", +"45:orders_model_4.has_model": "b5bea41b6c623f7c09f1bf24", +"46:orders_model_4.has_star": "b5bea41b6c623f7c09f1bf24", +"47:orders_model_4.edge_count": "d4735e3a265e16eee03f5971", +"48:orders_model_4.targeting": "f50bdb75eee2988eed8ac15d", +"49:orders_model_4.sourced": "39f9d2b502e4a51f5da00952", +"4:orders_model_0.sourced": "c67fcc4d7a42429aab9315c9", +"50:orders_model_7.has_model": "fcbcf165908dd18a9e49f7ff", +"51:orders_model_7.has_star": "fcbcf165908dd18a9e49f7ff", +"52:orders_model_7.edge_count": "5feceb66ffc86f38d952786c", +"53:orders_model_7.targeting": "6786f18f6ff42aa577c99d86", +"54:orders_model_7.sourced": "efe9b5370341db1214ac6791", +"55:orders_model_11.has_model": "fcbcf165908dd18a9e49f7ff", +"56:orders_model_11.has_star": "fcbcf165908dd18a9e49f7ff", +"57:orders_model_11.edge_count": "5feceb66ffc86f38d952786c", +"58:orders_model_11.targeting": "6786f18f6ff42aa577c99d86", +"59:orders_model_11.sourced": "994b51789f15903e6e3ff4f7", +"5:orders_model_12.has_model": "b5bea41b6c623f7c09f1bf24", +"60:orders_model_14.has_model": "b5bea41b6c623f7c09f1bf24", +"61:orders_model_14.has_star": "fcbcf165908dd18a9e49f7ff", +"62:orders_model_14.edge_count": "d4735e3a265e16eee03f5971", +"63:orders_model_14.targeting": "994b51789f15903e6e3ff4f7", +"64:orders_model_14.sourced": "6786f18f6ff42aa577c99d86", +"65:orders_model_2.has_model": "fcbcf165908dd18a9e49f7ff", +"66:orders_model_2.has_star": "fcbcf165908dd18a9e49f7ff", +"67:orders_model_2.edge_count": "5feceb66ffc86f38d952786c", +"68:orders_model_2.targeting": "6786f18f6ff42aa577c99d86", +"69:orders_model_2.sourced": "6786f18f6ff42aa577c99d86", +"6:orders_model_12.has_star": "fcbcf165908dd18a9e49f7ff", +"70:orders_model_5.has_model": "b5bea41b6c623f7c09f1bf24", +"71:orders_model_5.has_star": "fcbcf165908dd18a9e49f7ff", +"72:orders_model_5.edge_count": "d4735e3a265e16eee03f5971", +"73:orders_model_5.targeting": "39f9d2b502e4a51f5da00952", +"74:orders_model_5.sourced": "6786f18f6ff42aa577c99d86", +"75:orders_model_8.has_model": "b5bea41b6c623f7c09f1bf24", +"76:orders_model_8.has_star": "b5bea41b6c623f7c09f1bf24", +"77:orders_model_8.edge_count": "4b227777d4dd1fc61c6f884f", +"78:orders_model_8.targeting": "efe9b5370341db1214ac6791", +"79:orders_model_8.sourced": "6786f18f6ff42aa577c99d86", +"7:orders_model_12.edge_count": "d4735e3a265e16eee03f5971", +"80:models": "e3f9826cd489c85cd139787f", +"81:edges": "ff90a6fe0029bd81150fd61c", +"8:orders_model_12.targeting": "d7d16e7a663f8aecabea3ed6", +"9:orders_model_12.sourced": "6786f18f6ff42aa577c99d86" +} +], +[ +"lineage", +{ +"0:orders_model_0.has_model": "b5bea41b6c623f7c09f1bf24", +"10:orders_model_15.has_model": "b5bea41b6c623f7c09f1bf24", +"11:orders_model_15.has_star": "fcbcf165908dd18a9e49f7ff", +"12:orders_model_15.edge_count": "4e07408562bedb8b60ce05c1", +"13:orders_model_15.targeting": "c64df03c7fbbe86c07c4c602", +"14:orders_model_15.sourced": "6786f18f6ff42aa577c99d86", +"15:orders_model_3.has_model": "b5bea41b6c623f7c09f1bf24", +"16:orders_model_3.has_star": "fcbcf165908dd18a9e49f7ff", +"17:orders_model_3.edge_count": "d4735e3a265e16eee03f5971", +"18:orders_model_3.targeting": "c6aabcf090220f68834084fb", +"19:orders_model_3.sourced": "6786f18f6ff42aa577c99d86", +"1:orders_model_0.has_star": "b5bea41b6c623f7c09f1bf24", +"20:orders_model_6.has_model": "b5bea41b6c623f7c09f1bf24", +"21:orders_model_6.has_star": "fcbcf165908dd18a9e49f7ff", +"22:orders_model_6.edge_count": "4e07408562bedb8b60ce05c1", +"23:orders_model_6.targeting": "cf6090675ae627461ef89e59", +"24:orders_model_6.sourced": "6786f18f6ff42aa577c99d86", +"25:orders_model_9.has_model": "b5bea41b6c623f7c09f1bf24", +"26:orders_model_9.has_star": "b5bea41b6c623f7c09f1bf24", +"27:orders_model_9.edge_count": "d4735e3a265e16eee03f5971", +"28:orders_model_9.targeting": "ba0aa56821a51ebc64bd22bd", +"29:orders_model_9.sourced": "1b17f70a4e68bc83fc11a319", +"2:orders_model_0.edge_count": "d4735e3a265e16eee03f5971", +"30:orders_model_1.has_model": "b5bea41b6c623f7c09f1bf24", +"31:orders_model_1.has_star": "b5bea41b6c623f7c09f1bf24", +"32:orders_model_1.edge_count": "ef2d127de37b942baad06145", +"33:orders_model_1.targeting": "a1542a5c221b33c2756c09ec", +"34:orders_model_1.sourced": "ebabe32d36bc3dcf101f953f", +"35:orders_model_10.has_model": "b5bea41b6c623f7c09f1bf24", +"36:orders_model_10.has_star": "b5bea41b6c623f7c09f1bf24", +"37:orders_model_10.edge_count": "d4735e3a265e16eee03f5971", +"38:orders_model_10.targeting": "1b17f70a4e68bc83fc11a319", +"39:orders_model_10.sourced": "6786f18f6ff42aa577c99d86", +"3:orders_model_0.targeting": "24786d0b1ed2268bbe02c10e", +"40:orders_model_13.has_model": "b5bea41b6c623f7c09f1bf24", +"41:orders_model_13.has_star": "b5bea41b6c623f7c09f1bf24", +"42:orders_model_13.edge_count": "d4735e3a265e16eee03f5971", +"43:orders_model_13.targeting": "fb2bd7475476ed8980a4ac2c", +"44:orders_model_13.sourced": "6786f18f6ff42aa577c99d86", +"45:orders_model_4.has_model": "b5bea41b6c623f7c09f1bf24", +"46:orders_model_4.has_star": "b5bea41b6c623f7c09f1bf24", +"47:orders_model_4.edge_count": "d4735e3a265e16eee03f5971", +"48:orders_model_4.targeting": "f50bdb75eee2988eed8ac15d", +"49:orders_model_4.sourced": "3c447bb413c543ef9ff9f02b", +"4:orders_model_0.sourced": "2dcc5c2c565c905a98b1f3e0", +"50:orders_model_7.has_model": "b5bea41b6c623f7c09f1bf24", +"51:orders_model_7.has_star": "fcbcf165908dd18a9e49f7ff", +"52:orders_model_7.edge_count": "19581e27de7ced00ff1ce50b", +"53:orders_model_7.targeting": "723ca453518b102baf754807", +"54:orders_model_7.sourced": "efe9b5370341db1214ac6791", +"55:orders_model_11.has_model": "b5bea41b6c623f7c09f1bf24", +"56:orders_model_11.has_star": "fcbcf165908dd18a9e49f7ff", +"57:orders_model_11.edge_count": "6b86b273ff34fce19d6b804e", +"58:orders_model_11.targeting": "8e0e0c410e143c02cde2f39d", +"59:orders_model_11.sourced": "994b51789f15903e6e3ff4f7", +"5:orders_model_12.has_model": "b5bea41b6c623f7c09f1bf24", +"60:orders_model_14.has_model": "b5bea41b6c623f7c09f1bf24", +"61:orders_model_14.has_star": "fcbcf165908dd18a9e49f7ff", +"62:orders_model_14.edge_count": "d4735e3a265e16eee03f5971", +"63:orders_model_14.targeting": "994b51789f15903e6e3ff4f7", +"64:orders_model_14.sourced": "6786f18f6ff42aa577c99d86", +"65:orders_model_2.has_model": "b5bea41b6c623f7c09f1bf24", +"66:orders_model_2.has_star": "fcbcf165908dd18a9e49f7ff", +"67:orders_model_2.edge_count": "6b86b273ff34fce19d6b804e", +"68:orders_model_2.targeting": "a1cfbb075e39a1f31cf0a389", +"69:orders_model_2.sourced": "dbcb0d17df16270e8948b6a7", +"6:orders_model_12.has_star": "fcbcf165908dd18a9e49f7ff", +"70:orders_model_5.has_model": "b5bea41b6c623f7c09f1bf24", +"71:orders_model_5.has_star": "fcbcf165908dd18a9e49f7ff", +"72:orders_model_5.edge_count": "d4735e3a265e16eee03f5971", +"73:orders_model_5.targeting": "39f9d2b502e4a51f5da00952", +"74:orders_model_5.sourced": "6786f18f6ff42aa577c99d86", +"75:orders_model_8.has_model": "b5bea41b6c623f7c09f1bf24", +"76:orders_model_8.has_star": "b5bea41b6c623f7c09f1bf24", +"77:orders_model_8.edge_count": "4b227777d4dd1fc61c6f884f", +"78:orders_model_8.targeting": "efe9b5370341db1214ac6791", +"79:orders_model_8.sourced": "6786f18f6ff42aa577c99d86", +"7:orders_model_12.edge_count": "d4735e3a265e16eee03f5971", +"80:models": "766e6cff4a7c97985d321915", +"81:edges": "66def530d7ac79c6a553f347", +"8:orders_model_12.targeting": "d7d16e7a663f8aecabea3ed6", +"9:orders_model_12.sourced": "6786f18f6ff42aa577c99d86" +} +], +[ +"lineage", +{ +"0:orders_model_0.has_model": "fcbcf165908dd18a9e49f7ff", +"10:orders_model_15.has_model": "fcbcf165908dd18a9e49f7ff", +"11:orders_model_15.has_star": "fcbcf165908dd18a9e49f7ff", +"12:orders_model_15.edge_count": "5feceb66ffc86f38d952786c", +"13:orders_model_15.targeting": "6786f18f6ff42aa577c99d86", +"14:orders_model_15.sourced": "6786f18f6ff42aa577c99d86", +"15:orders_model_3.has_model": "fcbcf165908dd18a9e49f7ff", +"16:orders_model_3.has_star": "fcbcf165908dd18a9e49f7ff", +"17:orders_model_3.edge_count": "5feceb66ffc86f38d952786c", +"18:orders_model_3.targeting": "6786f18f6ff42aa577c99d86", +"19:orders_model_3.sourced": "6786f18f6ff42aa577c99d86", +"1:orders_model_0.has_star": "fcbcf165908dd18a9e49f7ff", +"20:orders_model_6.has_model": "fcbcf165908dd18a9e49f7ff", +"21:orders_model_6.has_star": "fcbcf165908dd18a9e49f7ff", +"22:orders_model_6.edge_count": "5feceb66ffc86f38d952786c", +"23:orders_model_6.targeting": "6786f18f6ff42aa577c99d86", +"24:orders_model_6.sourced": "6786f18f6ff42aa577c99d86", +"25:orders_model_9.has_model": "b5bea41b6c623f7c09f1bf24", +"26:orders_model_9.has_star": "b5bea41b6c623f7c09f1bf24", +"27:orders_model_9.edge_count": "d4735e3a265e16eee03f5971", +"28:orders_model_9.targeting": "ba0aa56821a51ebc64bd22bd", +"29:orders_model_9.sourced": "1b17f70a4e68bc83fc11a319", +"2:orders_model_0.edge_count": "5feceb66ffc86f38d952786c", +"30:orders_model_1.has_model": "b5bea41b6c623f7c09f1bf24", +"31:orders_model_1.has_star": "b5bea41b6c623f7c09f1bf24", +"32:orders_model_1.edge_count": "ef2d127de37b942baad06145", +"33:orders_model_1.targeting": "a1542a5c221b33c2756c09ec", +"34:orders_model_1.sourced": "ebabe32d36bc3dcf101f953f", +"35:orders_model_10.has_model": "b5bea41b6c623f7c09f1bf24", +"36:orders_model_10.has_star": "b5bea41b6c623f7c09f1bf24", +"37:orders_model_10.edge_count": "d4735e3a265e16eee03f5971", +"38:orders_model_10.targeting": "1b17f70a4e68bc83fc11a319", +"39:orders_model_10.sourced": "6786f18f6ff42aa577c99d86", +"3:orders_model_0.targeting": "6786f18f6ff42aa577c99d86", +"40:orders_model_13.has_model": "fcbcf165908dd18a9e49f7ff", +"41:orders_model_13.has_star": "fcbcf165908dd18a9e49f7ff", +"42:orders_model_13.edge_count": "5feceb66ffc86f38d952786c", +"43:orders_model_13.targeting": "6786f18f6ff42aa577c99d86", +"44:orders_model_13.sourced": "6786f18f6ff42aa577c99d86", +"45:orders_model_4.has_model": "b5bea41b6c623f7c09f1bf24", +"46:orders_model_4.has_star": "b5bea41b6c623f7c09f1bf24", +"47:orders_model_4.edge_count": "d4735e3a265e16eee03f5971", +"48:orders_model_4.targeting": "f50bdb75eee2988eed8ac15d", +"49:orders_model_4.sourced": "39f9d2b502e4a51f5da00952", +"4:orders_model_0.sourced": "c67fcc4d7a42429aab9315c9", +"50:orders_model_7.has_model": "fcbcf165908dd18a9e49f7ff", +"51:orders_model_7.has_star": "fcbcf165908dd18a9e49f7ff", +"52:orders_model_7.edge_count": "5feceb66ffc86f38d952786c", +"53:orders_model_7.targeting": "6786f18f6ff42aa577c99d86", +"54:orders_model_7.sourced": "efe9b5370341db1214ac6791", +"55:orders_model_11.has_model": "fcbcf165908dd18a9e49f7ff", +"56:orders_model_11.has_star": "fcbcf165908dd18a9e49f7ff", +"57:orders_model_11.edge_count": "5feceb66ffc86f38d952786c", +"58:orders_model_11.targeting": "6786f18f6ff42aa577c99d86", +"59:orders_model_11.sourced": "994b51789f15903e6e3ff4f7", +"5:orders_model_12.has_model": "b5bea41b6c623f7c09f1bf24", +"60:orders_model_14.has_model": "b5bea41b6c623f7c09f1bf24", +"61:orders_model_14.has_star": "fcbcf165908dd18a9e49f7ff", +"62:orders_model_14.edge_count": "d4735e3a265e16eee03f5971", +"63:orders_model_14.targeting": "994b51789f15903e6e3ff4f7", +"64:orders_model_14.sourced": "6786f18f6ff42aa577c99d86", +"65:orders_model_2.has_model": "fcbcf165908dd18a9e49f7ff", +"66:orders_model_2.has_star": "fcbcf165908dd18a9e49f7ff", +"67:orders_model_2.edge_count": "5feceb66ffc86f38d952786c", +"68:orders_model_2.targeting": "6786f18f6ff42aa577c99d86", +"69:orders_model_2.sourced": "6786f18f6ff42aa577c99d86", +"6:orders_model_12.has_star": "fcbcf165908dd18a9e49f7ff", +"70:orders_model_5.has_model": "b5bea41b6c623f7c09f1bf24", +"71:orders_model_5.has_star": "fcbcf165908dd18a9e49f7ff", +"72:orders_model_5.edge_count": "d4735e3a265e16eee03f5971", +"73:orders_model_5.targeting": "39f9d2b502e4a51f5da00952", +"74:orders_model_5.sourced": "6786f18f6ff42aa577c99d86", +"75:orders_model_8.has_model": "b5bea41b6c623f7c09f1bf24", +"76:orders_model_8.has_star": "b5bea41b6c623f7c09f1bf24", +"77:orders_model_8.edge_count": "4b227777d4dd1fc61c6f884f", +"78:orders_model_8.targeting": "efe9b5370341db1214ac6791", +"79:orders_model_8.sourced": "6786f18f6ff42aa577c99d86", +"7:orders_model_12.edge_count": "d4735e3a265e16eee03f5971", +"80:models": "e3f9826cd489c85cd139787f", +"81:edges": "ff90a6fe0029bd81150fd61c", +"8:orders_model_12.targeting": "d7d16e7a663f8aecabea3ed6", +"9:orders_model_12.sourced": "6786f18f6ff42aa577c99d86" +} +], +[ +"lineage", +{ +"0:orders_model_0.has_model": "b5bea41b6c623f7c09f1bf24", +"10:orders_model_15.has_model": "b5bea41b6c623f7c09f1bf24", +"11:orders_model_15.has_star": "fcbcf165908dd18a9e49f7ff", +"12:orders_model_15.edge_count": "4e07408562bedb8b60ce05c1", +"13:orders_model_15.targeting": "c64df03c7fbbe86c07c4c602", +"14:orders_model_15.sourced": "6786f18f6ff42aa577c99d86", +"15:orders_model_3.has_model": "b5bea41b6c623f7c09f1bf24", +"16:orders_model_3.has_star": "fcbcf165908dd18a9e49f7ff", +"17:orders_model_3.edge_count": "d4735e3a265e16eee03f5971", +"18:orders_model_3.targeting": "c6aabcf090220f68834084fb", +"19:orders_model_3.sourced": "6786f18f6ff42aa577c99d86", +"1:orders_model_0.has_star": "b5bea41b6c623f7c09f1bf24", +"20:orders_model_6.has_model": "b5bea41b6c623f7c09f1bf24", +"21:orders_model_6.has_star": "fcbcf165908dd18a9e49f7ff", +"22:orders_model_6.edge_count": "4e07408562bedb8b60ce05c1", +"23:orders_model_6.targeting": "cf6090675ae627461ef89e59", +"24:orders_model_6.sourced": "6786f18f6ff42aa577c99d86", +"25:orders_model_9.has_model": "b5bea41b6c623f7c09f1bf24", +"26:orders_model_9.has_star": "b5bea41b6c623f7c09f1bf24", +"27:orders_model_9.edge_count": "d4735e3a265e16eee03f5971", +"28:orders_model_9.targeting": "ba0aa56821a51ebc64bd22bd", +"29:orders_model_9.sourced": "1b17f70a4e68bc83fc11a319", +"2:orders_model_0.edge_count": "d4735e3a265e16eee03f5971", +"30:orders_model_1.has_model": "b5bea41b6c623f7c09f1bf24", +"31:orders_model_1.has_star": "b5bea41b6c623f7c09f1bf24", +"32:orders_model_1.edge_count": "ef2d127de37b942baad06145", +"33:orders_model_1.targeting": "a1542a5c221b33c2756c09ec", +"34:orders_model_1.sourced": "ebabe32d36bc3dcf101f953f", +"35:orders_model_10.has_model": "b5bea41b6c623f7c09f1bf24", +"36:orders_model_10.has_star": "b5bea41b6c623f7c09f1bf24", +"37:orders_model_10.edge_count": "d4735e3a265e16eee03f5971", +"38:orders_model_10.targeting": "1b17f70a4e68bc83fc11a319", +"39:orders_model_10.sourced": "6786f18f6ff42aa577c99d86", +"3:orders_model_0.targeting": "24786d0b1ed2268bbe02c10e", +"40:orders_model_13.has_model": "b5bea41b6c623f7c09f1bf24", +"41:orders_model_13.has_star": "b5bea41b6c623f7c09f1bf24", +"42:orders_model_13.edge_count": "d4735e3a265e16eee03f5971", +"43:orders_model_13.targeting": "fb2bd7475476ed8980a4ac2c", +"44:orders_model_13.sourced": "6786f18f6ff42aa577c99d86", +"45:orders_model_4.has_model": "b5bea41b6c623f7c09f1bf24", +"46:orders_model_4.has_star": "b5bea41b6c623f7c09f1bf24", +"47:orders_model_4.edge_count": "d4735e3a265e16eee03f5971", +"48:orders_model_4.targeting": "f50bdb75eee2988eed8ac15d", +"49:orders_model_4.sourced": "3c447bb413c543ef9ff9f02b", +"4:orders_model_0.sourced": "2dcc5c2c565c905a98b1f3e0", +"50:orders_model_7.has_model": "b5bea41b6c623f7c09f1bf24", +"51:orders_model_7.has_star": "fcbcf165908dd18a9e49f7ff", +"52:orders_model_7.edge_count": "19581e27de7ced00ff1ce50b", +"53:orders_model_7.targeting": "723ca453518b102baf754807", +"54:orders_model_7.sourced": "efe9b5370341db1214ac6791", +"55:orders_model_11.has_model": "b5bea41b6c623f7c09f1bf24", +"56:orders_model_11.has_star": "fcbcf165908dd18a9e49f7ff", +"57:orders_model_11.edge_count": "6b86b273ff34fce19d6b804e", +"58:orders_model_11.targeting": "8e0e0c410e143c02cde2f39d", +"59:orders_model_11.sourced": "994b51789f15903e6e3ff4f7", +"5:orders_model_12.has_model": "b5bea41b6c623f7c09f1bf24", +"60:orders_model_14.has_model": "b5bea41b6c623f7c09f1bf24", +"61:orders_model_14.has_star": "fcbcf165908dd18a9e49f7ff", +"62:orders_model_14.edge_count": "d4735e3a265e16eee03f5971", +"63:orders_model_14.targeting": "994b51789f15903e6e3ff4f7", +"64:orders_model_14.sourced": "6786f18f6ff42aa577c99d86", +"65:orders_model_2.has_model": "b5bea41b6c623f7c09f1bf24", +"66:orders_model_2.has_star": "fcbcf165908dd18a9e49f7ff", +"67:orders_model_2.edge_count": "6b86b273ff34fce19d6b804e", +"68:orders_model_2.targeting": "a1cfbb075e39a1f31cf0a389", +"69:orders_model_2.sourced": "dbcb0d17df16270e8948b6a7", +"6:orders_model_12.has_star": "fcbcf165908dd18a9e49f7ff", +"70:orders_model_5.has_model": "b5bea41b6c623f7c09f1bf24", +"71:orders_model_5.has_star": "fcbcf165908dd18a9e49f7ff", +"72:orders_model_5.edge_count": "d4735e3a265e16eee03f5971", +"73:orders_model_5.targeting": "39f9d2b502e4a51f5da00952", +"74:orders_model_5.sourced": "6786f18f6ff42aa577c99d86", +"75:orders_model_8.has_model": "b5bea41b6c623f7c09f1bf24", +"76:orders_model_8.has_star": "b5bea41b6c623f7c09f1bf24", +"77:orders_model_8.edge_count": "4b227777d4dd1fc61c6f884f", +"78:orders_model_8.targeting": "efe9b5370341db1214ac6791", +"79:orders_model_8.sourced": "6786f18f6ff42aa577c99d86", +"7:orders_model_12.edge_count": "d4735e3a265e16eee03f5971", +"80:models": "766e6cff4a7c97985d321915", +"81:edges": "66def530d7ac79c6a553f347", +"8:orders_model_12.targeting": "d7d16e7a663f8aecabea3ed6", +"9:orders_model_12.sourced": "6786f18f6ff42aa577c99d86" +} +], +[ +"lineage", +{ +"0:orders_model_0.has_model": "fcbcf165908dd18a9e49f7ff", +"10:orders_model_15.has_model": "fcbcf165908dd18a9e49f7ff", +"11:orders_model_15.has_star": "fcbcf165908dd18a9e49f7ff", +"12:orders_model_15.edge_count": "5feceb66ffc86f38d952786c", +"13:orders_model_15.targeting": "6786f18f6ff42aa577c99d86", +"14:orders_model_15.sourced": "6786f18f6ff42aa577c99d86", +"15:orders_model_3.has_model": "fcbcf165908dd18a9e49f7ff", +"16:orders_model_3.has_star": "fcbcf165908dd18a9e49f7ff", +"17:orders_model_3.edge_count": "5feceb66ffc86f38d952786c", +"18:orders_model_3.targeting": "6786f18f6ff42aa577c99d86", +"19:orders_model_3.sourced": "6786f18f6ff42aa577c99d86", +"1:orders_model_0.has_star": "fcbcf165908dd18a9e49f7ff", +"20:orders_model_6.has_model": "fcbcf165908dd18a9e49f7ff", +"21:orders_model_6.has_star": "fcbcf165908dd18a9e49f7ff", +"22:orders_model_6.edge_count": "5feceb66ffc86f38d952786c", +"23:orders_model_6.targeting": "6786f18f6ff42aa577c99d86", +"24:orders_model_6.sourced": "6786f18f6ff42aa577c99d86", +"25:orders_model_9.has_model": "b5bea41b6c623f7c09f1bf24", +"26:orders_model_9.has_star": "b5bea41b6c623f7c09f1bf24", +"27:orders_model_9.edge_count": "d4735e3a265e16eee03f5971", +"28:orders_model_9.targeting": "ba0aa56821a51ebc64bd22bd", +"29:orders_model_9.sourced": "1b17f70a4e68bc83fc11a319", +"2:orders_model_0.edge_count": "5feceb66ffc86f38d952786c", +"30:orders_model_1.has_model": "b5bea41b6c623f7c09f1bf24", +"31:orders_model_1.has_star": "b5bea41b6c623f7c09f1bf24", +"32:orders_model_1.edge_count": "ef2d127de37b942baad06145", +"33:orders_model_1.targeting": "a1542a5c221b33c2756c09ec", +"34:orders_model_1.sourced": "ebabe32d36bc3dcf101f953f", +"35:orders_model_10.has_model": "b5bea41b6c623f7c09f1bf24", +"36:orders_model_10.has_star": "b5bea41b6c623f7c09f1bf24", +"37:orders_model_10.edge_count": "d4735e3a265e16eee03f5971", +"38:orders_model_10.targeting": "1b17f70a4e68bc83fc11a319", +"39:orders_model_10.sourced": "6786f18f6ff42aa577c99d86", +"3:orders_model_0.targeting": "6786f18f6ff42aa577c99d86", +"40:orders_model_13.has_model": "fcbcf165908dd18a9e49f7ff", +"41:orders_model_13.has_star": "fcbcf165908dd18a9e49f7ff", +"42:orders_model_13.edge_count": "5feceb66ffc86f38d952786c", +"43:orders_model_13.targeting": "6786f18f6ff42aa577c99d86", +"44:orders_model_13.sourced": "6786f18f6ff42aa577c99d86", +"45:orders_model_4.has_model": "b5bea41b6c623f7c09f1bf24", +"46:orders_model_4.has_star": "b5bea41b6c623f7c09f1bf24", +"47:orders_model_4.edge_count": "d4735e3a265e16eee03f5971", +"48:orders_model_4.targeting": "f50bdb75eee2988eed8ac15d", +"49:orders_model_4.sourced": "39f9d2b502e4a51f5da00952", +"4:orders_model_0.sourced": "c67fcc4d7a42429aab9315c9", +"50:orders_model_7.has_model": "fcbcf165908dd18a9e49f7ff", +"51:orders_model_7.has_star": "fcbcf165908dd18a9e49f7ff", +"52:orders_model_7.edge_count": "5feceb66ffc86f38d952786c", +"53:orders_model_7.targeting": "6786f18f6ff42aa577c99d86", +"54:orders_model_7.sourced": "efe9b5370341db1214ac6791", +"55:orders_model_11.has_model": "fcbcf165908dd18a9e49f7ff", +"56:orders_model_11.has_star": "fcbcf165908dd18a9e49f7ff", +"57:orders_model_11.edge_count": "5feceb66ffc86f38d952786c", +"58:orders_model_11.targeting": "6786f18f6ff42aa577c99d86", +"59:orders_model_11.sourced": "994b51789f15903e6e3ff4f7", +"5:orders_model_12.has_model": "b5bea41b6c623f7c09f1bf24", +"60:orders_model_14.has_model": "b5bea41b6c623f7c09f1bf24", +"61:orders_model_14.has_star": "fcbcf165908dd18a9e49f7ff", +"62:orders_model_14.edge_count": "d4735e3a265e16eee03f5971", +"63:orders_model_14.targeting": "994b51789f15903e6e3ff4f7", +"64:orders_model_14.sourced": "6786f18f6ff42aa577c99d86", +"65:orders_model_2.has_model": "fcbcf165908dd18a9e49f7ff", +"66:orders_model_2.has_star": "fcbcf165908dd18a9e49f7ff", +"67:orders_model_2.edge_count": "5feceb66ffc86f38d952786c", +"68:orders_model_2.targeting": "6786f18f6ff42aa577c99d86", +"69:orders_model_2.sourced": "6786f18f6ff42aa577c99d86", +"6:orders_model_12.has_star": "fcbcf165908dd18a9e49f7ff", +"70:orders_model_5.has_model": "b5bea41b6c623f7c09f1bf24", +"71:orders_model_5.has_star": "fcbcf165908dd18a9e49f7ff", +"72:orders_model_5.edge_count": "d4735e3a265e16eee03f5971", +"73:orders_model_5.targeting": "39f9d2b502e4a51f5da00952", +"74:orders_model_5.sourced": "6786f18f6ff42aa577c99d86", +"75:orders_model_8.has_model": "b5bea41b6c623f7c09f1bf24", +"76:orders_model_8.has_star": "b5bea41b6c623f7c09f1bf24", +"77:orders_model_8.edge_count": "4b227777d4dd1fc61c6f884f", +"78:orders_model_8.targeting": "efe9b5370341db1214ac6791", +"79:orders_model_8.sourced": "6786f18f6ff42aa577c99d86", +"7:orders_model_12.edge_count": "d4735e3a265e16eee03f5971", +"80:models": "e3f9826cd489c85cd139787f", +"81:edges": "ff90a6fe0029bd81150fd61c", +"8:orders_model_12.targeting": "d7d16e7a663f8aecabea3ed6", +"9:orders_model_12.sourced": "6786f18f6ff42aa577c99d86" +} +], +[ +"lineage", +{ +"0:orders_model_0.has_model": "b5bea41b6c623f7c09f1bf24", +"10:orders_model_15.has_model": "b5bea41b6c623f7c09f1bf24", +"11:orders_model_15.has_star": "fcbcf165908dd18a9e49f7ff", +"12:orders_model_15.edge_count": "4e07408562bedb8b60ce05c1", +"13:orders_model_15.targeting": "c64df03c7fbbe86c07c4c602", +"14:orders_model_15.sourced": "6786f18f6ff42aa577c99d86", +"15:orders_model_3.has_model": "b5bea41b6c623f7c09f1bf24", +"16:orders_model_3.has_star": "fcbcf165908dd18a9e49f7ff", +"17:orders_model_3.edge_count": "d4735e3a265e16eee03f5971", +"18:orders_model_3.targeting": "c6aabcf090220f68834084fb", +"19:orders_model_3.sourced": "6786f18f6ff42aa577c99d86", +"1:orders_model_0.has_star": "b5bea41b6c623f7c09f1bf24", +"20:orders_model_6.has_model": "b5bea41b6c623f7c09f1bf24", +"21:orders_model_6.has_star": "fcbcf165908dd18a9e49f7ff", +"22:orders_model_6.edge_count": "4e07408562bedb8b60ce05c1", +"23:orders_model_6.targeting": "cf6090675ae627461ef89e59", +"24:orders_model_6.sourced": "6786f18f6ff42aa577c99d86", +"25:orders_model_9.has_model": "b5bea41b6c623f7c09f1bf24", +"26:orders_model_9.has_star": "b5bea41b6c623f7c09f1bf24", +"27:orders_model_9.edge_count": "d4735e3a265e16eee03f5971", +"28:orders_model_9.targeting": "ba0aa56821a51ebc64bd22bd", +"29:orders_model_9.sourced": "1b17f70a4e68bc83fc11a319", +"2:orders_model_0.edge_count": "d4735e3a265e16eee03f5971", +"30:orders_model_1.has_model": "b5bea41b6c623f7c09f1bf24", +"31:orders_model_1.has_star": "b5bea41b6c623f7c09f1bf24", +"32:orders_model_1.edge_count": "ef2d127de37b942baad06145", +"33:orders_model_1.targeting": "a1542a5c221b33c2756c09ec", +"34:orders_model_1.sourced": "ebabe32d36bc3dcf101f953f", +"35:orders_model_10.has_model": "b5bea41b6c623f7c09f1bf24", +"36:orders_model_10.has_star": "b5bea41b6c623f7c09f1bf24", +"37:orders_model_10.edge_count": "d4735e3a265e16eee03f5971", +"38:orders_model_10.targeting": "1b17f70a4e68bc83fc11a319", +"39:orders_model_10.sourced": "6786f18f6ff42aa577c99d86", +"3:orders_model_0.targeting": "24786d0b1ed2268bbe02c10e", +"40:orders_model_13.has_model": "b5bea41b6c623f7c09f1bf24", +"41:orders_model_13.has_star": "b5bea41b6c623f7c09f1bf24", +"42:orders_model_13.edge_count": "d4735e3a265e16eee03f5971", +"43:orders_model_13.targeting": "fb2bd7475476ed8980a4ac2c", +"44:orders_model_13.sourced": "6786f18f6ff42aa577c99d86", +"45:orders_model_4.has_model": "b5bea41b6c623f7c09f1bf24", +"46:orders_model_4.has_star": "b5bea41b6c623f7c09f1bf24", +"47:orders_model_4.edge_count": "d4735e3a265e16eee03f5971", +"48:orders_model_4.targeting": "f50bdb75eee2988eed8ac15d", +"49:orders_model_4.sourced": "3c447bb413c543ef9ff9f02b", +"4:orders_model_0.sourced": "2dcc5c2c565c905a98b1f3e0", +"50:orders_model_7.has_model": "b5bea41b6c623f7c09f1bf24", +"51:orders_model_7.has_star": "fcbcf165908dd18a9e49f7ff", +"52:orders_model_7.edge_count": "19581e27de7ced00ff1ce50b", +"53:orders_model_7.targeting": "723ca453518b102baf754807", +"54:orders_model_7.sourced": "efe9b5370341db1214ac6791", +"55:orders_model_11.has_model": "b5bea41b6c623f7c09f1bf24", +"56:orders_model_11.has_star": "fcbcf165908dd18a9e49f7ff", +"57:orders_model_11.edge_count": "6b86b273ff34fce19d6b804e", +"58:orders_model_11.targeting": "8e0e0c410e143c02cde2f39d", +"59:orders_model_11.sourced": "994b51789f15903e6e3ff4f7", +"5:orders_model_12.has_model": "b5bea41b6c623f7c09f1bf24", +"60:orders_model_14.has_model": "b5bea41b6c623f7c09f1bf24", +"61:orders_model_14.has_star": "fcbcf165908dd18a9e49f7ff", +"62:orders_model_14.edge_count": "d4735e3a265e16eee03f5971", +"63:orders_model_14.targeting": "994b51789f15903e6e3ff4f7", +"64:orders_model_14.sourced": "6786f18f6ff42aa577c99d86", +"65:orders_model_2.has_model": "b5bea41b6c623f7c09f1bf24", +"66:orders_model_2.has_star": "fcbcf165908dd18a9e49f7ff", +"67:orders_model_2.edge_count": "6b86b273ff34fce19d6b804e", +"68:orders_model_2.targeting": "a1cfbb075e39a1f31cf0a389", +"69:orders_model_2.sourced": "dbcb0d17df16270e8948b6a7", +"6:orders_model_12.has_star": "fcbcf165908dd18a9e49f7ff", +"70:orders_model_5.has_model": "b5bea41b6c623f7c09f1bf24", +"71:orders_model_5.has_star": "fcbcf165908dd18a9e49f7ff", +"72:orders_model_5.edge_count": "d4735e3a265e16eee03f5971", +"73:orders_model_5.targeting": "39f9d2b502e4a51f5da00952", +"74:orders_model_5.sourced": "6786f18f6ff42aa577c99d86", +"75:orders_model_8.has_model": "b5bea41b6c623f7c09f1bf24", +"76:orders_model_8.has_star": "b5bea41b6c623f7c09f1bf24", +"77:orders_model_8.edge_count": "4b227777d4dd1fc61c6f884f", +"78:orders_model_8.targeting": "efe9b5370341db1214ac6791", +"79:orders_model_8.sourced": "6786f18f6ff42aa577c99d86", +"7:orders_model_12.edge_count": "d4735e3a265e16eee03f5971", +"80:models": "766e6cff4a7c97985d321915", +"81:edges": "66def530d7ac79c6a553f347", +"8:orders_model_12.targeting": "d7d16e7a663f8aecabea3ed6", +"9:orders_model_12.sourced": "6786f18f6ff42aa577c99d86" +} +], +[ +"lineage", +{ +"0:orders_model_0.has_model": "fcbcf165908dd18a9e49f7ff", +"10:orders_model_15.has_model": "fcbcf165908dd18a9e49f7ff", +"11:orders_model_15.has_star": "fcbcf165908dd18a9e49f7ff", +"12:orders_model_15.edge_count": "5feceb66ffc86f38d952786c", +"13:orders_model_15.targeting": "6786f18f6ff42aa577c99d86", +"14:orders_model_15.sourced": "6786f18f6ff42aa577c99d86", +"15:orders_model_3.has_model": "fcbcf165908dd18a9e49f7ff", +"16:orders_model_3.has_star": "fcbcf165908dd18a9e49f7ff", +"17:orders_model_3.edge_count": "5feceb66ffc86f38d952786c", +"18:orders_model_3.targeting": "6786f18f6ff42aa577c99d86", +"19:orders_model_3.sourced": "6786f18f6ff42aa577c99d86", +"1:orders_model_0.has_star": "fcbcf165908dd18a9e49f7ff", +"20:orders_model_6.has_model": "fcbcf165908dd18a9e49f7ff", +"21:orders_model_6.has_star": "fcbcf165908dd18a9e49f7ff", +"22:orders_model_6.edge_count": "5feceb66ffc86f38d952786c", +"23:orders_model_6.targeting": "6786f18f6ff42aa577c99d86", +"24:orders_model_6.sourced": "6786f18f6ff42aa577c99d86", +"25:orders_model_9.has_model": "b5bea41b6c623f7c09f1bf24", +"26:orders_model_9.has_star": "b5bea41b6c623f7c09f1bf24", +"27:orders_model_9.edge_count": "d4735e3a265e16eee03f5971", +"28:orders_model_9.targeting": "ba0aa56821a51ebc64bd22bd", +"29:orders_model_9.sourced": "1b17f70a4e68bc83fc11a319", +"2:orders_model_0.edge_count": "5feceb66ffc86f38d952786c", +"30:orders_model_1.has_model": "b5bea41b6c623f7c09f1bf24", +"31:orders_model_1.has_star": "b5bea41b6c623f7c09f1bf24", +"32:orders_model_1.edge_count": "ef2d127de37b942baad06145", +"33:orders_model_1.targeting": "a1542a5c221b33c2756c09ec", +"34:orders_model_1.sourced": "ebabe32d36bc3dcf101f953f", +"35:orders_model_10.has_model": "b5bea41b6c623f7c09f1bf24", +"36:orders_model_10.has_star": "b5bea41b6c623f7c09f1bf24", +"37:orders_model_10.edge_count": "d4735e3a265e16eee03f5971", +"38:orders_model_10.targeting": "1b17f70a4e68bc83fc11a319", +"39:orders_model_10.sourced": "6786f18f6ff42aa577c99d86", +"3:orders_model_0.targeting": "6786f18f6ff42aa577c99d86", +"40:orders_model_13.has_model": "fcbcf165908dd18a9e49f7ff", +"41:orders_model_13.has_star": "fcbcf165908dd18a9e49f7ff", +"42:orders_model_13.edge_count": "5feceb66ffc86f38d952786c", +"43:orders_model_13.targeting": "6786f18f6ff42aa577c99d86", +"44:orders_model_13.sourced": "6786f18f6ff42aa577c99d86", +"45:orders_model_4.has_model": "b5bea41b6c623f7c09f1bf24", +"46:orders_model_4.has_star": "b5bea41b6c623f7c09f1bf24", +"47:orders_model_4.edge_count": "d4735e3a265e16eee03f5971", +"48:orders_model_4.targeting": "f50bdb75eee2988eed8ac15d", +"49:orders_model_4.sourced": "39f9d2b502e4a51f5da00952", +"4:orders_model_0.sourced": "c67fcc4d7a42429aab9315c9", +"50:orders_model_7.has_model": "fcbcf165908dd18a9e49f7ff", +"51:orders_model_7.has_star": "fcbcf165908dd18a9e49f7ff", +"52:orders_model_7.edge_count": "5feceb66ffc86f38d952786c", +"53:orders_model_7.targeting": "6786f18f6ff42aa577c99d86", +"54:orders_model_7.sourced": "efe9b5370341db1214ac6791", +"55:orders_model_11.has_model": "fcbcf165908dd18a9e49f7ff", +"56:orders_model_11.has_star": "fcbcf165908dd18a9e49f7ff", +"57:orders_model_11.edge_count": "5feceb66ffc86f38d952786c", +"58:orders_model_11.targeting": "6786f18f6ff42aa577c99d86", +"59:orders_model_11.sourced": "994b51789f15903e6e3ff4f7", +"5:orders_model_12.has_model": "b5bea41b6c623f7c09f1bf24", +"60:orders_model_14.has_model": "b5bea41b6c623f7c09f1bf24", +"61:orders_model_14.has_star": "fcbcf165908dd18a9e49f7ff", +"62:orders_model_14.edge_count": "d4735e3a265e16eee03f5971", +"63:orders_model_14.targeting": "994b51789f15903e6e3ff4f7", +"64:orders_model_14.sourced": "6786f18f6ff42aa577c99d86", +"65:orders_model_2.has_model": "fcbcf165908dd18a9e49f7ff", +"66:orders_model_2.has_star": "fcbcf165908dd18a9e49f7ff", +"67:orders_model_2.edge_count": "5feceb66ffc86f38d952786c", +"68:orders_model_2.targeting": "6786f18f6ff42aa577c99d86", +"69:orders_model_2.sourced": "6786f18f6ff42aa577c99d86", +"6:orders_model_12.has_star": "fcbcf165908dd18a9e49f7ff", +"70:orders_model_5.has_model": "b5bea41b6c623f7c09f1bf24", +"71:orders_model_5.has_star": "fcbcf165908dd18a9e49f7ff", +"72:orders_model_5.edge_count": "d4735e3a265e16eee03f5971", +"73:orders_model_5.targeting": "39f9d2b502e4a51f5da00952", +"74:orders_model_5.sourced": "6786f18f6ff42aa577c99d86", +"75:orders_model_8.has_model": "b5bea41b6c623f7c09f1bf24", +"76:orders_model_8.has_star": "b5bea41b6c623f7c09f1bf24", +"77:orders_model_8.edge_count": "4b227777d4dd1fc61c6f884f", +"78:orders_model_8.targeting": "efe9b5370341db1214ac6791", +"79:orders_model_8.sourced": "6786f18f6ff42aa577c99d86", +"7:orders_model_12.edge_count": "d4735e3a265e16eee03f5971", +"80:models": "e3f9826cd489c85cd139787f", +"81:edges": "ff90a6fe0029bd81150fd61c", +"8:orders_model_12.targeting": "d7d16e7a663f8aecabea3ed6", +"9:orders_model_12.sourced": "6786f18f6ff42aa577c99d86" +} +], +[ +"lineage", +{ +"0:orders_model_0.has_model": "b5bea41b6c623f7c09f1bf24", +"10:orders_model_15.has_model": "b5bea41b6c623f7c09f1bf24", +"11:orders_model_15.has_star": "fcbcf165908dd18a9e49f7ff", +"12:orders_model_15.edge_count": "4e07408562bedb8b60ce05c1", +"13:orders_model_15.targeting": "c64df03c7fbbe86c07c4c602", +"14:orders_model_15.sourced": "6786f18f6ff42aa577c99d86", +"15:orders_model_3.has_model": "fcbcf165908dd18a9e49f7ff", +"16:orders_model_3.has_star": "fcbcf165908dd18a9e49f7ff", +"17:orders_model_3.edge_count": "5feceb66ffc86f38d952786c", +"18:orders_model_3.targeting": "6786f18f6ff42aa577c99d86", +"19:orders_model_3.sourced": "6786f18f6ff42aa577c99d86", +"1:orders_model_0.has_star": "b5bea41b6c623f7c09f1bf24", +"20:orders_model_6.has_model": "b5bea41b6c623f7c09f1bf24", +"21:orders_model_6.has_star": "fcbcf165908dd18a9e49f7ff", +"22:orders_model_6.edge_count": "4e07408562bedb8b60ce05c1", +"23:orders_model_6.targeting": "1bc33c8cc436098dc553984f", +"24:orders_model_6.sourced": "6786f18f6ff42aa577c99d86", +"25:orders_model_9.has_model": "b5bea41b6c623f7c09f1bf24", +"26:orders_model_9.has_star": "b5bea41b6c623f7c09f1bf24", +"27:orders_model_9.edge_count": "d4735e3a265e16eee03f5971", +"28:orders_model_9.targeting": "dd982a80f52d1f2e0b2aa038", +"29:orders_model_9.sourced": "1b17f70a4e68bc83fc11a319", +"2:orders_model_0.edge_count": "d4735e3a265e16eee03f5971", +"30:orders_model_1.has_model": "b5bea41b6c623f7c09f1bf24", +"31:orders_model_1.has_star": "b5bea41b6c623f7c09f1bf24", +"32:orders_model_1.edge_count": "ef2d127de37b942baad06145", +"33:orders_model_1.targeting": "a1542a5c221b33c2756c09ec", +"34:orders_model_1.sourced": "e6943a672bbc12e8187aada0", +"35:orders_model_10.has_model": "b5bea41b6c623f7c09f1bf24", +"36:orders_model_10.has_star": "b5bea41b6c623f7c09f1bf24", +"37:orders_model_10.edge_count": "4e07408562bedb8b60ce05c1", +"38:orders_model_10.targeting": "c5c2638bd29835ebf459d9a4", +"39:orders_model_10.sourced": "6786f18f6ff42aa577c99d86", +"3:orders_model_0.targeting": "10f59ba6b47d64ce6b56d32b", +"40:orders_model_13.has_model": "b5bea41b6c623f7c09f1bf24", +"41:orders_model_13.has_star": "b5bea41b6c623f7c09f1bf24", +"42:orders_model_13.edge_count": "d4735e3a265e16eee03f5971", +"43:orders_model_13.targeting": "fb2bd7475476ed8980a4ac2c", +"44:orders_model_13.sourced": "6786f18f6ff42aa577c99d86", +"45:orders_model_4.has_model": "b5bea41b6c623f7c09f1bf24", +"46:orders_model_4.has_star": "b5bea41b6c623f7c09f1bf24", +"47:orders_model_4.edge_count": "d4735e3a265e16eee03f5971", +"48:orders_model_4.targeting": "f50bdb75eee2988eed8ac15d", +"49:orders_model_4.sourced": "801fdd180a6d4964a072f211", +"4:orders_model_0.sourced": "9efe230670328edc3abca75d", +"50:orders_model_7.has_model": "b5bea41b6c623f7c09f1bf24", +"51:orders_model_7.has_star": "fcbcf165908dd18a9e49f7ff", +"52:orders_model_7.edge_count": "7902699be42c8a8e46fbbb45", +"53:orders_model_7.targeting": "a14cb265582196761feee603", +"54:orders_model_7.sourced": "efe9b5370341db1214ac6791", +"55:orders_model_11.has_model": "b5bea41b6c623f7c09f1bf24", +"56:orders_model_11.has_star": "fcbcf165908dd18a9e49f7ff", +"57:orders_model_11.edge_count": "6b86b273ff34fce19d6b804e", +"58:orders_model_11.targeting": "8e0e0c410e143c02cde2f39d", +"59:orders_model_11.sourced": "994b51789f15903e6e3ff4f7", +"5:orders_model_12.has_model": "b5bea41b6c623f7c09f1bf24", +"60:orders_model_14.has_model": "b5bea41b6c623f7c09f1bf24", +"61:orders_model_14.has_star": "fcbcf165908dd18a9e49f7ff", +"62:orders_model_14.edge_count": "d4735e3a265e16eee03f5971", +"63:orders_model_14.targeting": "994b51789f15903e6e3ff4f7", +"64:orders_model_14.sourced": "6786f18f6ff42aa577c99d86", +"65:orders_model_2.has_model": "b5bea41b6c623f7c09f1bf24", +"66:orders_model_2.has_star": "fcbcf165908dd18a9e49f7ff", +"67:orders_model_2.edge_count": "6b86b273ff34fce19d6b804e", +"68:orders_model_2.targeting": "a1cfbb075e39a1f31cf0a389", +"69:orders_model_2.sourced": "bed262571d7e3d10fddbcd5c", +"6:orders_model_12.has_star": "fcbcf165908dd18a9e49f7ff", +"70:orders_model_5.has_model": "b5bea41b6c623f7c09f1bf24", +"71:orders_model_5.has_star": "fcbcf165908dd18a9e49f7ff", +"72:orders_model_5.edge_count": "d4735e3a265e16eee03f5971", +"73:orders_model_5.targeting": "387649cf44d2ffb7009909a1", +"74:orders_model_5.sourced": "6786f18f6ff42aa577c99d86", +"75:orders_model_8.has_model": "b5bea41b6c623f7c09f1bf24", +"76:orders_model_8.has_star": "b5bea41b6c623f7c09f1bf24", +"77:orders_model_8.edge_count": "4b227777d4dd1fc61c6f884f", +"78:orders_model_8.targeting": "efe9b5370341db1214ac6791", +"79:orders_model_8.sourced": "6786f18f6ff42aa577c99d86", +"7:orders_model_12.edge_count": "d4735e3a265e16eee03f5971", +"80:models": "726a3631488829e7d85f22a4", +"81:edges": "353ba5589c448640b32285cf", +"8:orders_model_12.targeting": "8a14701822a8a3706d504b23", +"9:orders_model_12.sourced": "6786f18f6ff42aa577c99d86" +} +], +[ +"lineage", +{ +"0:orders_model_0.has_model": "fcbcf165908dd18a9e49f7ff", +"10:orders_model_15.has_model": "fcbcf165908dd18a9e49f7ff", +"11:orders_model_15.has_star": "fcbcf165908dd18a9e49f7ff", +"12:orders_model_15.edge_count": "5feceb66ffc86f38d952786c", +"13:orders_model_15.targeting": "6786f18f6ff42aa577c99d86", +"14:orders_model_15.sourced": "6786f18f6ff42aa577c99d86", +"15:orders_model_3.has_model": "fcbcf165908dd18a9e49f7ff", +"16:orders_model_3.has_star": "fcbcf165908dd18a9e49f7ff", +"17:orders_model_3.edge_count": "5feceb66ffc86f38d952786c", +"18:orders_model_3.targeting": "6786f18f6ff42aa577c99d86", +"19:orders_model_3.sourced": "6786f18f6ff42aa577c99d86", +"1:orders_model_0.has_star": "fcbcf165908dd18a9e49f7ff", +"20:orders_model_6.has_model": "fcbcf165908dd18a9e49f7ff", +"21:orders_model_6.has_star": "fcbcf165908dd18a9e49f7ff", +"22:orders_model_6.edge_count": "5feceb66ffc86f38d952786c", +"23:orders_model_6.targeting": "6786f18f6ff42aa577c99d86", +"24:orders_model_6.sourced": "6786f18f6ff42aa577c99d86", +"25:orders_model_9.has_model": "b5bea41b6c623f7c09f1bf24", +"26:orders_model_9.has_star": "b5bea41b6c623f7c09f1bf24", +"27:orders_model_9.edge_count": "d4735e3a265e16eee03f5971", +"28:orders_model_9.targeting": "dd982a80f52d1f2e0b2aa038", +"29:orders_model_9.sourced": "1b17f70a4e68bc83fc11a319", +"2:orders_model_0.edge_count": "5feceb66ffc86f38d952786c", +"30:orders_model_1.has_model": "b5bea41b6c623f7c09f1bf24", +"31:orders_model_1.has_star": "b5bea41b6c623f7c09f1bf24", +"32:orders_model_1.edge_count": "ef2d127de37b942baad06145", +"33:orders_model_1.targeting": "a1542a5c221b33c2756c09ec", +"34:orders_model_1.sourced": "e6943a672bbc12e8187aada0", +"35:orders_model_10.has_model": "b5bea41b6c623f7c09f1bf24", +"36:orders_model_10.has_star": "b5bea41b6c623f7c09f1bf24", +"37:orders_model_10.edge_count": "4e07408562bedb8b60ce05c1", +"38:orders_model_10.targeting": "c5c2638bd29835ebf459d9a4", +"39:orders_model_10.sourced": "6786f18f6ff42aa577c99d86", +"3:orders_model_0.targeting": "6786f18f6ff42aa577c99d86", +"40:orders_model_13.has_model": "fcbcf165908dd18a9e49f7ff", +"41:orders_model_13.has_star": "fcbcf165908dd18a9e49f7ff", +"42:orders_model_13.edge_count": "5feceb66ffc86f38d952786c", +"43:orders_model_13.targeting": "6786f18f6ff42aa577c99d86", +"44:orders_model_13.sourced": "6786f18f6ff42aa577c99d86", +"45:orders_model_4.has_model": "b5bea41b6c623f7c09f1bf24", +"46:orders_model_4.has_star": "b5bea41b6c623f7c09f1bf24", +"47:orders_model_4.edge_count": "d4735e3a265e16eee03f5971", +"48:orders_model_4.targeting": "f50bdb75eee2988eed8ac15d", +"49:orders_model_4.sourced": "387649cf44d2ffb7009909a1", +"4:orders_model_0.sourced": "6ee202eaef83cf0a4a6ed539", +"50:orders_model_7.has_model": "fcbcf165908dd18a9e49f7ff", +"51:orders_model_7.has_star": "fcbcf165908dd18a9e49f7ff", +"52:orders_model_7.edge_count": "5feceb66ffc86f38d952786c", +"53:orders_model_7.targeting": "6786f18f6ff42aa577c99d86", +"54:orders_model_7.sourced": "efe9b5370341db1214ac6791", +"55:orders_model_11.has_model": "fcbcf165908dd18a9e49f7ff", +"56:orders_model_11.has_star": "fcbcf165908dd18a9e49f7ff", +"57:orders_model_11.edge_count": "5feceb66ffc86f38d952786c", +"58:orders_model_11.targeting": "6786f18f6ff42aa577c99d86", +"59:orders_model_11.sourced": "994b51789f15903e6e3ff4f7", +"5:orders_model_12.has_model": "b5bea41b6c623f7c09f1bf24", +"60:orders_model_14.has_model": "b5bea41b6c623f7c09f1bf24", +"61:orders_model_14.has_star": "fcbcf165908dd18a9e49f7ff", +"62:orders_model_14.edge_count": "d4735e3a265e16eee03f5971", +"63:orders_model_14.targeting": "994b51789f15903e6e3ff4f7", +"64:orders_model_14.sourced": "6786f18f6ff42aa577c99d86", +"65:orders_model_2.has_model": "fcbcf165908dd18a9e49f7ff", +"66:orders_model_2.has_star": "fcbcf165908dd18a9e49f7ff", +"67:orders_model_2.edge_count": "5feceb66ffc86f38d952786c", +"68:orders_model_2.targeting": "6786f18f6ff42aa577c99d86", +"69:orders_model_2.sourced": "6786f18f6ff42aa577c99d86", +"6:orders_model_12.has_star": "fcbcf165908dd18a9e49f7ff", +"70:orders_model_5.has_model": "b5bea41b6c623f7c09f1bf24", +"71:orders_model_5.has_star": "fcbcf165908dd18a9e49f7ff", +"72:orders_model_5.edge_count": "d4735e3a265e16eee03f5971", +"73:orders_model_5.targeting": "387649cf44d2ffb7009909a1", +"74:orders_model_5.sourced": "6786f18f6ff42aa577c99d86", +"75:orders_model_8.has_model": "b5bea41b6c623f7c09f1bf24", +"76:orders_model_8.has_star": "b5bea41b6c623f7c09f1bf24", +"77:orders_model_8.edge_count": "4b227777d4dd1fc61c6f884f", +"78:orders_model_8.targeting": "efe9b5370341db1214ac6791", +"79:orders_model_8.sourced": "6786f18f6ff42aa577c99d86", +"7:orders_model_12.edge_count": "d4735e3a265e16eee03f5971", +"80:models": "634a199b0204ba6c3ca102dc", +"81:edges": "5258bb66e465fbd07d87c222", +"8:orders_model_12.targeting": "8a14701822a8a3706d504b23", +"9:orders_model_12.sourced": "6786f18f6ff42aa577c99d86" +} +], +[ +"lineage", +{ +"0:orders_model_0.has_model": "b5bea41b6c623f7c09f1bf24", +"10:orders_model_15.has_model": "b5bea41b6c623f7c09f1bf24", +"11:orders_model_15.has_star": "fcbcf165908dd18a9e49f7ff", +"12:orders_model_15.edge_count": "4e07408562bedb8b60ce05c1", +"13:orders_model_15.targeting": "c64df03c7fbbe86c07c4c602", +"14:orders_model_15.sourced": "6786f18f6ff42aa577c99d86", +"15:orders_model_3.has_model": "fcbcf165908dd18a9e49f7ff", +"16:orders_model_3.has_star": "fcbcf165908dd18a9e49f7ff", +"17:orders_model_3.edge_count": "5feceb66ffc86f38d952786c", +"18:orders_model_3.targeting": "6786f18f6ff42aa577c99d86", +"19:orders_model_3.sourced": "6786f18f6ff42aa577c99d86", +"1:orders_model_0.has_star": "b5bea41b6c623f7c09f1bf24", +"20:orders_model_6.has_model": "b5bea41b6c623f7c09f1bf24", +"21:orders_model_6.has_star": "fcbcf165908dd18a9e49f7ff", +"22:orders_model_6.edge_count": "4e07408562bedb8b60ce05c1", +"23:orders_model_6.targeting": "1bc33c8cc436098dc553984f", +"24:orders_model_6.sourced": "6786f18f6ff42aa577c99d86", +"25:orders_model_9.has_model": "b5bea41b6c623f7c09f1bf24", +"26:orders_model_9.has_star": "b5bea41b6c623f7c09f1bf24", +"27:orders_model_9.edge_count": "d4735e3a265e16eee03f5971", +"28:orders_model_9.targeting": "dd982a80f52d1f2e0b2aa038", +"29:orders_model_9.sourced": "1b17f70a4e68bc83fc11a319", +"2:orders_model_0.edge_count": "d4735e3a265e16eee03f5971", +"30:orders_model_1.has_model": "b5bea41b6c623f7c09f1bf24", +"31:orders_model_1.has_star": "b5bea41b6c623f7c09f1bf24", +"32:orders_model_1.edge_count": "ef2d127de37b942baad06145", +"33:orders_model_1.targeting": "a1542a5c221b33c2756c09ec", +"34:orders_model_1.sourced": "e6943a672bbc12e8187aada0", +"35:orders_model_10.has_model": "b5bea41b6c623f7c09f1bf24", +"36:orders_model_10.has_star": "b5bea41b6c623f7c09f1bf24", +"37:orders_model_10.edge_count": "4e07408562bedb8b60ce05c1", +"38:orders_model_10.targeting": "c5c2638bd29835ebf459d9a4", +"39:orders_model_10.sourced": "6786f18f6ff42aa577c99d86", +"3:orders_model_0.targeting": "10f59ba6b47d64ce6b56d32b", +"40:orders_model_13.has_model": "b5bea41b6c623f7c09f1bf24", +"41:orders_model_13.has_star": "b5bea41b6c623f7c09f1bf24", +"42:orders_model_13.edge_count": "d4735e3a265e16eee03f5971", +"43:orders_model_13.targeting": "fb2bd7475476ed8980a4ac2c", +"44:orders_model_13.sourced": "6786f18f6ff42aa577c99d86", +"45:orders_model_4.has_model": "b5bea41b6c623f7c09f1bf24", +"46:orders_model_4.has_star": "b5bea41b6c623f7c09f1bf24", +"47:orders_model_4.edge_count": "d4735e3a265e16eee03f5971", +"48:orders_model_4.targeting": "f50bdb75eee2988eed8ac15d", +"49:orders_model_4.sourced": "801fdd180a6d4964a072f211", +"4:orders_model_0.sourced": "9efe230670328edc3abca75d", +"50:orders_model_7.has_model": "b5bea41b6c623f7c09f1bf24", +"51:orders_model_7.has_star": "fcbcf165908dd18a9e49f7ff", +"52:orders_model_7.edge_count": "7902699be42c8a8e46fbbb45", +"53:orders_model_7.targeting": "a14cb265582196761feee603", +"54:orders_model_7.sourced": "efe9b5370341db1214ac6791", +"55:orders_model_11.has_model": "b5bea41b6c623f7c09f1bf24", +"56:orders_model_11.has_star": "fcbcf165908dd18a9e49f7ff", +"57:orders_model_11.edge_count": "6b86b273ff34fce19d6b804e", +"58:orders_model_11.targeting": "8e0e0c410e143c02cde2f39d", +"59:orders_model_11.sourced": "994b51789f15903e6e3ff4f7", +"5:orders_model_12.has_model": "b5bea41b6c623f7c09f1bf24", +"60:orders_model_14.has_model": "b5bea41b6c623f7c09f1bf24", +"61:orders_model_14.has_star": "fcbcf165908dd18a9e49f7ff", +"62:orders_model_14.edge_count": "d4735e3a265e16eee03f5971", +"63:orders_model_14.targeting": "994b51789f15903e6e3ff4f7", +"64:orders_model_14.sourced": "6786f18f6ff42aa577c99d86", +"65:orders_model_2.has_model": "b5bea41b6c623f7c09f1bf24", +"66:orders_model_2.has_star": "fcbcf165908dd18a9e49f7ff", +"67:orders_model_2.edge_count": "6b86b273ff34fce19d6b804e", +"68:orders_model_2.targeting": "a1cfbb075e39a1f31cf0a389", +"69:orders_model_2.sourced": "bed262571d7e3d10fddbcd5c", +"6:orders_model_12.has_star": "fcbcf165908dd18a9e49f7ff", +"70:orders_model_5.has_model": "b5bea41b6c623f7c09f1bf24", +"71:orders_model_5.has_star": "fcbcf165908dd18a9e49f7ff", +"72:orders_model_5.edge_count": "d4735e3a265e16eee03f5971", +"73:orders_model_5.targeting": "387649cf44d2ffb7009909a1", +"74:orders_model_5.sourced": "6786f18f6ff42aa577c99d86", +"75:orders_model_8.has_model": "b5bea41b6c623f7c09f1bf24", +"76:orders_model_8.has_star": "b5bea41b6c623f7c09f1bf24", +"77:orders_model_8.edge_count": "4b227777d4dd1fc61c6f884f", +"78:orders_model_8.targeting": "efe9b5370341db1214ac6791", +"79:orders_model_8.sourced": "6786f18f6ff42aa577c99d86", +"7:orders_model_12.edge_count": "d4735e3a265e16eee03f5971", +"80:models": "726a3631488829e7d85f22a4", +"81:edges": "353ba5589c448640b32285cf", +"8:orders_model_12.targeting": "8a14701822a8a3706d504b23", +"9:orders_model_12.sourced": "6786f18f6ff42aa577c99d86" +} +], +[ +"lineage", +{ +"0:orders_model_0.has_model": "fcbcf165908dd18a9e49f7ff", +"10:orders_model_15.has_model": "fcbcf165908dd18a9e49f7ff", +"11:orders_model_15.has_star": "fcbcf165908dd18a9e49f7ff", +"12:orders_model_15.edge_count": "5feceb66ffc86f38d952786c", +"13:orders_model_15.targeting": "6786f18f6ff42aa577c99d86", +"14:orders_model_15.sourced": "6786f18f6ff42aa577c99d86", +"15:orders_model_3.has_model": "fcbcf165908dd18a9e49f7ff", +"16:orders_model_3.has_star": "fcbcf165908dd18a9e49f7ff", +"17:orders_model_3.edge_count": "5feceb66ffc86f38d952786c", +"18:orders_model_3.targeting": "6786f18f6ff42aa577c99d86", +"19:orders_model_3.sourced": "6786f18f6ff42aa577c99d86", +"1:orders_model_0.has_star": "fcbcf165908dd18a9e49f7ff", +"20:orders_model_6.has_model": "fcbcf165908dd18a9e49f7ff", +"21:orders_model_6.has_star": "fcbcf165908dd18a9e49f7ff", +"22:orders_model_6.edge_count": "5feceb66ffc86f38d952786c", +"23:orders_model_6.targeting": "6786f18f6ff42aa577c99d86", +"24:orders_model_6.sourced": "6786f18f6ff42aa577c99d86", +"25:orders_model_9.has_model": "b5bea41b6c623f7c09f1bf24", +"26:orders_model_9.has_star": "b5bea41b6c623f7c09f1bf24", +"27:orders_model_9.edge_count": "d4735e3a265e16eee03f5971", +"28:orders_model_9.targeting": "dd982a80f52d1f2e0b2aa038", +"29:orders_model_9.sourced": "1b17f70a4e68bc83fc11a319", +"2:orders_model_0.edge_count": "5feceb66ffc86f38d952786c", +"30:orders_model_1.has_model": "b5bea41b6c623f7c09f1bf24", +"31:orders_model_1.has_star": "b5bea41b6c623f7c09f1bf24", +"32:orders_model_1.edge_count": "ef2d127de37b942baad06145", +"33:orders_model_1.targeting": "a1542a5c221b33c2756c09ec", +"34:orders_model_1.sourced": "e6943a672bbc12e8187aada0", +"35:orders_model_10.has_model": "b5bea41b6c623f7c09f1bf24", +"36:orders_model_10.has_star": "b5bea41b6c623f7c09f1bf24", +"37:orders_model_10.edge_count": "4e07408562bedb8b60ce05c1", +"38:orders_model_10.targeting": "c5c2638bd29835ebf459d9a4", +"39:orders_model_10.sourced": "6786f18f6ff42aa577c99d86", +"3:orders_model_0.targeting": "6786f18f6ff42aa577c99d86", +"40:orders_model_13.has_model": "fcbcf165908dd18a9e49f7ff", +"41:orders_model_13.has_star": "fcbcf165908dd18a9e49f7ff", +"42:orders_model_13.edge_count": "5feceb66ffc86f38d952786c", +"43:orders_model_13.targeting": "6786f18f6ff42aa577c99d86", +"44:orders_model_13.sourced": "6786f18f6ff42aa577c99d86", +"45:orders_model_4.has_model": "b5bea41b6c623f7c09f1bf24", +"46:orders_model_4.has_star": "b5bea41b6c623f7c09f1bf24", +"47:orders_model_4.edge_count": "d4735e3a265e16eee03f5971", +"48:orders_model_4.targeting": "f50bdb75eee2988eed8ac15d", +"49:orders_model_4.sourced": "387649cf44d2ffb7009909a1", +"4:orders_model_0.sourced": "6ee202eaef83cf0a4a6ed539", +"50:orders_model_7.has_model": "fcbcf165908dd18a9e49f7ff", +"51:orders_model_7.has_star": "fcbcf165908dd18a9e49f7ff", +"52:orders_model_7.edge_count": "5feceb66ffc86f38d952786c", +"53:orders_model_7.targeting": "6786f18f6ff42aa577c99d86", +"54:orders_model_7.sourced": "efe9b5370341db1214ac6791", +"55:orders_model_11.has_model": "fcbcf165908dd18a9e49f7ff", +"56:orders_model_11.has_star": "fcbcf165908dd18a9e49f7ff", +"57:orders_model_11.edge_count": "5feceb66ffc86f38d952786c", +"58:orders_model_11.targeting": "6786f18f6ff42aa577c99d86", +"59:orders_model_11.sourced": "994b51789f15903e6e3ff4f7", +"5:orders_model_12.has_model": "b5bea41b6c623f7c09f1bf24", +"60:orders_model_14.has_model": "b5bea41b6c623f7c09f1bf24", +"61:orders_model_14.has_star": "fcbcf165908dd18a9e49f7ff", +"62:orders_model_14.edge_count": "d4735e3a265e16eee03f5971", +"63:orders_model_14.targeting": "994b51789f15903e6e3ff4f7", +"64:orders_model_14.sourced": "6786f18f6ff42aa577c99d86", +"65:orders_model_2.has_model": "fcbcf165908dd18a9e49f7ff", +"66:orders_model_2.has_star": "fcbcf165908dd18a9e49f7ff", +"67:orders_model_2.edge_count": "5feceb66ffc86f38d952786c", +"68:orders_model_2.targeting": "6786f18f6ff42aa577c99d86", +"69:orders_model_2.sourced": "6786f18f6ff42aa577c99d86", +"6:orders_model_12.has_star": "fcbcf165908dd18a9e49f7ff", +"70:orders_model_5.has_model": "b5bea41b6c623f7c09f1bf24", +"71:orders_model_5.has_star": "fcbcf165908dd18a9e49f7ff", +"72:orders_model_5.edge_count": "d4735e3a265e16eee03f5971", +"73:orders_model_5.targeting": "387649cf44d2ffb7009909a1", +"74:orders_model_5.sourced": "6786f18f6ff42aa577c99d86", +"75:orders_model_8.has_model": "b5bea41b6c623f7c09f1bf24", +"76:orders_model_8.has_star": "b5bea41b6c623f7c09f1bf24", +"77:orders_model_8.edge_count": "4b227777d4dd1fc61c6f884f", +"78:orders_model_8.targeting": "efe9b5370341db1214ac6791", +"79:orders_model_8.sourced": "6786f18f6ff42aa577c99d86", +"7:orders_model_12.edge_count": "d4735e3a265e16eee03f5971", +"80:models": "634a199b0204ba6c3ca102dc", +"81:edges": "5258bb66e465fbd07d87c222", +"8:orders_model_12.targeting": "8a14701822a8a3706d504b23", +"9:orders_model_12.sourced": "6786f18f6ff42aa577c99d86" +} +], +[ +"lineage", +{ +"0:orders_model_0.has_model": "b5bea41b6c623f7c09f1bf24", +"10:orders_model_15.has_model": "b5bea41b6c623f7c09f1bf24", +"11:orders_model_15.has_star": "fcbcf165908dd18a9e49f7ff", +"12:orders_model_15.edge_count": "4e07408562bedb8b60ce05c1", +"13:orders_model_15.targeting": "c64df03c7fbbe86c07c4c602", +"14:orders_model_15.sourced": "6786f18f6ff42aa577c99d86", +"15:orders_model_3.has_model": "fcbcf165908dd18a9e49f7ff", +"16:orders_model_3.has_star": "fcbcf165908dd18a9e49f7ff", +"17:orders_model_3.edge_count": "5feceb66ffc86f38d952786c", +"18:orders_model_3.targeting": "6786f18f6ff42aa577c99d86", +"19:orders_model_3.sourced": "6786f18f6ff42aa577c99d86", +"1:orders_model_0.has_star": "b5bea41b6c623f7c09f1bf24", +"20:orders_model_6.has_model": "b5bea41b6c623f7c09f1bf24", +"21:orders_model_6.has_star": "fcbcf165908dd18a9e49f7ff", +"22:orders_model_6.edge_count": "4e07408562bedb8b60ce05c1", +"23:orders_model_6.targeting": "1bc33c8cc436098dc553984f", +"24:orders_model_6.sourced": "6786f18f6ff42aa577c99d86", +"25:orders_model_9.has_model": "b5bea41b6c623f7c09f1bf24", +"26:orders_model_9.has_star": "b5bea41b6c623f7c09f1bf24", +"27:orders_model_9.edge_count": "d4735e3a265e16eee03f5971", +"28:orders_model_9.targeting": "dd982a80f52d1f2e0b2aa038", +"29:orders_model_9.sourced": "1b17f70a4e68bc83fc11a319", +"2:orders_model_0.edge_count": "d4735e3a265e16eee03f5971", +"30:orders_model_1.has_model": "b5bea41b6c623f7c09f1bf24", +"31:orders_model_1.has_star": "b5bea41b6c623f7c09f1bf24", +"32:orders_model_1.edge_count": "ef2d127de37b942baad06145", +"33:orders_model_1.targeting": "a1542a5c221b33c2756c09ec", +"34:orders_model_1.sourced": "e6943a672bbc12e8187aada0", +"35:orders_model_10.has_model": "b5bea41b6c623f7c09f1bf24", +"36:orders_model_10.has_star": "b5bea41b6c623f7c09f1bf24", +"37:orders_model_10.edge_count": "4e07408562bedb8b60ce05c1", +"38:orders_model_10.targeting": "c5c2638bd29835ebf459d9a4", +"39:orders_model_10.sourced": "6786f18f6ff42aa577c99d86", +"3:orders_model_0.targeting": "10f59ba6b47d64ce6b56d32b", +"40:orders_model_13.has_model": "b5bea41b6c623f7c09f1bf24", +"41:orders_model_13.has_star": "b5bea41b6c623f7c09f1bf24", +"42:orders_model_13.edge_count": "d4735e3a265e16eee03f5971", +"43:orders_model_13.targeting": "fb2bd7475476ed8980a4ac2c", +"44:orders_model_13.sourced": "6786f18f6ff42aa577c99d86", +"45:orders_model_4.has_model": "b5bea41b6c623f7c09f1bf24", +"46:orders_model_4.has_star": "b5bea41b6c623f7c09f1bf24", +"47:orders_model_4.edge_count": "d4735e3a265e16eee03f5971", +"48:orders_model_4.targeting": "f50bdb75eee2988eed8ac15d", +"49:orders_model_4.sourced": "801fdd180a6d4964a072f211", +"4:orders_model_0.sourced": "9efe230670328edc3abca75d", +"50:orders_model_7.has_model": "b5bea41b6c623f7c09f1bf24", +"51:orders_model_7.has_star": "fcbcf165908dd18a9e49f7ff", +"52:orders_model_7.edge_count": "7902699be42c8a8e46fbbb45", +"53:orders_model_7.targeting": "a14cb265582196761feee603", +"54:orders_model_7.sourced": "efe9b5370341db1214ac6791", +"55:orders_model_11.has_model": "b5bea41b6c623f7c09f1bf24", +"56:orders_model_11.has_star": "fcbcf165908dd18a9e49f7ff", +"57:orders_model_11.edge_count": "6b86b273ff34fce19d6b804e", +"58:orders_model_11.targeting": "8e0e0c410e143c02cde2f39d", +"59:orders_model_11.sourced": "994b51789f15903e6e3ff4f7", +"5:orders_model_12.has_model": "b5bea41b6c623f7c09f1bf24", +"60:orders_model_14.has_model": "b5bea41b6c623f7c09f1bf24", +"61:orders_model_14.has_star": "fcbcf165908dd18a9e49f7ff", +"62:orders_model_14.edge_count": "d4735e3a265e16eee03f5971", +"63:orders_model_14.targeting": "994b51789f15903e6e3ff4f7", +"64:orders_model_14.sourced": "6786f18f6ff42aa577c99d86", +"65:orders_model_2.has_model": "b5bea41b6c623f7c09f1bf24", +"66:orders_model_2.has_star": "fcbcf165908dd18a9e49f7ff", +"67:orders_model_2.edge_count": "6b86b273ff34fce19d6b804e", +"68:orders_model_2.targeting": "a1cfbb075e39a1f31cf0a389", +"69:orders_model_2.sourced": "bed262571d7e3d10fddbcd5c", +"6:orders_model_12.has_star": "fcbcf165908dd18a9e49f7ff", +"70:orders_model_5.has_model": "b5bea41b6c623f7c09f1bf24", +"71:orders_model_5.has_star": "fcbcf165908dd18a9e49f7ff", +"72:orders_model_5.edge_count": "d4735e3a265e16eee03f5971", +"73:orders_model_5.targeting": "387649cf44d2ffb7009909a1", +"74:orders_model_5.sourced": "6786f18f6ff42aa577c99d86", +"75:orders_model_8.has_model": "b5bea41b6c623f7c09f1bf24", +"76:orders_model_8.has_star": "b5bea41b6c623f7c09f1bf24", +"77:orders_model_8.edge_count": "4b227777d4dd1fc61c6f884f", +"78:orders_model_8.targeting": "efe9b5370341db1214ac6791", +"79:orders_model_8.sourced": "6786f18f6ff42aa577c99d86", +"7:orders_model_12.edge_count": "d4735e3a265e16eee03f5971", +"80:models": "726a3631488829e7d85f22a4", +"81:edges": "353ba5589c448640b32285cf", +"8:orders_model_12.targeting": "8a14701822a8a3706d504b23", +"9:orders_model_12.sourced": "6786f18f6ff42aa577c99d86" +} +], +[ +"lineage", +{ +"0:orders_model_0.has_model": "fcbcf165908dd18a9e49f7ff", +"10:orders_model_15.has_model": "fcbcf165908dd18a9e49f7ff", +"11:orders_model_15.has_star": "fcbcf165908dd18a9e49f7ff", +"12:orders_model_15.edge_count": "5feceb66ffc86f38d952786c", +"13:orders_model_15.targeting": "6786f18f6ff42aa577c99d86", +"14:orders_model_15.sourced": "6786f18f6ff42aa577c99d86", +"15:orders_model_3.has_model": "fcbcf165908dd18a9e49f7ff", +"16:orders_model_3.has_star": "fcbcf165908dd18a9e49f7ff", +"17:orders_model_3.edge_count": "5feceb66ffc86f38d952786c", +"18:orders_model_3.targeting": "6786f18f6ff42aa577c99d86", +"19:orders_model_3.sourced": "6786f18f6ff42aa577c99d86", +"1:orders_model_0.has_star": "fcbcf165908dd18a9e49f7ff", +"20:orders_model_6.has_model": "fcbcf165908dd18a9e49f7ff", +"21:orders_model_6.has_star": "fcbcf165908dd18a9e49f7ff", +"22:orders_model_6.edge_count": "5feceb66ffc86f38d952786c", +"23:orders_model_6.targeting": "6786f18f6ff42aa577c99d86", +"24:orders_model_6.sourced": "6786f18f6ff42aa577c99d86", +"25:orders_model_9.has_model": "b5bea41b6c623f7c09f1bf24", +"26:orders_model_9.has_star": "b5bea41b6c623f7c09f1bf24", +"27:orders_model_9.edge_count": "d4735e3a265e16eee03f5971", +"28:orders_model_9.targeting": "dd982a80f52d1f2e0b2aa038", +"29:orders_model_9.sourced": "1b17f70a4e68bc83fc11a319", +"2:orders_model_0.edge_count": "5feceb66ffc86f38d952786c", +"30:orders_model_1.has_model": "b5bea41b6c623f7c09f1bf24", +"31:orders_model_1.has_star": "b5bea41b6c623f7c09f1bf24", +"32:orders_model_1.edge_count": "ef2d127de37b942baad06145", +"33:orders_model_1.targeting": "a1542a5c221b33c2756c09ec", +"34:orders_model_1.sourced": "e6943a672bbc12e8187aada0", +"35:orders_model_10.has_model": "b5bea41b6c623f7c09f1bf24", +"36:orders_model_10.has_star": "b5bea41b6c623f7c09f1bf24", +"37:orders_model_10.edge_count": "4e07408562bedb8b60ce05c1", +"38:orders_model_10.targeting": "c5c2638bd29835ebf459d9a4", +"39:orders_model_10.sourced": "6786f18f6ff42aa577c99d86", +"3:orders_model_0.targeting": "6786f18f6ff42aa577c99d86", +"40:orders_model_13.has_model": "fcbcf165908dd18a9e49f7ff", +"41:orders_model_13.has_star": "fcbcf165908dd18a9e49f7ff", +"42:orders_model_13.edge_count": "5feceb66ffc86f38d952786c", +"43:orders_model_13.targeting": "6786f18f6ff42aa577c99d86", +"44:orders_model_13.sourced": "6786f18f6ff42aa577c99d86", +"45:orders_model_4.has_model": "b5bea41b6c623f7c09f1bf24", +"46:orders_model_4.has_star": "b5bea41b6c623f7c09f1bf24", +"47:orders_model_4.edge_count": "d4735e3a265e16eee03f5971", +"48:orders_model_4.targeting": "f50bdb75eee2988eed8ac15d", +"49:orders_model_4.sourced": "387649cf44d2ffb7009909a1", +"4:orders_model_0.sourced": "6ee202eaef83cf0a4a6ed539", +"50:orders_model_7.has_model": "fcbcf165908dd18a9e49f7ff", +"51:orders_model_7.has_star": "fcbcf165908dd18a9e49f7ff", +"52:orders_model_7.edge_count": "5feceb66ffc86f38d952786c", +"53:orders_model_7.targeting": "6786f18f6ff42aa577c99d86", +"54:orders_model_7.sourced": "efe9b5370341db1214ac6791", +"55:orders_model_11.has_model": "fcbcf165908dd18a9e49f7ff", +"56:orders_model_11.has_star": "fcbcf165908dd18a9e49f7ff", +"57:orders_model_11.edge_count": "5feceb66ffc86f38d952786c", +"58:orders_model_11.targeting": "6786f18f6ff42aa577c99d86", +"59:orders_model_11.sourced": "994b51789f15903e6e3ff4f7", +"5:orders_model_12.has_model": "b5bea41b6c623f7c09f1bf24", +"60:orders_model_14.has_model": "b5bea41b6c623f7c09f1bf24", +"61:orders_model_14.has_star": "fcbcf165908dd18a9e49f7ff", +"62:orders_model_14.edge_count": "d4735e3a265e16eee03f5971", +"63:orders_model_14.targeting": "994b51789f15903e6e3ff4f7", +"64:orders_model_14.sourced": "6786f18f6ff42aa577c99d86", +"65:orders_model_2.has_model": "fcbcf165908dd18a9e49f7ff", +"66:orders_model_2.has_star": "fcbcf165908dd18a9e49f7ff", +"67:orders_model_2.edge_count": "5feceb66ffc86f38d952786c", +"68:orders_model_2.targeting": "6786f18f6ff42aa577c99d86", +"69:orders_model_2.sourced": "6786f18f6ff42aa577c99d86", +"6:orders_model_12.has_star": "fcbcf165908dd18a9e49f7ff", +"70:orders_model_5.has_model": "b5bea41b6c623f7c09f1bf24", +"71:orders_model_5.has_star": "fcbcf165908dd18a9e49f7ff", +"72:orders_model_5.edge_count": "d4735e3a265e16eee03f5971", +"73:orders_model_5.targeting": "387649cf44d2ffb7009909a1", +"74:orders_model_5.sourced": "6786f18f6ff42aa577c99d86", +"75:orders_model_8.has_model": "b5bea41b6c623f7c09f1bf24", +"76:orders_model_8.has_star": "b5bea41b6c623f7c09f1bf24", +"77:orders_model_8.edge_count": "4b227777d4dd1fc61c6f884f", +"78:orders_model_8.targeting": "efe9b5370341db1214ac6791", +"79:orders_model_8.sourced": "6786f18f6ff42aa577c99d86", +"7:orders_model_12.edge_count": "d4735e3a265e16eee03f5971", +"80:models": "634a199b0204ba6c3ca102dc", +"81:edges": "5258bb66e465fbd07d87c222", +"8:orders_model_12.targeting": "8a14701822a8a3706d504b23", +"9:orders_model_12.sourced": "6786f18f6ff42aa577c99d86" +} +], +[ +"lineage", +{ +"0:orders_model_0.has_model": "b5bea41b6c623f7c09f1bf24", +"10:orders_model_15.has_model": "b5bea41b6c623f7c09f1bf24", +"11:orders_model_15.has_star": "fcbcf165908dd18a9e49f7ff", +"12:orders_model_15.edge_count": "4e07408562bedb8b60ce05c1", +"13:orders_model_15.targeting": "c64df03c7fbbe86c07c4c602", +"14:orders_model_15.sourced": "6786f18f6ff42aa577c99d86", +"15:orders_model_3.has_model": "fcbcf165908dd18a9e49f7ff", +"16:orders_model_3.has_star": "fcbcf165908dd18a9e49f7ff", +"17:orders_model_3.edge_count": "5feceb66ffc86f38d952786c", +"18:orders_model_3.targeting": "6786f18f6ff42aa577c99d86", +"19:orders_model_3.sourced": "6786f18f6ff42aa577c99d86", +"1:orders_model_0.has_star": "b5bea41b6c623f7c09f1bf24", +"20:orders_model_6.has_model": "b5bea41b6c623f7c09f1bf24", +"21:orders_model_6.has_star": "fcbcf165908dd18a9e49f7ff", +"22:orders_model_6.edge_count": "4e07408562bedb8b60ce05c1", +"23:orders_model_6.targeting": "1bc33c8cc436098dc553984f", +"24:orders_model_6.sourced": "6786f18f6ff42aa577c99d86", +"25:orders_model_9.has_model": "b5bea41b6c623f7c09f1bf24", +"26:orders_model_9.has_star": "b5bea41b6c623f7c09f1bf24", +"27:orders_model_9.edge_count": "d4735e3a265e16eee03f5971", +"28:orders_model_9.targeting": "dd982a80f52d1f2e0b2aa038", +"29:orders_model_9.sourced": "1b17f70a4e68bc83fc11a319", +"2:orders_model_0.edge_count": "d4735e3a265e16eee03f5971", +"30:orders_model_1.has_model": "b5bea41b6c623f7c09f1bf24", +"31:orders_model_1.has_star": "b5bea41b6c623f7c09f1bf24", +"32:orders_model_1.edge_count": "ef2d127de37b942baad06145", +"33:orders_model_1.targeting": "a1542a5c221b33c2756c09ec", +"34:orders_model_1.sourced": "e6943a672bbc12e8187aada0", +"35:orders_model_10.has_model": "b5bea41b6c623f7c09f1bf24", +"36:orders_model_10.has_star": "b5bea41b6c623f7c09f1bf24", +"37:orders_model_10.edge_count": "4e07408562bedb8b60ce05c1", +"38:orders_model_10.targeting": "c5c2638bd29835ebf459d9a4", +"39:orders_model_10.sourced": "6786f18f6ff42aa577c99d86", +"3:orders_model_0.targeting": "10f59ba6b47d64ce6b56d32b", +"40:orders_model_13.has_model": "b5bea41b6c623f7c09f1bf24", +"41:orders_model_13.has_star": "b5bea41b6c623f7c09f1bf24", +"42:orders_model_13.edge_count": "d4735e3a265e16eee03f5971", +"43:orders_model_13.targeting": "fb2bd7475476ed8980a4ac2c", +"44:orders_model_13.sourced": "6786f18f6ff42aa577c99d86", +"45:orders_model_4.has_model": "b5bea41b6c623f7c09f1bf24", +"46:orders_model_4.has_star": "b5bea41b6c623f7c09f1bf24", +"47:orders_model_4.edge_count": "d4735e3a265e16eee03f5971", +"48:orders_model_4.targeting": "f50bdb75eee2988eed8ac15d", +"49:orders_model_4.sourced": "801fdd180a6d4964a072f211", +"4:orders_model_0.sourced": "9efe230670328edc3abca75d", +"50:orders_model_7.has_model": "b5bea41b6c623f7c09f1bf24", +"51:orders_model_7.has_star": "fcbcf165908dd18a9e49f7ff", +"52:orders_model_7.edge_count": "7902699be42c8a8e46fbbb45", +"53:orders_model_7.targeting": "a14cb265582196761feee603", +"54:orders_model_7.sourced": "efe9b5370341db1214ac6791", +"55:orders_model_11.has_model": "b5bea41b6c623f7c09f1bf24", +"56:orders_model_11.has_star": "fcbcf165908dd18a9e49f7ff", +"57:orders_model_11.edge_count": "6b86b273ff34fce19d6b804e", +"58:orders_model_11.targeting": "8e0e0c410e143c02cde2f39d", +"59:orders_model_11.sourced": "994b51789f15903e6e3ff4f7", +"5:orders_model_12.has_model": "b5bea41b6c623f7c09f1bf24", +"60:orders_model_14.has_model": "b5bea41b6c623f7c09f1bf24", +"61:orders_model_14.has_star": "fcbcf165908dd18a9e49f7ff", +"62:orders_model_14.edge_count": "d4735e3a265e16eee03f5971", +"63:orders_model_14.targeting": "994b51789f15903e6e3ff4f7", +"64:orders_model_14.sourced": "6786f18f6ff42aa577c99d86", +"65:orders_model_2.has_model": "b5bea41b6c623f7c09f1bf24", +"66:orders_model_2.has_star": "fcbcf165908dd18a9e49f7ff", +"67:orders_model_2.edge_count": "6b86b273ff34fce19d6b804e", +"68:orders_model_2.targeting": "a1cfbb075e39a1f31cf0a389", +"69:orders_model_2.sourced": "bed262571d7e3d10fddbcd5c", +"6:orders_model_12.has_star": "fcbcf165908dd18a9e49f7ff", +"70:orders_model_5.has_model": "b5bea41b6c623f7c09f1bf24", +"71:orders_model_5.has_star": "fcbcf165908dd18a9e49f7ff", +"72:orders_model_5.edge_count": "d4735e3a265e16eee03f5971", +"73:orders_model_5.targeting": "387649cf44d2ffb7009909a1", +"74:orders_model_5.sourced": "6786f18f6ff42aa577c99d86", +"75:orders_model_8.has_model": "b5bea41b6c623f7c09f1bf24", +"76:orders_model_8.has_star": "b5bea41b6c623f7c09f1bf24", +"77:orders_model_8.edge_count": "4b227777d4dd1fc61c6f884f", +"78:orders_model_8.targeting": "efe9b5370341db1214ac6791", +"79:orders_model_8.sourced": "6786f18f6ff42aa577c99d86", +"7:orders_model_12.edge_count": "d4735e3a265e16eee03f5971", +"80:models": "726a3631488829e7d85f22a4", +"81:edges": "353ba5589c448640b32285cf", +"8:orders_model_12.targeting": "8a14701822a8a3706d504b23", +"9:orders_model_12.sourced": "6786f18f6ff42aa577c99d86" +} +], +[ +"lineage", +{ +"0:orders_model_0.has_model": "fcbcf165908dd18a9e49f7ff", +"10:orders_model_15.has_model": "fcbcf165908dd18a9e49f7ff", +"11:orders_model_15.has_star": "fcbcf165908dd18a9e49f7ff", +"12:orders_model_15.edge_count": "5feceb66ffc86f38d952786c", +"13:orders_model_15.targeting": "6786f18f6ff42aa577c99d86", +"14:orders_model_15.sourced": "6786f18f6ff42aa577c99d86", +"15:orders_model_3.has_model": "fcbcf165908dd18a9e49f7ff", +"16:orders_model_3.has_star": "fcbcf165908dd18a9e49f7ff", +"17:orders_model_3.edge_count": "5feceb66ffc86f38d952786c", +"18:orders_model_3.targeting": "6786f18f6ff42aa577c99d86", +"19:orders_model_3.sourced": "6786f18f6ff42aa577c99d86", +"1:orders_model_0.has_star": "fcbcf165908dd18a9e49f7ff", +"20:orders_model_6.has_model": "fcbcf165908dd18a9e49f7ff", +"21:orders_model_6.has_star": "fcbcf165908dd18a9e49f7ff", +"22:orders_model_6.edge_count": "5feceb66ffc86f38d952786c", +"23:orders_model_6.targeting": "6786f18f6ff42aa577c99d86", +"24:orders_model_6.sourced": "6786f18f6ff42aa577c99d86", +"25:orders_model_9.has_model": "b5bea41b6c623f7c09f1bf24", +"26:orders_model_9.has_star": "b5bea41b6c623f7c09f1bf24", +"27:orders_model_9.edge_count": "d4735e3a265e16eee03f5971", +"28:orders_model_9.targeting": "dd982a80f52d1f2e0b2aa038", +"29:orders_model_9.sourced": "1b17f70a4e68bc83fc11a319", +"2:orders_model_0.edge_count": "5feceb66ffc86f38d952786c", +"30:orders_model_1.has_model": "b5bea41b6c623f7c09f1bf24", +"31:orders_model_1.has_star": "b5bea41b6c623f7c09f1bf24", +"32:orders_model_1.edge_count": "ef2d127de37b942baad06145", +"33:orders_model_1.targeting": "a1542a5c221b33c2756c09ec", +"34:orders_model_1.sourced": "e6943a672bbc12e8187aada0", +"35:orders_model_10.has_model": "b5bea41b6c623f7c09f1bf24", +"36:orders_model_10.has_star": "b5bea41b6c623f7c09f1bf24", +"37:orders_model_10.edge_count": "4e07408562bedb8b60ce05c1", +"38:orders_model_10.targeting": "c5c2638bd29835ebf459d9a4", +"39:orders_model_10.sourced": "6786f18f6ff42aa577c99d86", +"3:orders_model_0.targeting": "6786f18f6ff42aa577c99d86", +"40:orders_model_13.has_model": "fcbcf165908dd18a9e49f7ff", +"41:orders_model_13.has_star": "fcbcf165908dd18a9e49f7ff", +"42:orders_model_13.edge_count": "5feceb66ffc86f38d952786c", +"43:orders_model_13.targeting": "6786f18f6ff42aa577c99d86", +"44:orders_model_13.sourced": "6786f18f6ff42aa577c99d86", +"45:orders_model_4.has_model": "b5bea41b6c623f7c09f1bf24", +"46:orders_model_4.has_star": "b5bea41b6c623f7c09f1bf24", +"47:orders_model_4.edge_count": "d4735e3a265e16eee03f5971", +"48:orders_model_4.targeting": "f50bdb75eee2988eed8ac15d", +"49:orders_model_4.sourced": "387649cf44d2ffb7009909a1", +"4:orders_model_0.sourced": "6ee202eaef83cf0a4a6ed539", +"50:orders_model_7.has_model": "fcbcf165908dd18a9e49f7ff", +"51:orders_model_7.has_star": "fcbcf165908dd18a9e49f7ff", +"52:orders_model_7.edge_count": "5feceb66ffc86f38d952786c", +"53:orders_model_7.targeting": "6786f18f6ff42aa577c99d86", +"54:orders_model_7.sourced": "efe9b5370341db1214ac6791", +"55:orders_model_11.has_model": "fcbcf165908dd18a9e49f7ff", +"56:orders_model_11.has_star": "fcbcf165908dd18a9e49f7ff", +"57:orders_model_11.edge_count": "5feceb66ffc86f38d952786c", +"58:orders_model_11.targeting": "6786f18f6ff42aa577c99d86", +"59:orders_model_11.sourced": "994b51789f15903e6e3ff4f7", +"5:orders_model_12.has_model": "b5bea41b6c623f7c09f1bf24", +"60:orders_model_14.has_model": "b5bea41b6c623f7c09f1bf24", +"61:orders_model_14.has_star": "fcbcf165908dd18a9e49f7ff", +"62:orders_model_14.edge_count": "d4735e3a265e16eee03f5971", +"63:orders_model_14.targeting": "994b51789f15903e6e3ff4f7", +"64:orders_model_14.sourced": "6786f18f6ff42aa577c99d86", +"65:orders_model_2.has_model": "fcbcf165908dd18a9e49f7ff", +"66:orders_model_2.has_star": "fcbcf165908dd18a9e49f7ff", +"67:orders_model_2.edge_count": "5feceb66ffc86f38d952786c", +"68:orders_model_2.targeting": "6786f18f6ff42aa577c99d86", +"69:orders_model_2.sourced": "6786f18f6ff42aa577c99d86", +"6:orders_model_12.has_star": "fcbcf165908dd18a9e49f7ff", +"70:orders_model_5.has_model": "b5bea41b6c623f7c09f1bf24", +"71:orders_model_5.has_star": "fcbcf165908dd18a9e49f7ff", +"72:orders_model_5.edge_count": "d4735e3a265e16eee03f5971", +"73:orders_model_5.targeting": "387649cf44d2ffb7009909a1", +"74:orders_model_5.sourced": "6786f18f6ff42aa577c99d86", +"75:orders_model_8.has_model": "b5bea41b6c623f7c09f1bf24", +"76:orders_model_8.has_star": "b5bea41b6c623f7c09f1bf24", +"77:orders_model_8.edge_count": "4b227777d4dd1fc61c6f884f", +"78:orders_model_8.targeting": "efe9b5370341db1214ac6791", +"79:orders_model_8.sourced": "6786f18f6ff42aa577c99d86", +"7:orders_model_12.edge_count": "d4735e3a265e16eee03f5971", +"80:models": "634a199b0204ba6c3ca102dc", +"81:edges": "5258bb66e465fbd07d87c222", +"8:orders_model_12.targeting": "8a14701822a8a3706d504b23", +"9:orders_model_12.sourced": "6786f18f6ff42aa577c99d86" +} +], +[ +"lineage", +{ +"0:orders_model_0.has_model": "b5bea41b6c623f7c09f1bf24", +"10:orders_model_15.has_model": "b5bea41b6c623f7c09f1bf24", +"11:orders_model_15.has_star": "fcbcf165908dd18a9e49f7ff", +"12:orders_model_15.edge_count": "4e07408562bedb8b60ce05c1", +"13:orders_model_15.targeting": "3a2211ec7f6ecf213884189f", +"14:orders_model_15.sourced": "6786f18f6ff42aa577c99d86", +"15:orders_model_3.has_model": "b5bea41b6c623f7c09f1bf24", +"16:orders_model_3.has_star": "fcbcf165908dd18a9e49f7ff", +"17:orders_model_3.edge_count": "d4735e3a265e16eee03f5971", +"18:orders_model_3.targeting": "5d4db6051418c956e0e9bf9f", +"19:orders_model_3.sourced": "67ac37eb58f45c8042ba79fb", +"1:orders_model_0.has_star": "b5bea41b6c623f7c09f1bf24", +"20:orders_model_6.has_model": "b5bea41b6c623f7c09f1bf24", +"21:orders_model_6.has_star": "fcbcf165908dd18a9e49f7ff", +"22:orders_model_6.edge_count": "4e07408562bedb8b60ce05c1", +"23:orders_model_6.targeting": "bba7433c100a9ca120f6fbcf", +"24:orders_model_6.sourced": "1883ac21741e29509968e6b0", +"25:orders_model_9.has_model": "b5bea41b6c623f7c09f1bf24", +"26:orders_model_9.has_star": "b5bea41b6c623f7c09f1bf24", +"27:orders_model_9.edge_count": "d4735e3a265e16eee03f5971", +"28:orders_model_9.targeting": "67ac37eb58f45c8042ba79fb", +"29:orders_model_9.sourced": "6786f18f6ff42aa577c99d86", +"2:orders_model_0.edge_count": "d4735e3a265e16eee03f5971", +"30:orders_model_1.has_model": "b5bea41b6c623f7c09f1bf24", +"31:orders_model_1.has_star": "b5bea41b6c623f7c09f1bf24", +"32:orders_model_1.edge_count": "4e07408562bedb8b60ce05c1", +"33:orders_model_1.targeting": "452427dd584527df4f8ece1d", +"34:orders_model_1.sourced": "3099535ea109c12832471665", +"35:orders_model_10.has_model": "b5bea41b6c623f7c09f1bf24", +"36:orders_model_10.has_star": "b5bea41b6c623f7c09f1bf24", +"37:orders_model_10.edge_count": "4e07408562bedb8b60ce05c1", +"38:orders_model_10.targeting": "6ce4efde8f1573118d43d489", +"39:orders_model_10.sourced": "6786f18f6ff42aa577c99d86", +"3:orders_model_0.targeting": "24786d0b1ed2268bbe02c10e", +"40:orders_model_13.has_model": "b5bea41b6c623f7c09f1bf24", +"41:orders_model_13.has_star": "b5bea41b6c623f7c09f1bf24", +"42:orders_model_13.edge_count": "4b227777d4dd1fc61c6f884f", +"43:orders_model_13.targeting": "15745747c1d507b3b5c6d94e", +"44:orders_model_13.sourced": "6786f18f6ff42aa577c99d86", +"45:orders_model_4.has_model": "b5bea41b6c623f7c09f1bf24", +"46:orders_model_4.has_star": "b5bea41b6c623f7c09f1bf24", +"47:orders_model_4.edge_count": "4b227777d4dd1fc61c6f884f", +"48:orders_model_4.targeting": "190d3318e6fbd9ae444edfd6", +"49:orders_model_4.sourced": "6786f18f6ff42aa577c99d86", +"4:orders_model_0.sourced": "75fb8b4ea541b83a96bb78aa", +"50:orders_model_7.has_model": "b5bea41b6c623f7c09f1bf24", +"51:orders_model_7.has_star": "fcbcf165908dd18a9e49f7ff", +"52:orders_model_7.edge_count": "19581e27de7ced00ff1ce50b", +"53:orders_model_7.targeting": "537db932e35c0fb59ac91164", +"54:orders_model_7.sourced": "6786f18f6ff42aa577c99d86", +"55:orders_model_11.has_model": "b5bea41b6c623f7c09f1bf24", +"56:orders_model_11.has_star": "fcbcf165908dd18a9e49f7ff", +"57:orders_model_11.edge_count": "6b86b273ff34fce19d6b804e", +"58:orders_model_11.targeting": "422c92f9dd61b2ef65dee3be", +"59:orders_model_11.sourced": "3a2211ec7f6ecf213884189f", +"5:orders_model_12.has_model": "b5bea41b6c623f7c09f1bf24", +"60:orders_model_14.has_model": "b5bea41b6c623f7c09f1bf24", +"61:orders_model_14.has_star": "fcbcf165908dd18a9e49f7ff", +"62:orders_model_14.edge_count": "d4735e3a265e16eee03f5971", +"63:orders_model_14.targeting": "c65a7937992d637d9dc783ca", +"64:orders_model_14.sourced": "6786f18f6ff42aa577c99d86", +"65:orders_model_2.has_model": "b5bea41b6c623f7c09f1bf24", +"66:orders_model_2.has_star": "fcbcf165908dd18a9e49f7ff", +"67:orders_model_2.edge_count": "6b86b273ff34fce19d6b804e", +"68:orders_model_2.targeting": "62f420101b911c5efeabdd8a", +"69:orders_model_2.sourced": "931996e30dd330a5cf09825c", +"6:orders_model_12.has_star": "fcbcf165908dd18a9e49f7ff", +"70:orders_model_5.has_model": "b5bea41b6c623f7c09f1bf24", +"71:orders_model_5.has_star": "fcbcf165908dd18a9e49f7ff", +"72:orders_model_5.edge_count": "d4735e3a265e16eee03f5971", +"73:orders_model_5.targeting": "9509b49ef34d9b478bf17b70", +"74:orders_model_5.sourced": "6786f18f6ff42aa577c99d86", +"75:orders_model_8.has_model": "b5bea41b6c623f7c09f1bf24", +"76:orders_model_8.has_star": "b5bea41b6c623f7c09f1bf24", +"77:orders_model_8.edge_count": "4b227777d4dd1fc61c6f884f", +"78:orders_model_8.targeting": "52ad3bd8074b30476404477a", +"79:orders_model_8.sourced": "6786f18f6ff42aa577c99d86", +"7:orders_model_12.edge_count": "d4735e3a265e16eee03f5971", +"80:models": "51075542f67bd94c29d3f0c4", +"81:edges": "bbe2efc481c2f6f64d4e62a1", +"8:orders_model_12.targeting": "7eb1a6cd5b907b1881d7b4cb", +"9:orders_model_12.sourced": "6786f18f6ff42aa577c99d86" +} +], +[ +"lineage", +{ +"0:orders_model_0.has_model": "fcbcf165908dd18a9e49f7ff", +"10:orders_model_15.has_model": "b5bea41b6c623f7c09f1bf24", +"11:orders_model_15.has_star": "fcbcf165908dd18a9e49f7ff", +"12:orders_model_15.edge_count": "4e07408562bedb8b60ce05c1", +"13:orders_model_15.targeting": "3a2211ec7f6ecf213884189f", +"14:orders_model_15.sourced": "6786f18f6ff42aa577c99d86", +"15:orders_model_3.has_model": "fcbcf165908dd18a9e49f7ff", +"16:orders_model_3.has_star": "fcbcf165908dd18a9e49f7ff", +"17:orders_model_3.edge_count": "5feceb66ffc86f38d952786c", +"18:orders_model_3.targeting": "6786f18f6ff42aa577c99d86", +"19:orders_model_3.sourced": "67ac37eb58f45c8042ba79fb", +"1:orders_model_0.has_star": "fcbcf165908dd18a9e49f7ff", +"20:orders_model_6.has_model": "b5bea41b6c623f7c09f1bf24", +"21:orders_model_6.has_star": "fcbcf165908dd18a9e49f7ff", +"22:orders_model_6.edge_count": "4e07408562bedb8b60ce05c1", +"23:orders_model_6.targeting": "bba7433c100a9ca120f6fbcf", +"24:orders_model_6.sourced": "1883ac21741e29509968e6b0", +"25:orders_model_9.has_model": "b5bea41b6c623f7c09f1bf24", +"26:orders_model_9.has_star": "b5bea41b6c623f7c09f1bf24", +"27:orders_model_9.edge_count": "d4735e3a265e16eee03f5971", +"28:orders_model_9.targeting": "67ac37eb58f45c8042ba79fb", +"29:orders_model_9.sourced": "6786f18f6ff42aa577c99d86", +"2:orders_model_0.edge_count": "5feceb66ffc86f38d952786c", +"30:orders_model_1.has_model": "b5bea41b6c623f7c09f1bf24", +"31:orders_model_1.has_star": "b5bea41b6c623f7c09f1bf24", +"32:orders_model_1.edge_count": "4e07408562bedb8b60ce05c1", +"33:orders_model_1.targeting": "452427dd584527df4f8ece1d", +"34:orders_model_1.sourced": "6786f18f6ff42aa577c99d86", +"35:orders_model_10.has_model": "b5bea41b6c623f7c09f1bf24", +"36:orders_model_10.has_star": "b5bea41b6c623f7c09f1bf24", +"37:orders_model_10.edge_count": "4e07408562bedb8b60ce05c1", +"38:orders_model_10.targeting": "6ce4efde8f1573118d43d489", +"39:orders_model_10.sourced": "6786f18f6ff42aa577c99d86", +"3:orders_model_0.targeting": "6786f18f6ff42aa577c99d86", +"40:orders_model_13.has_model": "fcbcf165908dd18a9e49f7ff", +"41:orders_model_13.has_star": "fcbcf165908dd18a9e49f7ff", +"42:orders_model_13.edge_count": "5feceb66ffc86f38d952786c", +"43:orders_model_13.targeting": "6786f18f6ff42aa577c99d86", +"44:orders_model_13.sourced": "6786f18f6ff42aa577c99d86", +"45:orders_model_4.has_model": "fcbcf165908dd18a9e49f7ff", +"46:orders_model_4.has_star": "fcbcf165908dd18a9e49f7ff", +"47:orders_model_4.edge_count": "5feceb66ffc86f38d952786c", +"48:orders_model_4.targeting": "6786f18f6ff42aa577c99d86", +"49:orders_model_4.sourced": "6786f18f6ff42aa577c99d86", +"4:orders_model_0.sourced": "75fb8b4ea541b83a96bb78aa", +"50:orders_model_7.has_model": "fcbcf165908dd18a9e49f7ff", +"51:orders_model_7.has_star": "fcbcf165908dd18a9e49f7ff", +"52:orders_model_7.edge_count": "5feceb66ffc86f38d952786c", +"53:orders_model_7.targeting": "6786f18f6ff42aa577c99d86", +"54:orders_model_7.sourced": "6786f18f6ff42aa577c99d86", +"55:orders_model_11.has_model": "b5bea41b6c623f7c09f1bf24", +"56:orders_model_11.has_star": "fcbcf165908dd18a9e49f7ff", +"57:orders_model_11.edge_count": "6b86b273ff34fce19d6b804e", +"58:orders_model_11.targeting": "422c92f9dd61b2ef65dee3be", +"59:orders_model_11.sourced": "3a2211ec7f6ecf213884189f", +"5:orders_model_12.has_model": "b5bea41b6c623f7c09f1bf24", +"60:orders_model_14.has_model": "fcbcf165908dd18a9e49f7ff", +"61:orders_model_14.has_star": "fcbcf165908dd18a9e49f7ff", +"62:orders_model_14.edge_count": "5feceb66ffc86f38d952786c", +"63:orders_model_14.targeting": "6786f18f6ff42aa577c99d86", +"64:orders_model_14.sourced": "6786f18f6ff42aa577c99d86", +"65:orders_model_2.has_model": "fcbcf165908dd18a9e49f7ff", +"66:orders_model_2.has_star": "fcbcf165908dd18a9e49f7ff", +"67:orders_model_2.edge_count": "5feceb66ffc86f38d952786c", +"68:orders_model_2.targeting": "6786f18f6ff42aa577c99d86", +"69:orders_model_2.sourced": "6786f18f6ff42aa577c99d86", +"6:orders_model_12.has_star": "fcbcf165908dd18a9e49f7ff", +"70:orders_model_5.has_model": "fcbcf165908dd18a9e49f7ff", +"71:orders_model_5.has_star": "fcbcf165908dd18a9e49f7ff", +"72:orders_model_5.edge_count": "5feceb66ffc86f38d952786c", +"73:orders_model_5.targeting": "6786f18f6ff42aa577c99d86", +"74:orders_model_5.sourced": "6786f18f6ff42aa577c99d86", +"75:orders_model_8.has_model": "b5bea41b6c623f7c09f1bf24", +"76:orders_model_8.has_star": "b5bea41b6c623f7c09f1bf24", +"77:orders_model_8.edge_count": "4b227777d4dd1fc61c6f884f", +"78:orders_model_8.targeting": "52ad3bd8074b30476404477a", +"79:orders_model_8.sourced": "6786f18f6ff42aa577c99d86", +"7:orders_model_12.edge_count": "d4735e3a265e16eee03f5971", +"80:models": "162bd27b0ba0371264b7f846", +"81:edges": "7f0f5f6e0554b4505652d3aa", +"8:orders_model_12.targeting": "7eb1a6cd5b907b1881d7b4cb", +"9:orders_model_12.sourced": "6786f18f6ff42aa577c99d86" +} +], +[ +"lineage", +{ +"0:orders_model_0.has_model": "b5bea41b6c623f7c09f1bf24", +"10:orders_model_15.has_model": "b5bea41b6c623f7c09f1bf24", +"11:orders_model_15.has_star": "fcbcf165908dd18a9e49f7ff", +"12:orders_model_15.edge_count": "4e07408562bedb8b60ce05c1", +"13:orders_model_15.targeting": "3a2211ec7f6ecf213884189f", +"14:orders_model_15.sourced": "6786f18f6ff42aa577c99d86", +"15:orders_model_3.has_model": "b5bea41b6c623f7c09f1bf24", +"16:orders_model_3.has_star": "fcbcf165908dd18a9e49f7ff", +"17:orders_model_3.edge_count": "d4735e3a265e16eee03f5971", +"18:orders_model_3.targeting": "5d4db6051418c956e0e9bf9f", +"19:orders_model_3.sourced": "67ac37eb58f45c8042ba79fb", +"1:orders_model_0.has_star": "b5bea41b6c623f7c09f1bf24", +"20:orders_model_6.has_model": "b5bea41b6c623f7c09f1bf24", +"21:orders_model_6.has_star": "fcbcf165908dd18a9e49f7ff", +"22:orders_model_6.edge_count": "4e07408562bedb8b60ce05c1", +"23:orders_model_6.targeting": "bba7433c100a9ca120f6fbcf", +"24:orders_model_6.sourced": "1883ac21741e29509968e6b0", +"25:orders_model_9.has_model": "b5bea41b6c623f7c09f1bf24", +"26:orders_model_9.has_star": "b5bea41b6c623f7c09f1bf24", +"27:orders_model_9.edge_count": "d4735e3a265e16eee03f5971", +"28:orders_model_9.targeting": "67ac37eb58f45c8042ba79fb", +"29:orders_model_9.sourced": "6786f18f6ff42aa577c99d86", +"2:orders_model_0.edge_count": "d4735e3a265e16eee03f5971", +"30:orders_model_1.has_model": "b5bea41b6c623f7c09f1bf24", +"31:orders_model_1.has_star": "b5bea41b6c623f7c09f1bf24", +"32:orders_model_1.edge_count": "4e07408562bedb8b60ce05c1", +"33:orders_model_1.targeting": "452427dd584527df4f8ece1d", +"34:orders_model_1.sourced": "3099535ea109c12832471665", +"35:orders_model_10.has_model": "b5bea41b6c623f7c09f1bf24", +"36:orders_model_10.has_star": "b5bea41b6c623f7c09f1bf24", +"37:orders_model_10.edge_count": "4e07408562bedb8b60ce05c1", +"38:orders_model_10.targeting": "6ce4efde8f1573118d43d489", +"39:orders_model_10.sourced": "6786f18f6ff42aa577c99d86", +"3:orders_model_0.targeting": "24786d0b1ed2268bbe02c10e", +"40:orders_model_13.has_model": "b5bea41b6c623f7c09f1bf24", +"41:orders_model_13.has_star": "b5bea41b6c623f7c09f1bf24", +"42:orders_model_13.edge_count": "4b227777d4dd1fc61c6f884f", +"43:orders_model_13.targeting": "15745747c1d507b3b5c6d94e", +"44:orders_model_13.sourced": "6786f18f6ff42aa577c99d86", +"45:orders_model_4.has_model": "b5bea41b6c623f7c09f1bf24", +"46:orders_model_4.has_star": "b5bea41b6c623f7c09f1bf24", +"47:orders_model_4.edge_count": "4b227777d4dd1fc61c6f884f", +"48:orders_model_4.targeting": "190d3318e6fbd9ae444edfd6", +"49:orders_model_4.sourced": "6786f18f6ff42aa577c99d86", +"4:orders_model_0.sourced": "75fb8b4ea541b83a96bb78aa", +"50:orders_model_7.has_model": "b5bea41b6c623f7c09f1bf24", +"51:orders_model_7.has_star": "fcbcf165908dd18a9e49f7ff", +"52:orders_model_7.edge_count": "19581e27de7ced00ff1ce50b", +"53:orders_model_7.targeting": "537db932e35c0fb59ac91164", +"54:orders_model_7.sourced": "6786f18f6ff42aa577c99d86", +"55:orders_model_11.has_model": "b5bea41b6c623f7c09f1bf24", +"56:orders_model_11.has_star": "fcbcf165908dd18a9e49f7ff", +"57:orders_model_11.edge_count": "6b86b273ff34fce19d6b804e", +"58:orders_model_11.targeting": "422c92f9dd61b2ef65dee3be", +"59:orders_model_11.sourced": "3a2211ec7f6ecf213884189f", +"5:orders_model_12.has_model": "b5bea41b6c623f7c09f1bf24", +"60:orders_model_14.has_model": "b5bea41b6c623f7c09f1bf24", +"61:orders_model_14.has_star": "fcbcf165908dd18a9e49f7ff", +"62:orders_model_14.edge_count": "d4735e3a265e16eee03f5971", +"63:orders_model_14.targeting": "c65a7937992d637d9dc783ca", +"64:orders_model_14.sourced": "6786f18f6ff42aa577c99d86", +"65:orders_model_2.has_model": "b5bea41b6c623f7c09f1bf24", +"66:orders_model_2.has_star": "fcbcf165908dd18a9e49f7ff", +"67:orders_model_2.edge_count": "6b86b273ff34fce19d6b804e", +"68:orders_model_2.targeting": "62f420101b911c5efeabdd8a", +"69:orders_model_2.sourced": "931996e30dd330a5cf09825c", +"6:orders_model_12.has_star": "fcbcf165908dd18a9e49f7ff", +"70:orders_model_5.has_model": "b5bea41b6c623f7c09f1bf24", +"71:orders_model_5.has_star": "fcbcf165908dd18a9e49f7ff", +"72:orders_model_5.edge_count": "d4735e3a265e16eee03f5971", +"73:orders_model_5.targeting": "9509b49ef34d9b478bf17b70", +"74:orders_model_5.sourced": "6786f18f6ff42aa577c99d86", +"75:orders_model_8.has_model": "b5bea41b6c623f7c09f1bf24", +"76:orders_model_8.has_star": "b5bea41b6c623f7c09f1bf24", +"77:orders_model_8.edge_count": "4b227777d4dd1fc61c6f884f", +"78:orders_model_8.targeting": "52ad3bd8074b30476404477a", +"79:orders_model_8.sourced": "6786f18f6ff42aa577c99d86", +"7:orders_model_12.edge_count": "d4735e3a265e16eee03f5971", +"80:models": "51075542f67bd94c29d3f0c4", +"81:edges": "bbe2efc481c2f6f64d4e62a1", +"8:orders_model_12.targeting": "7eb1a6cd5b907b1881d7b4cb", +"9:orders_model_12.sourced": "6786f18f6ff42aa577c99d86" +} +], +[ +"lineage", +{ +"0:orders_model_0.has_model": "fcbcf165908dd18a9e49f7ff", +"10:orders_model_15.has_model": "b5bea41b6c623f7c09f1bf24", +"11:orders_model_15.has_star": "fcbcf165908dd18a9e49f7ff", +"12:orders_model_15.edge_count": "4e07408562bedb8b60ce05c1", +"13:orders_model_15.targeting": "3a2211ec7f6ecf213884189f", +"14:orders_model_15.sourced": "6786f18f6ff42aa577c99d86", +"15:orders_model_3.has_model": "fcbcf165908dd18a9e49f7ff", +"16:orders_model_3.has_star": "fcbcf165908dd18a9e49f7ff", +"17:orders_model_3.edge_count": "5feceb66ffc86f38d952786c", +"18:orders_model_3.targeting": "6786f18f6ff42aa577c99d86", +"19:orders_model_3.sourced": "67ac37eb58f45c8042ba79fb", +"1:orders_model_0.has_star": "fcbcf165908dd18a9e49f7ff", +"20:orders_model_6.has_model": "b5bea41b6c623f7c09f1bf24", +"21:orders_model_6.has_star": "fcbcf165908dd18a9e49f7ff", +"22:orders_model_6.edge_count": "4e07408562bedb8b60ce05c1", +"23:orders_model_6.targeting": "bba7433c100a9ca120f6fbcf", +"24:orders_model_6.sourced": "1883ac21741e29509968e6b0", +"25:orders_model_9.has_model": "b5bea41b6c623f7c09f1bf24", +"26:orders_model_9.has_star": "b5bea41b6c623f7c09f1bf24", +"27:orders_model_9.edge_count": "d4735e3a265e16eee03f5971", +"28:orders_model_9.targeting": "67ac37eb58f45c8042ba79fb", +"29:orders_model_9.sourced": "6786f18f6ff42aa577c99d86", +"2:orders_model_0.edge_count": "5feceb66ffc86f38d952786c", +"30:orders_model_1.has_model": "b5bea41b6c623f7c09f1bf24", +"31:orders_model_1.has_star": "b5bea41b6c623f7c09f1bf24", +"32:orders_model_1.edge_count": "4e07408562bedb8b60ce05c1", +"33:orders_model_1.targeting": "452427dd584527df4f8ece1d", +"34:orders_model_1.sourced": "6786f18f6ff42aa577c99d86", +"35:orders_model_10.has_model": "b5bea41b6c623f7c09f1bf24", +"36:orders_model_10.has_star": "b5bea41b6c623f7c09f1bf24", +"37:orders_model_10.edge_count": "4e07408562bedb8b60ce05c1", +"38:orders_model_10.targeting": "6ce4efde8f1573118d43d489", +"39:orders_model_10.sourced": "6786f18f6ff42aa577c99d86", +"3:orders_model_0.targeting": "6786f18f6ff42aa577c99d86", +"40:orders_model_13.has_model": "fcbcf165908dd18a9e49f7ff", +"41:orders_model_13.has_star": "fcbcf165908dd18a9e49f7ff", +"42:orders_model_13.edge_count": "5feceb66ffc86f38d952786c", +"43:orders_model_13.targeting": "6786f18f6ff42aa577c99d86", +"44:orders_model_13.sourced": "6786f18f6ff42aa577c99d86", +"45:orders_model_4.has_model": "fcbcf165908dd18a9e49f7ff", +"46:orders_model_4.has_star": "fcbcf165908dd18a9e49f7ff", +"47:orders_model_4.edge_count": "5feceb66ffc86f38d952786c", +"48:orders_model_4.targeting": "6786f18f6ff42aa577c99d86", +"49:orders_model_4.sourced": "6786f18f6ff42aa577c99d86", +"4:orders_model_0.sourced": "75fb8b4ea541b83a96bb78aa", +"50:orders_model_7.has_model": "fcbcf165908dd18a9e49f7ff", +"51:orders_model_7.has_star": "fcbcf165908dd18a9e49f7ff", +"52:orders_model_7.edge_count": "5feceb66ffc86f38d952786c", +"53:orders_model_7.targeting": "6786f18f6ff42aa577c99d86", +"54:orders_model_7.sourced": "6786f18f6ff42aa577c99d86", +"55:orders_model_11.has_model": "b5bea41b6c623f7c09f1bf24", +"56:orders_model_11.has_star": "fcbcf165908dd18a9e49f7ff", +"57:orders_model_11.edge_count": "6b86b273ff34fce19d6b804e", +"58:orders_model_11.targeting": "422c92f9dd61b2ef65dee3be", +"59:orders_model_11.sourced": "3a2211ec7f6ecf213884189f", +"5:orders_model_12.has_model": "b5bea41b6c623f7c09f1bf24", +"60:orders_model_14.has_model": "fcbcf165908dd18a9e49f7ff", +"61:orders_model_14.has_star": "fcbcf165908dd18a9e49f7ff", +"62:orders_model_14.edge_count": "5feceb66ffc86f38d952786c", +"63:orders_model_14.targeting": "6786f18f6ff42aa577c99d86", +"64:orders_model_14.sourced": "6786f18f6ff42aa577c99d86", +"65:orders_model_2.has_model": "fcbcf165908dd18a9e49f7ff", +"66:orders_model_2.has_star": "fcbcf165908dd18a9e49f7ff", +"67:orders_model_2.edge_count": "5feceb66ffc86f38d952786c", +"68:orders_model_2.targeting": "6786f18f6ff42aa577c99d86", +"69:orders_model_2.sourced": "6786f18f6ff42aa577c99d86", +"6:orders_model_12.has_star": "fcbcf165908dd18a9e49f7ff", +"70:orders_model_5.has_model": "fcbcf165908dd18a9e49f7ff", +"71:orders_model_5.has_star": "fcbcf165908dd18a9e49f7ff", +"72:orders_model_5.edge_count": "5feceb66ffc86f38d952786c", +"73:orders_model_5.targeting": "6786f18f6ff42aa577c99d86", +"74:orders_model_5.sourced": "6786f18f6ff42aa577c99d86", +"75:orders_model_8.has_model": "b5bea41b6c623f7c09f1bf24", +"76:orders_model_8.has_star": "b5bea41b6c623f7c09f1bf24", +"77:orders_model_8.edge_count": "4b227777d4dd1fc61c6f884f", +"78:orders_model_8.targeting": "52ad3bd8074b30476404477a", +"79:orders_model_8.sourced": "6786f18f6ff42aa577c99d86", +"7:orders_model_12.edge_count": "d4735e3a265e16eee03f5971", +"80:models": "162bd27b0ba0371264b7f846", +"81:edges": "7f0f5f6e0554b4505652d3aa", +"8:orders_model_12.targeting": "7eb1a6cd5b907b1881d7b4cb", +"9:orders_model_12.sourced": "6786f18f6ff42aa577c99d86" +} +], +[ +"lineage", +{ +"0:orders_model_0.has_model": "b5bea41b6c623f7c09f1bf24", +"10:orders_model_15.has_model": "b5bea41b6c623f7c09f1bf24", +"11:orders_model_15.has_star": "fcbcf165908dd18a9e49f7ff", +"12:orders_model_15.edge_count": "4e07408562bedb8b60ce05c1", +"13:orders_model_15.targeting": "3a2211ec7f6ecf213884189f", +"14:orders_model_15.sourced": "6786f18f6ff42aa577c99d86", +"15:orders_model_3.has_model": "b5bea41b6c623f7c09f1bf24", +"16:orders_model_3.has_star": "fcbcf165908dd18a9e49f7ff", +"17:orders_model_3.edge_count": "d4735e3a265e16eee03f5971", +"18:orders_model_3.targeting": "5d4db6051418c956e0e9bf9f", +"19:orders_model_3.sourced": "67ac37eb58f45c8042ba79fb", +"1:orders_model_0.has_star": "b5bea41b6c623f7c09f1bf24", +"20:orders_model_6.has_model": "b5bea41b6c623f7c09f1bf24", +"21:orders_model_6.has_star": "fcbcf165908dd18a9e49f7ff", +"22:orders_model_6.edge_count": "4e07408562bedb8b60ce05c1", +"23:orders_model_6.targeting": "bba7433c100a9ca120f6fbcf", +"24:orders_model_6.sourced": "1883ac21741e29509968e6b0", +"25:orders_model_9.has_model": "b5bea41b6c623f7c09f1bf24", +"26:orders_model_9.has_star": "b5bea41b6c623f7c09f1bf24", +"27:orders_model_9.edge_count": "d4735e3a265e16eee03f5971", +"28:orders_model_9.targeting": "67ac37eb58f45c8042ba79fb", +"29:orders_model_9.sourced": "6786f18f6ff42aa577c99d86", +"2:orders_model_0.edge_count": "d4735e3a265e16eee03f5971", +"30:orders_model_1.has_model": "b5bea41b6c623f7c09f1bf24", +"31:orders_model_1.has_star": "b5bea41b6c623f7c09f1bf24", +"32:orders_model_1.edge_count": "4e07408562bedb8b60ce05c1", +"33:orders_model_1.targeting": "452427dd584527df4f8ece1d", +"34:orders_model_1.sourced": "3099535ea109c12832471665", +"35:orders_model_10.has_model": "b5bea41b6c623f7c09f1bf24", +"36:orders_model_10.has_star": "b5bea41b6c623f7c09f1bf24", +"37:orders_model_10.edge_count": "4e07408562bedb8b60ce05c1", +"38:orders_model_10.targeting": "6ce4efde8f1573118d43d489", +"39:orders_model_10.sourced": "6786f18f6ff42aa577c99d86", +"3:orders_model_0.targeting": "24786d0b1ed2268bbe02c10e", +"40:orders_model_13.has_model": "b5bea41b6c623f7c09f1bf24", +"41:orders_model_13.has_star": "b5bea41b6c623f7c09f1bf24", +"42:orders_model_13.edge_count": "4b227777d4dd1fc61c6f884f", +"43:orders_model_13.targeting": "15745747c1d507b3b5c6d94e", +"44:orders_model_13.sourced": "6786f18f6ff42aa577c99d86", +"45:orders_model_4.has_model": "b5bea41b6c623f7c09f1bf24", +"46:orders_model_4.has_star": "b5bea41b6c623f7c09f1bf24", +"47:orders_model_4.edge_count": "4b227777d4dd1fc61c6f884f", +"48:orders_model_4.targeting": "190d3318e6fbd9ae444edfd6", +"49:orders_model_4.sourced": "6786f18f6ff42aa577c99d86", +"4:orders_model_0.sourced": "75fb8b4ea541b83a96bb78aa", +"50:orders_model_7.has_model": "b5bea41b6c623f7c09f1bf24", +"51:orders_model_7.has_star": "fcbcf165908dd18a9e49f7ff", +"52:orders_model_7.edge_count": "19581e27de7ced00ff1ce50b", +"53:orders_model_7.targeting": "537db932e35c0fb59ac91164", +"54:orders_model_7.sourced": "6786f18f6ff42aa577c99d86", +"55:orders_model_11.has_model": "b5bea41b6c623f7c09f1bf24", +"56:orders_model_11.has_star": "fcbcf165908dd18a9e49f7ff", +"57:orders_model_11.edge_count": "6b86b273ff34fce19d6b804e", +"58:orders_model_11.targeting": "422c92f9dd61b2ef65dee3be", +"59:orders_model_11.sourced": "3a2211ec7f6ecf213884189f", +"5:orders_model_12.has_model": "b5bea41b6c623f7c09f1bf24", +"60:orders_model_14.has_model": "b5bea41b6c623f7c09f1bf24", +"61:orders_model_14.has_star": "fcbcf165908dd18a9e49f7ff", +"62:orders_model_14.edge_count": "d4735e3a265e16eee03f5971", +"63:orders_model_14.targeting": "c65a7937992d637d9dc783ca", +"64:orders_model_14.sourced": "6786f18f6ff42aa577c99d86", +"65:orders_model_2.has_model": "b5bea41b6c623f7c09f1bf24", +"66:orders_model_2.has_star": "fcbcf165908dd18a9e49f7ff", +"67:orders_model_2.edge_count": "6b86b273ff34fce19d6b804e", +"68:orders_model_2.targeting": "62f420101b911c5efeabdd8a", +"69:orders_model_2.sourced": "931996e30dd330a5cf09825c", +"6:orders_model_12.has_star": "fcbcf165908dd18a9e49f7ff", +"70:orders_model_5.has_model": "b5bea41b6c623f7c09f1bf24", +"71:orders_model_5.has_star": "fcbcf165908dd18a9e49f7ff", +"72:orders_model_5.edge_count": "d4735e3a265e16eee03f5971", +"73:orders_model_5.targeting": "9509b49ef34d9b478bf17b70", +"74:orders_model_5.sourced": "6786f18f6ff42aa577c99d86", +"75:orders_model_8.has_model": "b5bea41b6c623f7c09f1bf24", +"76:orders_model_8.has_star": "b5bea41b6c623f7c09f1bf24", +"77:orders_model_8.edge_count": "4b227777d4dd1fc61c6f884f", +"78:orders_model_8.targeting": "52ad3bd8074b30476404477a", +"79:orders_model_8.sourced": "6786f18f6ff42aa577c99d86", +"7:orders_model_12.edge_count": "d4735e3a265e16eee03f5971", +"80:models": "51075542f67bd94c29d3f0c4", +"81:edges": "bbe2efc481c2f6f64d4e62a1", +"8:orders_model_12.targeting": "7eb1a6cd5b907b1881d7b4cb", +"9:orders_model_12.sourced": "6786f18f6ff42aa577c99d86" +} +], +[ +"lineage", +{ +"0:orders_model_0.has_model": "fcbcf165908dd18a9e49f7ff", +"10:orders_model_15.has_model": "b5bea41b6c623f7c09f1bf24", +"11:orders_model_15.has_star": "fcbcf165908dd18a9e49f7ff", +"12:orders_model_15.edge_count": "4e07408562bedb8b60ce05c1", +"13:orders_model_15.targeting": "3a2211ec7f6ecf213884189f", +"14:orders_model_15.sourced": "6786f18f6ff42aa577c99d86", +"15:orders_model_3.has_model": "fcbcf165908dd18a9e49f7ff", +"16:orders_model_3.has_star": "fcbcf165908dd18a9e49f7ff", +"17:orders_model_3.edge_count": "5feceb66ffc86f38d952786c", +"18:orders_model_3.targeting": "6786f18f6ff42aa577c99d86", +"19:orders_model_3.sourced": "67ac37eb58f45c8042ba79fb", +"1:orders_model_0.has_star": "fcbcf165908dd18a9e49f7ff", +"20:orders_model_6.has_model": "b5bea41b6c623f7c09f1bf24", +"21:orders_model_6.has_star": "fcbcf165908dd18a9e49f7ff", +"22:orders_model_6.edge_count": "4e07408562bedb8b60ce05c1", +"23:orders_model_6.targeting": "bba7433c100a9ca120f6fbcf", +"24:orders_model_6.sourced": "1883ac21741e29509968e6b0", +"25:orders_model_9.has_model": "b5bea41b6c623f7c09f1bf24", +"26:orders_model_9.has_star": "b5bea41b6c623f7c09f1bf24", +"27:orders_model_9.edge_count": "d4735e3a265e16eee03f5971", +"28:orders_model_9.targeting": "67ac37eb58f45c8042ba79fb", +"29:orders_model_9.sourced": "6786f18f6ff42aa577c99d86", +"2:orders_model_0.edge_count": "5feceb66ffc86f38d952786c", +"30:orders_model_1.has_model": "b5bea41b6c623f7c09f1bf24", +"31:orders_model_1.has_star": "b5bea41b6c623f7c09f1bf24", +"32:orders_model_1.edge_count": "4e07408562bedb8b60ce05c1", +"33:orders_model_1.targeting": "452427dd584527df4f8ece1d", +"34:orders_model_1.sourced": "6786f18f6ff42aa577c99d86", +"35:orders_model_10.has_model": "b5bea41b6c623f7c09f1bf24", +"36:orders_model_10.has_star": "b5bea41b6c623f7c09f1bf24", +"37:orders_model_10.edge_count": "4e07408562bedb8b60ce05c1", +"38:orders_model_10.targeting": "6ce4efde8f1573118d43d489", +"39:orders_model_10.sourced": "6786f18f6ff42aa577c99d86", +"3:orders_model_0.targeting": "6786f18f6ff42aa577c99d86", +"40:orders_model_13.has_model": "fcbcf165908dd18a9e49f7ff", +"41:orders_model_13.has_star": "fcbcf165908dd18a9e49f7ff", +"42:orders_model_13.edge_count": "5feceb66ffc86f38d952786c", +"43:orders_model_13.targeting": "6786f18f6ff42aa577c99d86", +"44:orders_model_13.sourced": "6786f18f6ff42aa577c99d86", +"45:orders_model_4.has_model": "fcbcf165908dd18a9e49f7ff", +"46:orders_model_4.has_star": "fcbcf165908dd18a9e49f7ff", +"47:orders_model_4.edge_count": "5feceb66ffc86f38d952786c", +"48:orders_model_4.targeting": "6786f18f6ff42aa577c99d86", +"49:orders_model_4.sourced": "6786f18f6ff42aa577c99d86", +"4:orders_model_0.sourced": "75fb8b4ea541b83a96bb78aa", +"50:orders_model_7.has_model": "fcbcf165908dd18a9e49f7ff", +"51:orders_model_7.has_star": "fcbcf165908dd18a9e49f7ff", +"52:orders_model_7.edge_count": "5feceb66ffc86f38d952786c", +"53:orders_model_7.targeting": "6786f18f6ff42aa577c99d86", +"54:orders_model_7.sourced": "6786f18f6ff42aa577c99d86", +"55:orders_model_11.has_model": "b5bea41b6c623f7c09f1bf24", +"56:orders_model_11.has_star": "fcbcf165908dd18a9e49f7ff", +"57:orders_model_11.edge_count": "6b86b273ff34fce19d6b804e", +"58:orders_model_11.targeting": "422c92f9dd61b2ef65dee3be", +"59:orders_model_11.sourced": "3a2211ec7f6ecf213884189f", +"5:orders_model_12.has_model": "b5bea41b6c623f7c09f1bf24", +"60:orders_model_14.has_model": "fcbcf165908dd18a9e49f7ff", +"61:orders_model_14.has_star": "fcbcf165908dd18a9e49f7ff", +"62:orders_model_14.edge_count": "5feceb66ffc86f38d952786c", +"63:orders_model_14.targeting": "6786f18f6ff42aa577c99d86", +"64:orders_model_14.sourced": "6786f18f6ff42aa577c99d86", +"65:orders_model_2.has_model": "fcbcf165908dd18a9e49f7ff", +"66:orders_model_2.has_star": "fcbcf165908dd18a9e49f7ff", +"67:orders_model_2.edge_count": "5feceb66ffc86f38d952786c", +"68:orders_model_2.targeting": "6786f18f6ff42aa577c99d86", +"69:orders_model_2.sourced": "6786f18f6ff42aa577c99d86", +"6:orders_model_12.has_star": "fcbcf165908dd18a9e49f7ff", +"70:orders_model_5.has_model": "fcbcf165908dd18a9e49f7ff", +"71:orders_model_5.has_star": "fcbcf165908dd18a9e49f7ff", +"72:orders_model_5.edge_count": "5feceb66ffc86f38d952786c", +"73:orders_model_5.targeting": "6786f18f6ff42aa577c99d86", +"74:orders_model_5.sourced": "6786f18f6ff42aa577c99d86", +"75:orders_model_8.has_model": "b5bea41b6c623f7c09f1bf24", +"76:orders_model_8.has_star": "b5bea41b6c623f7c09f1bf24", +"77:orders_model_8.edge_count": "4b227777d4dd1fc61c6f884f", +"78:orders_model_8.targeting": "52ad3bd8074b30476404477a", +"79:orders_model_8.sourced": "6786f18f6ff42aa577c99d86", +"7:orders_model_12.edge_count": "d4735e3a265e16eee03f5971", +"80:models": "162bd27b0ba0371264b7f846", +"81:edges": "7f0f5f6e0554b4505652d3aa", +"8:orders_model_12.targeting": "7eb1a6cd5b907b1881d7b4cb", +"9:orders_model_12.sourced": "6786f18f6ff42aa577c99d86" +} +], +[ +"lineage", +{ +"0:orders_model_0.has_model": "b5bea41b6c623f7c09f1bf24", +"10:orders_model_15.has_model": "b5bea41b6c623f7c09f1bf24", +"11:orders_model_15.has_star": "fcbcf165908dd18a9e49f7ff", +"12:orders_model_15.edge_count": "4e07408562bedb8b60ce05c1", +"13:orders_model_15.targeting": "3a2211ec7f6ecf213884189f", +"14:orders_model_15.sourced": "6786f18f6ff42aa577c99d86", +"15:orders_model_3.has_model": "b5bea41b6c623f7c09f1bf24", +"16:orders_model_3.has_star": "fcbcf165908dd18a9e49f7ff", +"17:orders_model_3.edge_count": "d4735e3a265e16eee03f5971", +"18:orders_model_3.targeting": "5d4db6051418c956e0e9bf9f", +"19:orders_model_3.sourced": "67ac37eb58f45c8042ba79fb", +"1:orders_model_0.has_star": "b5bea41b6c623f7c09f1bf24", +"20:orders_model_6.has_model": "b5bea41b6c623f7c09f1bf24", +"21:orders_model_6.has_star": "fcbcf165908dd18a9e49f7ff", +"22:orders_model_6.edge_count": "4e07408562bedb8b60ce05c1", +"23:orders_model_6.targeting": "bba7433c100a9ca120f6fbcf", +"24:orders_model_6.sourced": "1883ac21741e29509968e6b0", +"25:orders_model_9.has_model": "b5bea41b6c623f7c09f1bf24", +"26:orders_model_9.has_star": "b5bea41b6c623f7c09f1bf24", +"27:orders_model_9.edge_count": "d4735e3a265e16eee03f5971", +"28:orders_model_9.targeting": "67ac37eb58f45c8042ba79fb", +"29:orders_model_9.sourced": "6786f18f6ff42aa577c99d86", +"2:orders_model_0.edge_count": "d4735e3a265e16eee03f5971", +"30:orders_model_1.has_model": "b5bea41b6c623f7c09f1bf24", +"31:orders_model_1.has_star": "b5bea41b6c623f7c09f1bf24", +"32:orders_model_1.edge_count": "4e07408562bedb8b60ce05c1", +"33:orders_model_1.targeting": "452427dd584527df4f8ece1d", +"34:orders_model_1.sourced": "3099535ea109c12832471665", +"35:orders_model_10.has_model": "b5bea41b6c623f7c09f1bf24", +"36:orders_model_10.has_star": "b5bea41b6c623f7c09f1bf24", +"37:orders_model_10.edge_count": "4e07408562bedb8b60ce05c1", +"38:orders_model_10.targeting": "6ce4efde8f1573118d43d489", +"39:orders_model_10.sourced": "6786f18f6ff42aa577c99d86", +"3:orders_model_0.targeting": "24786d0b1ed2268bbe02c10e", +"40:orders_model_13.has_model": "b5bea41b6c623f7c09f1bf24", +"41:orders_model_13.has_star": "b5bea41b6c623f7c09f1bf24", +"42:orders_model_13.edge_count": "4b227777d4dd1fc61c6f884f", +"43:orders_model_13.targeting": "15745747c1d507b3b5c6d94e", +"44:orders_model_13.sourced": "6786f18f6ff42aa577c99d86", +"45:orders_model_4.has_model": "b5bea41b6c623f7c09f1bf24", +"46:orders_model_4.has_star": "b5bea41b6c623f7c09f1bf24", +"47:orders_model_4.edge_count": "4b227777d4dd1fc61c6f884f", +"48:orders_model_4.targeting": "190d3318e6fbd9ae444edfd6", +"49:orders_model_4.sourced": "6786f18f6ff42aa577c99d86", +"4:orders_model_0.sourced": "75fb8b4ea541b83a96bb78aa", +"50:orders_model_7.has_model": "b5bea41b6c623f7c09f1bf24", +"51:orders_model_7.has_star": "fcbcf165908dd18a9e49f7ff", +"52:orders_model_7.edge_count": "19581e27de7ced00ff1ce50b", +"53:orders_model_7.targeting": "537db932e35c0fb59ac91164", +"54:orders_model_7.sourced": "6786f18f6ff42aa577c99d86", +"55:orders_model_11.has_model": "b5bea41b6c623f7c09f1bf24", +"56:orders_model_11.has_star": "fcbcf165908dd18a9e49f7ff", +"57:orders_model_11.edge_count": "6b86b273ff34fce19d6b804e", +"58:orders_model_11.targeting": "422c92f9dd61b2ef65dee3be", +"59:orders_model_11.sourced": "3a2211ec7f6ecf213884189f", +"5:orders_model_12.has_model": "b5bea41b6c623f7c09f1bf24", +"60:orders_model_14.has_model": "b5bea41b6c623f7c09f1bf24", +"61:orders_model_14.has_star": "fcbcf165908dd18a9e49f7ff", +"62:orders_model_14.edge_count": "d4735e3a265e16eee03f5971", +"63:orders_model_14.targeting": "c65a7937992d637d9dc783ca", +"64:orders_model_14.sourced": "6786f18f6ff42aa577c99d86", +"65:orders_model_2.has_model": "b5bea41b6c623f7c09f1bf24", +"66:orders_model_2.has_star": "fcbcf165908dd18a9e49f7ff", +"67:orders_model_2.edge_count": "6b86b273ff34fce19d6b804e", +"68:orders_model_2.targeting": "62f420101b911c5efeabdd8a", +"69:orders_model_2.sourced": "931996e30dd330a5cf09825c", +"6:orders_model_12.has_star": "fcbcf165908dd18a9e49f7ff", +"70:orders_model_5.has_model": "b5bea41b6c623f7c09f1bf24", +"71:orders_model_5.has_star": "fcbcf165908dd18a9e49f7ff", +"72:orders_model_5.edge_count": "d4735e3a265e16eee03f5971", +"73:orders_model_5.targeting": "9509b49ef34d9b478bf17b70", +"74:orders_model_5.sourced": "6786f18f6ff42aa577c99d86", +"75:orders_model_8.has_model": "b5bea41b6c623f7c09f1bf24", +"76:orders_model_8.has_star": "b5bea41b6c623f7c09f1bf24", +"77:orders_model_8.edge_count": "4b227777d4dd1fc61c6f884f", +"78:orders_model_8.targeting": "52ad3bd8074b30476404477a", +"79:orders_model_8.sourced": "6786f18f6ff42aa577c99d86", +"7:orders_model_12.edge_count": "d4735e3a265e16eee03f5971", +"80:models": "51075542f67bd94c29d3f0c4", +"81:edges": "bbe2efc481c2f6f64d4e62a1", +"8:orders_model_12.targeting": "7eb1a6cd5b907b1881d7b4cb", +"9:orders_model_12.sourced": "6786f18f6ff42aa577c99d86" +} +], +[ +"lineage", +{ +"0:orders_model_0.has_model": "fcbcf165908dd18a9e49f7ff", +"10:orders_model_15.has_model": "b5bea41b6c623f7c09f1bf24", +"11:orders_model_15.has_star": "fcbcf165908dd18a9e49f7ff", +"12:orders_model_15.edge_count": "4e07408562bedb8b60ce05c1", +"13:orders_model_15.targeting": "3a2211ec7f6ecf213884189f", +"14:orders_model_15.sourced": "6786f18f6ff42aa577c99d86", +"15:orders_model_3.has_model": "fcbcf165908dd18a9e49f7ff", +"16:orders_model_3.has_star": "fcbcf165908dd18a9e49f7ff", +"17:orders_model_3.edge_count": "5feceb66ffc86f38d952786c", +"18:orders_model_3.targeting": "6786f18f6ff42aa577c99d86", +"19:orders_model_3.sourced": "67ac37eb58f45c8042ba79fb", +"1:orders_model_0.has_star": "fcbcf165908dd18a9e49f7ff", +"20:orders_model_6.has_model": "b5bea41b6c623f7c09f1bf24", +"21:orders_model_6.has_star": "fcbcf165908dd18a9e49f7ff", +"22:orders_model_6.edge_count": "4e07408562bedb8b60ce05c1", +"23:orders_model_6.targeting": "bba7433c100a9ca120f6fbcf", +"24:orders_model_6.sourced": "1883ac21741e29509968e6b0", +"25:orders_model_9.has_model": "b5bea41b6c623f7c09f1bf24", +"26:orders_model_9.has_star": "b5bea41b6c623f7c09f1bf24", +"27:orders_model_9.edge_count": "d4735e3a265e16eee03f5971", +"28:orders_model_9.targeting": "67ac37eb58f45c8042ba79fb", +"29:orders_model_9.sourced": "6786f18f6ff42aa577c99d86", +"2:orders_model_0.edge_count": "5feceb66ffc86f38d952786c", +"30:orders_model_1.has_model": "b5bea41b6c623f7c09f1bf24", +"31:orders_model_1.has_star": "b5bea41b6c623f7c09f1bf24", +"32:orders_model_1.edge_count": "4e07408562bedb8b60ce05c1", +"33:orders_model_1.targeting": "452427dd584527df4f8ece1d", +"34:orders_model_1.sourced": "6786f18f6ff42aa577c99d86", +"35:orders_model_10.has_model": "b5bea41b6c623f7c09f1bf24", +"36:orders_model_10.has_star": "b5bea41b6c623f7c09f1bf24", +"37:orders_model_10.edge_count": "4e07408562bedb8b60ce05c1", +"38:orders_model_10.targeting": "6ce4efde8f1573118d43d489", +"39:orders_model_10.sourced": "6786f18f6ff42aa577c99d86", +"3:orders_model_0.targeting": "6786f18f6ff42aa577c99d86", +"40:orders_model_13.has_model": "fcbcf165908dd18a9e49f7ff", +"41:orders_model_13.has_star": "fcbcf165908dd18a9e49f7ff", +"42:orders_model_13.edge_count": "5feceb66ffc86f38d952786c", +"43:orders_model_13.targeting": "6786f18f6ff42aa577c99d86", +"44:orders_model_13.sourced": "6786f18f6ff42aa577c99d86", +"45:orders_model_4.has_model": "fcbcf165908dd18a9e49f7ff", +"46:orders_model_4.has_star": "fcbcf165908dd18a9e49f7ff", +"47:orders_model_4.edge_count": "5feceb66ffc86f38d952786c", +"48:orders_model_4.targeting": "6786f18f6ff42aa577c99d86", +"49:orders_model_4.sourced": "6786f18f6ff42aa577c99d86", +"4:orders_model_0.sourced": "75fb8b4ea541b83a96bb78aa", +"50:orders_model_7.has_model": "fcbcf165908dd18a9e49f7ff", +"51:orders_model_7.has_star": "fcbcf165908dd18a9e49f7ff", +"52:orders_model_7.edge_count": "5feceb66ffc86f38d952786c", +"53:orders_model_7.targeting": "6786f18f6ff42aa577c99d86", +"54:orders_model_7.sourced": "6786f18f6ff42aa577c99d86", +"55:orders_model_11.has_model": "b5bea41b6c623f7c09f1bf24", +"56:orders_model_11.has_star": "fcbcf165908dd18a9e49f7ff", +"57:orders_model_11.edge_count": "6b86b273ff34fce19d6b804e", +"58:orders_model_11.targeting": "422c92f9dd61b2ef65dee3be", +"59:orders_model_11.sourced": "3a2211ec7f6ecf213884189f", +"5:orders_model_12.has_model": "b5bea41b6c623f7c09f1bf24", +"60:orders_model_14.has_model": "fcbcf165908dd18a9e49f7ff", +"61:orders_model_14.has_star": "fcbcf165908dd18a9e49f7ff", +"62:orders_model_14.edge_count": "5feceb66ffc86f38d952786c", +"63:orders_model_14.targeting": "6786f18f6ff42aa577c99d86", +"64:orders_model_14.sourced": "6786f18f6ff42aa577c99d86", +"65:orders_model_2.has_model": "fcbcf165908dd18a9e49f7ff", +"66:orders_model_2.has_star": "fcbcf165908dd18a9e49f7ff", +"67:orders_model_2.edge_count": "5feceb66ffc86f38d952786c", +"68:orders_model_2.targeting": "6786f18f6ff42aa577c99d86", +"69:orders_model_2.sourced": "6786f18f6ff42aa577c99d86", +"6:orders_model_12.has_star": "fcbcf165908dd18a9e49f7ff", +"70:orders_model_5.has_model": "fcbcf165908dd18a9e49f7ff", +"71:orders_model_5.has_star": "fcbcf165908dd18a9e49f7ff", +"72:orders_model_5.edge_count": "5feceb66ffc86f38d952786c", +"73:orders_model_5.targeting": "6786f18f6ff42aa577c99d86", +"74:orders_model_5.sourced": "6786f18f6ff42aa577c99d86", +"75:orders_model_8.has_model": "b5bea41b6c623f7c09f1bf24", +"76:orders_model_8.has_star": "b5bea41b6c623f7c09f1bf24", +"77:orders_model_8.edge_count": "4b227777d4dd1fc61c6f884f", +"78:orders_model_8.targeting": "52ad3bd8074b30476404477a", +"79:orders_model_8.sourced": "6786f18f6ff42aa577c99d86", +"7:orders_model_12.edge_count": "d4735e3a265e16eee03f5971", +"80:models": "162bd27b0ba0371264b7f846", +"81:edges": "7f0f5f6e0554b4505652d3aa", +"8:orders_model_12.targeting": "7eb1a6cd5b907b1881d7b4cb", +"9:orders_model_12.sourced": "6786f18f6ff42aa577c99d86" +} +], +[ +"lineage", +{ +"0:orders_model_0.has_model": "b5bea41b6c623f7c09f1bf24", +"10:orders_model_15.has_model": "b5bea41b6c623f7c09f1bf24", +"11:orders_model_15.has_star": "fcbcf165908dd18a9e49f7ff", +"12:orders_model_15.edge_count": "4e07408562bedb8b60ce05c1", +"13:orders_model_15.targeting": "623473241d8ca9bda2996980", +"14:orders_model_15.sourced": "6786f18f6ff42aa577c99d86", +"15:orders_model_3.has_model": "fcbcf165908dd18a9e49f7ff", +"16:orders_model_3.has_star": "fcbcf165908dd18a9e49f7ff", +"17:orders_model_3.edge_count": "5feceb66ffc86f38d952786c", +"18:orders_model_3.targeting": "6786f18f6ff42aa577c99d86", +"19:orders_model_3.sourced": "67ac37eb58f45c8042ba79fb", +"1:orders_model_0.has_star": "b5bea41b6c623f7c09f1bf24", +"20:orders_model_6.has_model": "b5bea41b6c623f7c09f1bf24", +"21:orders_model_6.has_star": "fcbcf165908dd18a9e49f7ff", +"22:orders_model_6.edge_count": "4e07408562bedb8b60ce05c1", +"23:orders_model_6.targeting": "f8fbb61b3c961fa2694c9c39", +"24:orders_model_6.sourced": "38e17123b61705a17df7d300", +"25:orders_model_9.has_model": "b5bea41b6c623f7c09f1bf24", +"26:orders_model_9.has_star": "b5bea41b6c623f7c09f1bf24", +"27:orders_model_9.edge_count": "d4735e3a265e16eee03f5971", +"28:orders_model_9.targeting": "67ac37eb58f45c8042ba79fb", +"29:orders_model_9.sourced": "6786f18f6ff42aa577c99d86", +"2:orders_model_0.edge_count": "d4735e3a265e16eee03f5971", +"30:orders_model_1.has_model": "b5bea41b6c623f7c09f1bf24", +"31:orders_model_1.has_star": "b5bea41b6c623f7c09f1bf24", +"32:orders_model_1.edge_count": "4e07408562bedb8b60ce05c1", +"33:orders_model_1.targeting": "18ac30c5dd99f8c1b7a2db88", +"34:orders_model_1.sourced": "52882debecc7c972eb26e4ff", +"35:orders_model_10.has_model": "b5bea41b6c623f7c09f1bf24", +"36:orders_model_10.has_star": "b5bea41b6c623f7c09f1bf24", +"37:orders_model_10.edge_count": "4e07408562bedb8b60ce05c1", +"38:orders_model_10.targeting": "6ce4efde8f1573118d43d489", +"39:orders_model_10.sourced": "6786f18f6ff42aa577c99d86", +"3:orders_model_0.targeting": "10f59ba6b47d64ce6b56d32b", +"40:orders_model_13.has_model": "b5bea41b6c623f7c09f1bf24", +"41:orders_model_13.has_star": "b5bea41b6c623f7c09f1bf24", +"42:orders_model_13.edge_count": "4e07408562bedb8b60ce05c1", +"43:orders_model_13.targeting": "c5bd06cf3f6a094d7fb244f2", +"44:orders_model_13.sourced": "6786f18f6ff42aa577c99d86", +"45:orders_model_4.has_model": "b5bea41b6c623f7c09f1bf24", +"46:orders_model_4.has_star": "b5bea41b6c623f7c09f1bf24", +"47:orders_model_4.edge_count": "4e07408562bedb8b60ce05c1", +"48:orders_model_4.targeting": "2fe1b26c19346af87d9dce63", +"49:orders_model_4.sourced": "6786f18f6ff42aa577c99d86", +"4:orders_model_0.sourced": "75fb8b4ea541b83a96bb78aa", +"50:orders_model_7.has_model": "b5bea41b6c623f7c09f1bf24", +"51:orders_model_7.has_star": "fcbcf165908dd18a9e49f7ff", +"52:orders_model_7.edge_count": "7902699be42c8a8e46fbbb45", +"53:orders_model_7.targeting": "9df29af9bb05304b24f1c2a5", +"54:orders_model_7.sourced": "6786f18f6ff42aa577c99d86", +"55:orders_model_11.has_model": "b5bea41b6c623f7c09f1bf24", +"56:orders_model_11.has_star": "fcbcf165908dd18a9e49f7ff", +"57:orders_model_11.edge_count": "6b86b273ff34fce19d6b804e", +"58:orders_model_11.targeting": "422c92f9dd61b2ef65dee3be", +"59:orders_model_11.sourced": "623473241d8ca9bda2996980", +"5:orders_model_12.has_model": "fcbcf165908dd18a9e49f7ff", +"60:orders_model_14.has_model": "b5bea41b6c623f7c09f1bf24", +"61:orders_model_14.has_star": "fcbcf165908dd18a9e49f7ff", +"62:orders_model_14.edge_count": "d4735e3a265e16eee03f5971", +"63:orders_model_14.targeting": "2f589a910397d13d89a42610", +"64:orders_model_14.sourced": "6786f18f6ff42aa577c99d86", +"65:orders_model_2.has_model": "b5bea41b6c623f7c09f1bf24", +"66:orders_model_2.has_star": "fcbcf165908dd18a9e49f7ff", +"67:orders_model_2.edge_count": "6b86b273ff34fce19d6b804e", +"68:orders_model_2.targeting": "62f420101b911c5efeabdd8a", +"69:orders_model_2.sourced": "8320fd4ca2df04ccf0261f2f", +"6:orders_model_12.has_star": "fcbcf165908dd18a9e49f7ff", +"70:orders_model_5.has_model": "b5bea41b6c623f7c09f1bf24", +"71:orders_model_5.has_star": "fcbcf165908dd18a9e49f7ff", +"72:orders_model_5.edge_count": "d4735e3a265e16eee03f5971", +"73:orders_model_5.targeting": "720842844b7fea44c5badfc4", +"74:orders_model_5.sourced": "6786f18f6ff42aa577c99d86", +"75:orders_model_8.has_model": "b5bea41b6c623f7c09f1bf24", +"76:orders_model_8.has_star": "b5bea41b6c623f7c09f1bf24", +"77:orders_model_8.edge_count": "4b227777d4dd1fc61c6f884f", +"78:orders_model_8.targeting": "52ad3bd8074b30476404477a", +"79:orders_model_8.sourced": "6786f18f6ff42aa577c99d86", +"7:orders_model_12.edge_count": "5feceb66ffc86f38d952786c", +"80:models": "27e54dae2504a7f831e0369b", +"81:edges": "3530701087d04534df62ce37", +"8:orders_model_12.targeting": "6786f18f6ff42aa577c99d86", +"9:orders_model_12.sourced": "6786f18f6ff42aa577c99d86" +} +], +[ +"lineage", +{ +"0:orders_model_0.has_model": "fcbcf165908dd18a9e49f7ff", +"10:orders_model_15.has_model": "b5bea41b6c623f7c09f1bf24", +"11:orders_model_15.has_star": "fcbcf165908dd18a9e49f7ff", +"12:orders_model_15.edge_count": "4e07408562bedb8b60ce05c1", +"13:orders_model_15.targeting": "623473241d8ca9bda2996980", +"14:orders_model_15.sourced": "6786f18f6ff42aa577c99d86", +"15:orders_model_3.has_model": "fcbcf165908dd18a9e49f7ff", +"16:orders_model_3.has_star": "fcbcf165908dd18a9e49f7ff", +"17:orders_model_3.edge_count": "5feceb66ffc86f38d952786c", +"18:orders_model_3.targeting": "6786f18f6ff42aa577c99d86", +"19:orders_model_3.sourced": "67ac37eb58f45c8042ba79fb", +"1:orders_model_0.has_star": "fcbcf165908dd18a9e49f7ff", +"20:orders_model_6.has_model": "b5bea41b6c623f7c09f1bf24", +"21:orders_model_6.has_star": "fcbcf165908dd18a9e49f7ff", +"22:orders_model_6.edge_count": "4e07408562bedb8b60ce05c1", +"23:orders_model_6.targeting": "f8fbb61b3c961fa2694c9c39", +"24:orders_model_6.sourced": "38e17123b61705a17df7d300", +"25:orders_model_9.has_model": "b5bea41b6c623f7c09f1bf24", +"26:orders_model_9.has_star": "b5bea41b6c623f7c09f1bf24", +"27:orders_model_9.edge_count": "d4735e3a265e16eee03f5971", +"28:orders_model_9.targeting": "67ac37eb58f45c8042ba79fb", +"29:orders_model_9.sourced": "6786f18f6ff42aa577c99d86", +"2:orders_model_0.edge_count": "5feceb66ffc86f38d952786c", +"30:orders_model_1.has_model": "b5bea41b6c623f7c09f1bf24", +"31:orders_model_1.has_star": "b5bea41b6c623f7c09f1bf24", +"32:orders_model_1.edge_count": "4e07408562bedb8b60ce05c1", +"33:orders_model_1.targeting": "18ac30c5dd99f8c1b7a2db88", +"34:orders_model_1.sourced": "6786f18f6ff42aa577c99d86", +"35:orders_model_10.has_model": "b5bea41b6c623f7c09f1bf24", +"36:orders_model_10.has_star": "b5bea41b6c623f7c09f1bf24", +"37:orders_model_10.edge_count": "4e07408562bedb8b60ce05c1", +"38:orders_model_10.targeting": "6ce4efde8f1573118d43d489", +"39:orders_model_10.sourced": "6786f18f6ff42aa577c99d86", +"3:orders_model_0.targeting": "6786f18f6ff42aa577c99d86", +"40:orders_model_13.has_model": "fcbcf165908dd18a9e49f7ff", +"41:orders_model_13.has_star": "fcbcf165908dd18a9e49f7ff", +"42:orders_model_13.edge_count": "5feceb66ffc86f38d952786c", +"43:orders_model_13.targeting": "6786f18f6ff42aa577c99d86", +"44:orders_model_13.sourced": "6786f18f6ff42aa577c99d86", +"45:orders_model_4.has_model": "fcbcf165908dd18a9e49f7ff", +"46:orders_model_4.has_star": "fcbcf165908dd18a9e49f7ff", +"47:orders_model_4.edge_count": "5feceb66ffc86f38d952786c", +"48:orders_model_4.targeting": "6786f18f6ff42aa577c99d86", +"49:orders_model_4.sourced": "6786f18f6ff42aa577c99d86", +"4:orders_model_0.sourced": "75fb8b4ea541b83a96bb78aa", +"50:orders_model_7.has_model": "fcbcf165908dd18a9e49f7ff", +"51:orders_model_7.has_star": "fcbcf165908dd18a9e49f7ff", +"52:orders_model_7.edge_count": "5feceb66ffc86f38d952786c", +"53:orders_model_7.targeting": "6786f18f6ff42aa577c99d86", +"54:orders_model_7.sourced": "6786f18f6ff42aa577c99d86", +"55:orders_model_11.has_model": "b5bea41b6c623f7c09f1bf24", +"56:orders_model_11.has_star": "fcbcf165908dd18a9e49f7ff", +"57:orders_model_11.edge_count": "6b86b273ff34fce19d6b804e", +"58:orders_model_11.targeting": "422c92f9dd61b2ef65dee3be", +"59:orders_model_11.sourced": "623473241d8ca9bda2996980", +"5:orders_model_12.has_model": "fcbcf165908dd18a9e49f7ff", +"60:orders_model_14.has_model": "fcbcf165908dd18a9e49f7ff", +"61:orders_model_14.has_star": "fcbcf165908dd18a9e49f7ff", +"62:orders_model_14.edge_count": "5feceb66ffc86f38d952786c", +"63:orders_model_14.targeting": "6786f18f6ff42aa577c99d86", +"64:orders_model_14.sourced": "6786f18f6ff42aa577c99d86", +"65:orders_model_2.has_model": "fcbcf165908dd18a9e49f7ff", +"66:orders_model_2.has_star": "fcbcf165908dd18a9e49f7ff", +"67:orders_model_2.edge_count": "5feceb66ffc86f38d952786c", +"68:orders_model_2.targeting": "6786f18f6ff42aa577c99d86", +"69:orders_model_2.sourced": "6786f18f6ff42aa577c99d86", +"6:orders_model_12.has_star": "fcbcf165908dd18a9e49f7ff", +"70:orders_model_5.has_model": "fcbcf165908dd18a9e49f7ff", +"71:orders_model_5.has_star": "fcbcf165908dd18a9e49f7ff", +"72:orders_model_5.edge_count": "5feceb66ffc86f38d952786c", +"73:orders_model_5.targeting": "6786f18f6ff42aa577c99d86", +"74:orders_model_5.sourced": "6786f18f6ff42aa577c99d86", +"75:orders_model_8.has_model": "b5bea41b6c623f7c09f1bf24", +"76:orders_model_8.has_star": "b5bea41b6c623f7c09f1bf24", +"77:orders_model_8.edge_count": "4b227777d4dd1fc61c6f884f", +"78:orders_model_8.targeting": "52ad3bd8074b30476404477a", +"79:orders_model_8.sourced": "6786f18f6ff42aa577c99d86", +"7:orders_model_12.edge_count": "5feceb66ffc86f38d952786c", +"80:models": "582bc1ad59a348db0ee52665", +"81:edges": "d24dafbe5842db03ac5ee2e0", +"8:orders_model_12.targeting": "6786f18f6ff42aa577c99d86", +"9:orders_model_12.sourced": "6786f18f6ff42aa577c99d86" +} +], +[ +"lineage", +{ +"0:orders_model_0.has_model": "b5bea41b6c623f7c09f1bf24", +"10:orders_model_15.has_model": "b5bea41b6c623f7c09f1bf24", +"11:orders_model_15.has_star": "fcbcf165908dd18a9e49f7ff", +"12:orders_model_15.edge_count": "4e07408562bedb8b60ce05c1", +"13:orders_model_15.targeting": "623473241d8ca9bda2996980", +"14:orders_model_15.sourced": "6786f18f6ff42aa577c99d86", +"15:orders_model_3.has_model": "fcbcf165908dd18a9e49f7ff", +"16:orders_model_3.has_star": "fcbcf165908dd18a9e49f7ff", +"17:orders_model_3.edge_count": "5feceb66ffc86f38d952786c", +"18:orders_model_3.targeting": "6786f18f6ff42aa577c99d86", +"19:orders_model_3.sourced": "67ac37eb58f45c8042ba79fb", +"1:orders_model_0.has_star": "b5bea41b6c623f7c09f1bf24", +"20:orders_model_6.has_model": "b5bea41b6c623f7c09f1bf24", +"21:orders_model_6.has_star": "fcbcf165908dd18a9e49f7ff", +"22:orders_model_6.edge_count": "4e07408562bedb8b60ce05c1", +"23:orders_model_6.targeting": "f8fbb61b3c961fa2694c9c39", +"24:orders_model_6.sourced": "38e17123b61705a17df7d300", +"25:orders_model_9.has_model": "b5bea41b6c623f7c09f1bf24", +"26:orders_model_9.has_star": "b5bea41b6c623f7c09f1bf24", +"27:orders_model_9.edge_count": "d4735e3a265e16eee03f5971", +"28:orders_model_9.targeting": "67ac37eb58f45c8042ba79fb", +"29:orders_model_9.sourced": "6786f18f6ff42aa577c99d86", +"2:orders_model_0.edge_count": "d4735e3a265e16eee03f5971", +"30:orders_model_1.has_model": "b5bea41b6c623f7c09f1bf24", +"31:orders_model_1.has_star": "b5bea41b6c623f7c09f1bf24", +"32:orders_model_1.edge_count": "4e07408562bedb8b60ce05c1", +"33:orders_model_1.targeting": "18ac30c5dd99f8c1b7a2db88", +"34:orders_model_1.sourced": "52882debecc7c972eb26e4ff", +"35:orders_model_10.has_model": "b5bea41b6c623f7c09f1bf24", +"36:orders_model_10.has_star": "b5bea41b6c623f7c09f1bf24", +"37:orders_model_10.edge_count": "4e07408562bedb8b60ce05c1", +"38:orders_model_10.targeting": "6ce4efde8f1573118d43d489", +"39:orders_model_10.sourced": "6786f18f6ff42aa577c99d86", +"3:orders_model_0.targeting": "10f59ba6b47d64ce6b56d32b", +"40:orders_model_13.has_model": "b5bea41b6c623f7c09f1bf24", +"41:orders_model_13.has_star": "b5bea41b6c623f7c09f1bf24", +"42:orders_model_13.edge_count": "4e07408562bedb8b60ce05c1", +"43:orders_model_13.targeting": "c5bd06cf3f6a094d7fb244f2", +"44:orders_model_13.sourced": "6786f18f6ff42aa577c99d86", +"45:orders_model_4.has_model": "b5bea41b6c623f7c09f1bf24", +"46:orders_model_4.has_star": "b5bea41b6c623f7c09f1bf24", +"47:orders_model_4.edge_count": "4e07408562bedb8b60ce05c1", +"48:orders_model_4.targeting": "2fe1b26c19346af87d9dce63", +"49:orders_model_4.sourced": "6786f18f6ff42aa577c99d86", +"4:orders_model_0.sourced": "75fb8b4ea541b83a96bb78aa", +"50:orders_model_7.has_model": "b5bea41b6c623f7c09f1bf24", +"51:orders_model_7.has_star": "fcbcf165908dd18a9e49f7ff", +"52:orders_model_7.edge_count": "7902699be42c8a8e46fbbb45", +"53:orders_model_7.targeting": "9df29af9bb05304b24f1c2a5", +"54:orders_model_7.sourced": "6786f18f6ff42aa577c99d86", +"55:orders_model_11.has_model": "b5bea41b6c623f7c09f1bf24", +"56:orders_model_11.has_star": "fcbcf165908dd18a9e49f7ff", +"57:orders_model_11.edge_count": "6b86b273ff34fce19d6b804e", +"58:orders_model_11.targeting": "422c92f9dd61b2ef65dee3be", +"59:orders_model_11.sourced": "623473241d8ca9bda2996980", +"5:orders_model_12.has_model": "fcbcf165908dd18a9e49f7ff", +"60:orders_model_14.has_model": "b5bea41b6c623f7c09f1bf24", +"61:orders_model_14.has_star": "fcbcf165908dd18a9e49f7ff", +"62:orders_model_14.edge_count": "d4735e3a265e16eee03f5971", +"63:orders_model_14.targeting": "2f589a910397d13d89a42610", +"64:orders_model_14.sourced": "6786f18f6ff42aa577c99d86", +"65:orders_model_2.has_model": "b5bea41b6c623f7c09f1bf24", +"66:orders_model_2.has_star": "fcbcf165908dd18a9e49f7ff", +"67:orders_model_2.edge_count": "6b86b273ff34fce19d6b804e", +"68:orders_model_2.targeting": "62f420101b911c5efeabdd8a", +"69:orders_model_2.sourced": "8320fd4ca2df04ccf0261f2f", +"6:orders_model_12.has_star": "fcbcf165908dd18a9e49f7ff", +"70:orders_model_5.has_model": "b5bea41b6c623f7c09f1bf24", +"71:orders_model_5.has_star": "fcbcf165908dd18a9e49f7ff", +"72:orders_model_5.edge_count": "d4735e3a265e16eee03f5971", +"73:orders_model_5.targeting": "720842844b7fea44c5badfc4", +"74:orders_model_5.sourced": "6786f18f6ff42aa577c99d86", +"75:orders_model_8.has_model": "b5bea41b6c623f7c09f1bf24", +"76:orders_model_8.has_star": "b5bea41b6c623f7c09f1bf24", +"77:orders_model_8.edge_count": "4b227777d4dd1fc61c6f884f", +"78:orders_model_8.targeting": "52ad3bd8074b30476404477a", +"79:orders_model_8.sourced": "6786f18f6ff42aa577c99d86", +"7:orders_model_12.edge_count": "5feceb66ffc86f38d952786c", +"80:models": "27e54dae2504a7f831e0369b", +"81:edges": "3530701087d04534df62ce37", +"8:orders_model_12.targeting": "6786f18f6ff42aa577c99d86", +"9:orders_model_12.sourced": "6786f18f6ff42aa577c99d86" +} +], +[ +"lineage", +{ +"0:orders_model_0.has_model": "fcbcf165908dd18a9e49f7ff", +"10:orders_model_15.has_model": "b5bea41b6c623f7c09f1bf24", +"11:orders_model_15.has_star": "fcbcf165908dd18a9e49f7ff", +"12:orders_model_15.edge_count": "4e07408562bedb8b60ce05c1", +"13:orders_model_15.targeting": "623473241d8ca9bda2996980", +"14:orders_model_15.sourced": "6786f18f6ff42aa577c99d86", +"15:orders_model_3.has_model": "fcbcf165908dd18a9e49f7ff", +"16:orders_model_3.has_star": "fcbcf165908dd18a9e49f7ff", +"17:orders_model_3.edge_count": "5feceb66ffc86f38d952786c", +"18:orders_model_3.targeting": "6786f18f6ff42aa577c99d86", +"19:orders_model_3.sourced": "67ac37eb58f45c8042ba79fb", +"1:orders_model_0.has_star": "fcbcf165908dd18a9e49f7ff", +"20:orders_model_6.has_model": "b5bea41b6c623f7c09f1bf24", +"21:orders_model_6.has_star": "fcbcf165908dd18a9e49f7ff", +"22:orders_model_6.edge_count": "4e07408562bedb8b60ce05c1", +"23:orders_model_6.targeting": "f8fbb61b3c961fa2694c9c39", +"24:orders_model_6.sourced": "38e17123b61705a17df7d300", +"25:orders_model_9.has_model": "b5bea41b6c623f7c09f1bf24", +"26:orders_model_9.has_star": "b5bea41b6c623f7c09f1bf24", +"27:orders_model_9.edge_count": "d4735e3a265e16eee03f5971", +"28:orders_model_9.targeting": "67ac37eb58f45c8042ba79fb", +"29:orders_model_9.sourced": "6786f18f6ff42aa577c99d86", +"2:orders_model_0.edge_count": "5feceb66ffc86f38d952786c", +"30:orders_model_1.has_model": "b5bea41b6c623f7c09f1bf24", +"31:orders_model_1.has_star": "b5bea41b6c623f7c09f1bf24", +"32:orders_model_1.edge_count": "4e07408562bedb8b60ce05c1", +"33:orders_model_1.targeting": "18ac30c5dd99f8c1b7a2db88", +"34:orders_model_1.sourced": "6786f18f6ff42aa577c99d86", +"35:orders_model_10.has_model": "b5bea41b6c623f7c09f1bf24", +"36:orders_model_10.has_star": "b5bea41b6c623f7c09f1bf24", +"37:orders_model_10.edge_count": "4e07408562bedb8b60ce05c1", +"38:orders_model_10.targeting": "6ce4efde8f1573118d43d489", +"39:orders_model_10.sourced": "6786f18f6ff42aa577c99d86", +"3:orders_model_0.targeting": "6786f18f6ff42aa577c99d86", +"40:orders_model_13.has_model": "fcbcf165908dd18a9e49f7ff", +"41:orders_model_13.has_star": "fcbcf165908dd18a9e49f7ff", +"42:orders_model_13.edge_count": "5feceb66ffc86f38d952786c", +"43:orders_model_13.targeting": "6786f18f6ff42aa577c99d86", +"44:orders_model_13.sourced": "6786f18f6ff42aa577c99d86", +"45:orders_model_4.has_model": "fcbcf165908dd18a9e49f7ff", +"46:orders_model_4.has_star": "fcbcf165908dd18a9e49f7ff", +"47:orders_model_4.edge_count": "5feceb66ffc86f38d952786c", +"48:orders_model_4.targeting": "6786f18f6ff42aa577c99d86", +"49:orders_model_4.sourced": "6786f18f6ff42aa577c99d86", +"4:orders_model_0.sourced": "75fb8b4ea541b83a96bb78aa", +"50:orders_model_7.has_model": "fcbcf165908dd18a9e49f7ff", +"51:orders_model_7.has_star": "fcbcf165908dd18a9e49f7ff", +"52:orders_model_7.edge_count": "5feceb66ffc86f38d952786c", +"53:orders_model_7.targeting": "6786f18f6ff42aa577c99d86", +"54:orders_model_7.sourced": "6786f18f6ff42aa577c99d86", +"55:orders_model_11.has_model": "b5bea41b6c623f7c09f1bf24", +"56:orders_model_11.has_star": "fcbcf165908dd18a9e49f7ff", +"57:orders_model_11.edge_count": "6b86b273ff34fce19d6b804e", +"58:orders_model_11.targeting": "422c92f9dd61b2ef65dee3be", +"59:orders_model_11.sourced": "623473241d8ca9bda2996980", +"5:orders_model_12.has_model": "fcbcf165908dd18a9e49f7ff", +"60:orders_model_14.has_model": "fcbcf165908dd18a9e49f7ff", +"61:orders_model_14.has_star": "fcbcf165908dd18a9e49f7ff", +"62:orders_model_14.edge_count": "5feceb66ffc86f38d952786c", +"63:orders_model_14.targeting": "6786f18f6ff42aa577c99d86", +"64:orders_model_14.sourced": "6786f18f6ff42aa577c99d86", +"65:orders_model_2.has_model": "fcbcf165908dd18a9e49f7ff", +"66:orders_model_2.has_star": "fcbcf165908dd18a9e49f7ff", +"67:orders_model_2.edge_count": "5feceb66ffc86f38d952786c", +"68:orders_model_2.targeting": "6786f18f6ff42aa577c99d86", +"69:orders_model_2.sourced": "6786f18f6ff42aa577c99d86", +"6:orders_model_12.has_star": "fcbcf165908dd18a9e49f7ff", +"70:orders_model_5.has_model": "fcbcf165908dd18a9e49f7ff", +"71:orders_model_5.has_star": "fcbcf165908dd18a9e49f7ff", +"72:orders_model_5.edge_count": "5feceb66ffc86f38d952786c", +"73:orders_model_5.targeting": "6786f18f6ff42aa577c99d86", +"74:orders_model_5.sourced": "6786f18f6ff42aa577c99d86", +"75:orders_model_8.has_model": "b5bea41b6c623f7c09f1bf24", +"76:orders_model_8.has_star": "b5bea41b6c623f7c09f1bf24", +"77:orders_model_8.edge_count": "4b227777d4dd1fc61c6f884f", +"78:orders_model_8.targeting": "52ad3bd8074b30476404477a", +"79:orders_model_8.sourced": "6786f18f6ff42aa577c99d86", +"7:orders_model_12.edge_count": "5feceb66ffc86f38d952786c", +"80:models": "582bc1ad59a348db0ee52665", +"81:edges": "d24dafbe5842db03ac5ee2e0", +"8:orders_model_12.targeting": "6786f18f6ff42aa577c99d86", +"9:orders_model_12.sourced": "6786f18f6ff42aa577c99d86" +} +], +[ +"lineage", +{ +"0:orders_model_0.has_model": "b5bea41b6c623f7c09f1bf24", +"10:orders_model_15.has_model": "b5bea41b6c623f7c09f1bf24", +"11:orders_model_15.has_star": "fcbcf165908dd18a9e49f7ff", +"12:orders_model_15.edge_count": "4e07408562bedb8b60ce05c1", +"13:orders_model_15.targeting": "623473241d8ca9bda2996980", +"14:orders_model_15.sourced": "6786f18f6ff42aa577c99d86", +"15:orders_model_3.has_model": "fcbcf165908dd18a9e49f7ff", +"16:orders_model_3.has_star": "fcbcf165908dd18a9e49f7ff", +"17:orders_model_3.edge_count": "5feceb66ffc86f38d952786c", +"18:orders_model_3.targeting": "6786f18f6ff42aa577c99d86", +"19:orders_model_3.sourced": "67ac37eb58f45c8042ba79fb", +"1:orders_model_0.has_star": "b5bea41b6c623f7c09f1bf24", +"20:orders_model_6.has_model": "b5bea41b6c623f7c09f1bf24", +"21:orders_model_6.has_star": "fcbcf165908dd18a9e49f7ff", +"22:orders_model_6.edge_count": "4e07408562bedb8b60ce05c1", +"23:orders_model_6.targeting": "f8fbb61b3c961fa2694c9c39", +"24:orders_model_6.sourced": "38e17123b61705a17df7d300", +"25:orders_model_9.has_model": "b5bea41b6c623f7c09f1bf24", +"26:orders_model_9.has_star": "b5bea41b6c623f7c09f1bf24", +"27:orders_model_9.edge_count": "d4735e3a265e16eee03f5971", +"28:orders_model_9.targeting": "67ac37eb58f45c8042ba79fb", +"29:orders_model_9.sourced": "6786f18f6ff42aa577c99d86", +"2:orders_model_0.edge_count": "d4735e3a265e16eee03f5971", +"30:orders_model_1.has_model": "b5bea41b6c623f7c09f1bf24", +"31:orders_model_1.has_star": "b5bea41b6c623f7c09f1bf24", +"32:orders_model_1.edge_count": "4e07408562bedb8b60ce05c1", +"33:orders_model_1.targeting": "18ac30c5dd99f8c1b7a2db88", +"34:orders_model_1.sourced": "52882debecc7c972eb26e4ff", +"35:orders_model_10.has_model": "b5bea41b6c623f7c09f1bf24", +"36:orders_model_10.has_star": "b5bea41b6c623f7c09f1bf24", +"37:orders_model_10.edge_count": "4e07408562bedb8b60ce05c1", +"38:orders_model_10.targeting": "6ce4efde8f1573118d43d489", +"39:orders_model_10.sourced": "6786f18f6ff42aa577c99d86", +"3:orders_model_0.targeting": "10f59ba6b47d64ce6b56d32b", +"40:orders_model_13.has_model": "b5bea41b6c623f7c09f1bf24", +"41:orders_model_13.has_star": "b5bea41b6c623f7c09f1bf24", +"42:orders_model_13.edge_count": "4e07408562bedb8b60ce05c1", +"43:orders_model_13.targeting": "c5bd06cf3f6a094d7fb244f2", +"44:orders_model_13.sourced": "6786f18f6ff42aa577c99d86", +"45:orders_model_4.has_model": "b5bea41b6c623f7c09f1bf24", +"46:orders_model_4.has_star": "b5bea41b6c623f7c09f1bf24", +"47:orders_model_4.edge_count": "4e07408562bedb8b60ce05c1", +"48:orders_model_4.targeting": "2fe1b26c19346af87d9dce63", +"49:orders_model_4.sourced": "6786f18f6ff42aa577c99d86", +"4:orders_model_0.sourced": "75fb8b4ea541b83a96bb78aa", +"50:orders_model_7.has_model": "b5bea41b6c623f7c09f1bf24", +"51:orders_model_7.has_star": "fcbcf165908dd18a9e49f7ff", +"52:orders_model_7.edge_count": "7902699be42c8a8e46fbbb45", +"53:orders_model_7.targeting": "9df29af9bb05304b24f1c2a5", +"54:orders_model_7.sourced": "6786f18f6ff42aa577c99d86", +"55:orders_model_11.has_model": "b5bea41b6c623f7c09f1bf24", +"56:orders_model_11.has_star": "fcbcf165908dd18a9e49f7ff", +"57:orders_model_11.edge_count": "6b86b273ff34fce19d6b804e", +"58:orders_model_11.targeting": "422c92f9dd61b2ef65dee3be", +"59:orders_model_11.sourced": "623473241d8ca9bda2996980", +"5:orders_model_12.has_model": "fcbcf165908dd18a9e49f7ff", +"60:orders_model_14.has_model": "b5bea41b6c623f7c09f1bf24", +"61:orders_model_14.has_star": "fcbcf165908dd18a9e49f7ff", +"62:orders_model_14.edge_count": "d4735e3a265e16eee03f5971", +"63:orders_model_14.targeting": "2f589a910397d13d89a42610", +"64:orders_model_14.sourced": "6786f18f6ff42aa577c99d86", +"65:orders_model_2.has_model": "b5bea41b6c623f7c09f1bf24", +"66:orders_model_2.has_star": "fcbcf165908dd18a9e49f7ff", +"67:orders_model_2.edge_count": "6b86b273ff34fce19d6b804e", +"68:orders_model_2.targeting": "62f420101b911c5efeabdd8a", +"69:orders_model_2.sourced": "8320fd4ca2df04ccf0261f2f", +"6:orders_model_12.has_star": "fcbcf165908dd18a9e49f7ff", +"70:orders_model_5.has_model": "b5bea41b6c623f7c09f1bf24", +"71:orders_model_5.has_star": "fcbcf165908dd18a9e49f7ff", +"72:orders_model_5.edge_count": "d4735e3a265e16eee03f5971", +"73:orders_model_5.targeting": "720842844b7fea44c5badfc4", +"74:orders_model_5.sourced": "6786f18f6ff42aa577c99d86", +"75:orders_model_8.has_model": "b5bea41b6c623f7c09f1bf24", +"76:orders_model_8.has_star": "b5bea41b6c623f7c09f1bf24", +"77:orders_model_8.edge_count": "4b227777d4dd1fc61c6f884f", +"78:orders_model_8.targeting": "52ad3bd8074b30476404477a", +"79:orders_model_8.sourced": "6786f18f6ff42aa577c99d86", +"7:orders_model_12.edge_count": "5feceb66ffc86f38d952786c", +"80:models": "27e54dae2504a7f831e0369b", +"81:edges": "3530701087d04534df62ce37", +"8:orders_model_12.targeting": "6786f18f6ff42aa577c99d86", +"9:orders_model_12.sourced": "6786f18f6ff42aa577c99d86" +} +], +[ +"lineage", +{ +"0:orders_model_0.has_model": "fcbcf165908dd18a9e49f7ff", +"10:orders_model_15.has_model": "b5bea41b6c623f7c09f1bf24", +"11:orders_model_15.has_star": "fcbcf165908dd18a9e49f7ff", +"12:orders_model_15.edge_count": "4e07408562bedb8b60ce05c1", +"13:orders_model_15.targeting": "623473241d8ca9bda2996980", +"14:orders_model_15.sourced": "6786f18f6ff42aa577c99d86", +"15:orders_model_3.has_model": "fcbcf165908dd18a9e49f7ff", +"16:orders_model_3.has_star": "fcbcf165908dd18a9e49f7ff", +"17:orders_model_3.edge_count": "5feceb66ffc86f38d952786c", +"18:orders_model_3.targeting": "6786f18f6ff42aa577c99d86", +"19:orders_model_3.sourced": "67ac37eb58f45c8042ba79fb", +"1:orders_model_0.has_star": "fcbcf165908dd18a9e49f7ff", +"20:orders_model_6.has_model": "b5bea41b6c623f7c09f1bf24", +"21:orders_model_6.has_star": "fcbcf165908dd18a9e49f7ff", +"22:orders_model_6.edge_count": "4e07408562bedb8b60ce05c1", +"23:orders_model_6.targeting": "f8fbb61b3c961fa2694c9c39", +"24:orders_model_6.sourced": "38e17123b61705a17df7d300", +"25:orders_model_9.has_model": "b5bea41b6c623f7c09f1bf24", +"26:orders_model_9.has_star": "b5bea41b6c623f7c09f1bf24", +"27:orders_model_9.edge_count": "d4735e3a265e16eee03f5971", +"28:orders_model_9.targeting": "67ac37eb58f45c8042ba79fb", +"29:orders_model_9.sourced": "6786f18f6ff42aa577c99d86", +"2:orders_model_0.edge_count": "5feceb66ffc86f38d952786c", +"30:orders_model_1.has_model": "b5bea41b6c623f7c09f1bf24", +"31:orders_model_1.has_star": "b5bea41b6c623f7c09f1bf24", +"32:orders_model_1.edge_count": "4e07408562bedb8b60ce05c1", +"33:orders_model_1.targeting": "18ac30c5dd99f8c1b7a2db88", +"34:orders_model_1.sourced": "6786f18f6ff42aa577c99d86", +"35:orders_model_10.has_model": "b5bea41b6c623f7c09f1bf24", +"36:orders_model_10.has_star": "b5bea41b6c623f7c09f1bf24", +"37:orders_model_10.edge_count": "4e07408562bedb8b60ce05c1", +"38:orders_model_10.targeting": "6ce4efde8f1573118d43d489", +"39:orders_model_10.sourced": "6786f18f6ff42aa577c99d86", +"3:orders_model_0.targeting": "6786f18f6ff42aa577c99d86", +"40:orders_model_13.has_model": "fcbcf165908dd18a9e49f7ff", +"41:orders_model_13.has_star": "fcbcf165908dd18a9e49f7ff", +"42:orders_model_13.edge_count": "5feceb66ffc86f38d952786c", +"43:orders_model_13.targeting": "6786f18f6ff42aa577c99d86", +"44:orders_model_13.sourced": "6786f18f6ff42aa577c99d86", +"45:orders_model_4.has_model": "fcbcf165908dd18a9e49f7ff", +"46:orders_model_4.has_star": "fcbcf165908dd18a9e49f7ff", +"47:orders_model_4.edge_count": "5feceb66ffc86f38d952786c", +"48:orders_model_4.targeting": "6786f18f6ff42aa577c99d86", +"49:orders_model_4.sourced": "6786f18f6ff42aa577c99d86", +"4:orders_model_0.sourced": "75fb8b4ea541b83a96bb78aa", +"50:orders_model_7.has_model": "fcbcf165908dd18a9e49f7ff", +"51:orders_model_7.has_star": "fcbcf165908dd18a9e49f7ff", +"52:orders_model_7.edge_count": "5feceb66ffc86f38d952786c", +"53:orders_model_7.targeting": "6786f18f6ff42aa577c99d86", +"54:orders_model_7.sourced": "6786f18f6ff42aa577c99d86", +"55:orders_model_11.has_model": "b5bea41b6c623f7c09f1bf24", +"56:orders_model_11.has_star": "fcbcf165908dd18a9e49f7ff", +"57:orders_model_11.edge_count": "6b86b273ff34fce19d6b804e", +"58:orders_model_11.targeting": "422c92f9dd61b2ef65dee3be", +"59:orders_model_11.sourced": "623473241d8ca9bda2996980", +"5:orders_model_12.has_model": "fcbcf165908dd18a9e49f7ff", +"60:orders_model_14.has_model": "fcbcf165908dd18a9e49f7ff", +"61:orders_model_14.has_star": "fcbcf165908dd18a9e49f7ff", +"62:orders_model_14.edge_count": "5feceb66ffc86f38d952786c", +"63:orders_model_14.targeting": "6786f18f6ff42aa577c99d86", +"64:orders_model_14.sourced": "6786f18f6ff42aa577c99d86", +"65:orders_model_2.has_model": "fcbcf165908dd18a9e49f7ff", +"66:orders_model_2.has_star": "fcbcf165908dd18a9e49f7ff", +"67:orders_model_2.edge_count": "5feceb66ffc86f38d952786c", +"68:orders_model_2.targeting": "6786f18f6ff42aa577c99d86", +"69:orders_model_2.sourced": "6786f18f6ff42aa577c99d86", +"6:orders_model_12.has_star": "fcbcf165908dd18a9e49f7ff", +"70:orders_model_5.has_model": "fcbcf165908dd18a9e49f7ff", +"71:orders_model_5.has_star": "fcbcf165908dd18a9e49f7ff", +"72:orders_model_5.edge_count": "5feceb66ffc86f38d952786c", +"73:orders_model_5.targeting": "6786f18f6ff42aa577c99d86", +"74:orders_model_5.sourced": "6786f18f6ff42aa577c99d86", +"75:orders_model_8.has_model": "b5bea41b6c623f7c09f1bf24", +"76:orders_model_8.has_star": "b5bea41b6c623f7c09f1bf24", +"77:orders_model_8.edge_count": "4b227777d4dd1fc61c6f884f", +"78:orders_model_8.targeting": "52ad3bd8074b30476404477a", +"79:orders_model_8.sourced": "6786f18f6ff42aa577c99d86", +"7:orders_model_12.edge_count": "5feceb66ffc86f38d952786c", +"80:models": "582bc1ad59a348db0ee52665", +"81:edges": "d24dafbe5842db03ac5ee2e0", +"8:orders_model_12.targeting": "6786f18f6ff42aa577c99d86", +"9:orders_model_12.sourced": "6786f18f6ff42aa577c99d86" +} +], +[ +"lineage", +{ +"0:orders_model_0.has_model": "b5bea41b6c623f7c09f1bf24", +"10:orders_model_15.has_model": "b5bea41b6c623f7c09f1bf24", +"11:orders_model_15.has_star": "fcbcf165908dd18a9e49f7ff", +"12:orders_model_15.edge_count": "4e07408562bedb8b60ce05c1", +"13:orders_model_15.targeting": "623473241d8ca9bda2996980", +"14:orders_model_15.sourced": "6786f18f6ff42aa577c99d86", +"15:orders_model_3.has_model": "fcbcf165908dd18a9e49f7ff", +"16:orders_model_3.has_star": "fcbcf165908dd18a9e49f7ff", +"17:orders_model_3.edge_count": "5feceb66ffc86f38d952786c", +"18:orders_model_3.targeting": "6786f18f6ff42aa577c99d86", +"19:orders_model_3.sourced": "67ac37eb58f45c8042ba79fb", +"1:orders_model_0.has_star": "b5bea41b6c623f7c09f1bf24", +"20:orders_model_6.has_model": "b5bea41b6c623f7c09f1bf24", +"21:orders_model_6.has_star": "fcbcf165908dd18a9e49f7ff", +"22:orders_model_6.edge_count": "4e07408562bedb8b60ce05c1", +"23:orders_model_6.targeting": "f8fbb61b3c961fa2694c9c39", +"24:orders_model_6.sourced": "38e17123b61705a17df7d300", +"25:orders_model_9.has_model": "b5bea41b6c623f7c09f1bf24", +"26:orders_model_9.has_star": "b5bea41b6c623f7c09f1bf24", +"27:orders_model_9.edge_count": "d4735e3a265e16eee03f5971", +"28:orders_model_9.targeting": "67ac37eb58f45c8042ba79fb", +"29:orders_model_9.sourced": "6786f18f6ff42aa577c99d86", +"2:orders_model_0.edge_count": "d4735e3a265e16eee03f5971", +"30:orders_model_1.has_model": "b5bea41b6c623f7c09f1bf24", +"31:orders_model_1.has_star": "b5bea41b6c623f7c09f1bf24", +"32:orders_model_1.edge_count": "4e07408562bedb8b60ce05c1", +"33:orders_model_1.targeting": "18ac30c5dd99f8c1b7a2db88", +"34:orders_model_1.sourced": "52882debecc7c972eb26e4ff", +"35:orders_model_10.has_model": "b5bea41b6c623f7c09f1bf24", +"36:orders_model_10.has_star": "b5bea41b6c623f7c09f1bf24", +"37:orders_model_10.edge_count": "4e07408562bedb8b60ce05c1", +"38:orders_model_10.targeting": "6ce4efde8f1573118d43d489", +"39:orders_model_10.sourced": "6786f18f6ff42aa577c99d86", +"3:orders_model_0.targeting": "10f59ba6b47d64ce6b56d32b", +"40:orders_model_13.has_model": "b5bea41b6c623f7c09f1bf24", +"41:orders_model_13.has_star": "b5bea41b6c623f7c09f1bf24", +"42:orders_model_13.edge_count": "4e07408562bedb8b60ce05c1", +"43:orders_model_13.targeting": "c5bd06cf3f6a094d7fb244f2", +"44:orders_model_13.sourced": "6786f18f6ff42aa577c99d86", +"45:orders_model_4.has_model": "b5bea41b6c623f7c09f1bf24", +"46:orders_model_4.has_star": "b5bea41b6c623f7c09f1bf24", +"47:orders_model_4.edge_count": "4e07408562bedb8b60ce05c1", +"48:orders_model_4.targeting": "2fe1b26c19346af87d9dce63", +"49:orders_model_4.sourced": "6786f18f6ff42aa577c99d86", +"4:orders_model_0.sourced": "75fb8b4ea541b83a96bb78aa", +"50:orders_model_7.has_model": "b5bea41b6c623f7c09f1bf24", +"51:orders_model_7.has_star": "fcbcf165908dd18a9e49f7ff", +"52:orders_model_7.edge_count": "7902699be42c8a8e46fbbb45", +"53:orders_model_7.targeting": "9df29af9bb05304b24f1c2a5", +"54:orders_model_7.sourced": "6786f18f6ff42aa577c99d86", +"55:orders_model_11.has_model": "b5bea41b6c623f7c09f1bf24", +"56:orders_model_11.has_star": "fcbcf165908dd18a9e49f7ff", +"57:orders_model_11.edge_count": "6b86b273ff34fce19d6b804e", +"58:orders_model_11.targeting": "422c92f9dd61b2ef65dee3be", +"59:orders_model_11.sourced": "623473241d8ca9bda2996980", +"5:orders_model_12.has_model": "fcbcf165908dd18a9e49f7ff", +"60:orders_model_14.has_model": "b5bea41b6c623f7c09f1bf24", +"61:orders_model_14.has_star": "fcbcf165908dd18a9e49f7ff", +"62:orders_model_14.edge_count": "d4735e3a265e16eee03f5971", +"63:orders_model_14.targeting": "2f589a910397d13d89a42610", +"64:orders_model_14.sourced": "6786f18f6ff42aa577c99d86", +"65:orders_model_2.has_model": "b5bea41b6c623f7c09f1bf24", +"66:orders_model_2.has_star": "fcbcf165908dd18a9e49f7ff", +"67:orders_model_2.edge_count": "6b86b273ff34fce19d6b804e", +"68:orders_model_2.targeting": "62f420101b911c5efeabdd8a", +"69:orders_model_2.sourced": "8320fd4ca2df04ccf0261f2f", +"6:orders_model_12.has_star": "fcbcf165908dd18a9e49f7ff", +"70:orders_model_5.has_model": "b5bea41b6c623f7c09f1bf24", +"71:orders_model_5.has_star": "fcbcf165908dd18a9e49f7ff", +"72:orders_model_5.edge_count": "d4735e3a265e16eee03f5971", +"73:orders_model_5.targeting": "720842844b7fea44c5badfc4", +"74:orders_model_5.sourced": "6786f18f6ff42aa577c99d86", +"75:orders_model_8.has_model": "b5bea41b6c623f7c09f1bf24", +"76:orders_model_8.has_star": "b5bea41b6c623f7c09f1bf24", +"77:orders_model_8.edge_count": "4b227777d4dd1fc61c6f884f", +"78:orders_model_8.targeting": "52ad3bd8074b30476404477a", +"79:orders_model_8.sourced": "6786f18f6ff42aa577c99d86", +"7:orders_model_12.edge_count": "5feceb66ffc86f38d952786c", +"80:models": "27e54dae2504a7f831e0369b", +"81:edges": "3530701087d04534df62ce37", +"8:orders_model_12.targeting": "6786f18f6ff42aa577c99d86", +"9:orders_model_12.sourced": "6786f18f6ff42aa577c99d86" +} +], +[ +"lineage", +{ +"0:orders_model_0.has_model": "fcbcf165908dd18a9e49f7ff", +"10:orders_model_15.has_model": "b5bea41b6c623f7c09f1bf24", +"11:orders_model_15.has_star": "fcbcf165908dd18a9e49f7ff", +"12:orders_model_15.edge_count": "4e07408562bedb8b60ce05c1", +"13:orders_model_15.targeting": "623473241d8ca9bda2996980", +"14:orders_model_15.sourced": "6786f18f6ff42aa577c99d86", +"15:orders_model_3.has_model": "fcbcf165908dd18a9e49f7ff", +"16:orders_model_3.has_star": "fcbcf165908dd18a9e49f7ff", +"17:orders_model_3.edge_count": "5feceb66ffc86f38d952786c", +"18:orders_model_3.targeting": "6786f18f6ff42aa577c99d86", +"19:orders_model_3.sourced": "67ac37eb58f45c8042ba79fb", +"1:orders_model_0.has_star": "fcbcf165908dd18a9e49f7ff", +"20:orders_model_6.has_model": "b5bea41b6c623f7c09f1bf24", +"21:orders_model_6.has_star": "fcbcf165908dd18a9e49f7ff", +"22:orders_model_6.edge_count": "4e07408562bedb8b60ce05c1", +"23:orders_model_6.targeting": "f8fbb61b3c961fa2694c9c39", +"24:orders_model_6.sourced": "38e17123b61705a17df7d300", +"25:orders_model_9.has_model": "b5bea41b6c623f7c09f1bf24", +"26:orders_model_9.has_star": "b5bea41b6c623f7c09f1bf24", +"27:orders_model_9.edge_count": "d4735e3a265e16eee03f5971", +"28:orders_model_9.targeting": "67ac37eb58f45c8042ba79fb", +"29:orders_model_9.sourced": "6786f18f6ff42aa577c99d86", +"2:orders_model_0.edge_count": "5feceb66ffc86f38d952786c", +"30:orders_model_1.has_model": "b5bea41b6c623f7c09f1bf24", +"31:orders_model_1.has_star": "b5bea41b6c623f7c09f1bf24", +"32:orders_model_1.edge_count": "4e07408562bedb8b60ce05c1", +"33:orders_model_1.targeting": "18ac30c5dd99f8c1b7a2db88", +"34:orders_model_1.sourced": "6786f18f6ff42aa577c99d86", +"35:orders_model_10.has_model": "b5bea41b6c623f7c09f1bf24", +"36:orders_model_10.has_star": "b5bea41b6c623f7c09f1bf24", +"37:orders_model_10.edge_count": "4e07408562bedb8b60ce05c1", +"38:orders_model_10.targeting": "6ce4efde8f1573118d43d489", +"39:orders_model_10.sourced": "6786f18f6ff42aa577c99d86", +"3:orders_model_0.targeting": "6786f18f6ff42aa577c99d86", +"40:orders_model_13.has_model": "fcbcf165908dd18a9e49f7ff", +"41:orders_model_13.has_star": "fcbcf165908dd18a9e49f7ff", +"42:orders_model_13.edge_count": "5feceb66ffc86f38d952786c", +"43:orders_model_13.targeting": "6786f18f6ff42aa577c99d86", +"44:orders_model_13.sourced": "6786f18f6ff42aa577c99d86", +"45:orders_model_4.has_model": "fcbcf165908dd18a9e49f7ff", +"46:orders_model_4.has_star": "fcbcf165908dd18a9e49f7ff", +"47:orders_model_4.edge_count": "5feceb66ffc86f38d952786c", +"48:orders_model_4.targeting": "6786f18f6ff42aa577c99d86", +"49:orders_model_4.sourced": "6786f18f6ff42aa577c99d86", +"4:orders_model_0.sourced": "75fb8b4ea541b83a96bb78aa", +"50:orders_model_7.has_model": "fcbcf165908dd18a9e49f7ff", +"51:orders_model_7.has_star": "fcbcf165908dd18a9e49f7ff", +"52:orders_model_7.edge_count": "5feceb66ffc86f38d952786c", +"53:orders_model_7.targeting": "6786f18f6ff42aa577c99d86", +"54:orders_model_7.sourced": "6786f18f6ff42aa577c99d86", +"55:orders_model_11.has_model": "b5bea41b6c623f7c09f1bf24", +"56:orders_model_11.has_star": "fcbcf165908dd18a9e49f7ff", +"57:orders_model_11.edge_count": "6b86b273ff34fce19d6b804e", +"58:orders_model_11.targeting": "422c92f9dd61b2ef65dee3be", +"59:orders_model_11.sourced": "623473241d8ca9bda2996980", +"5:orders_model_12.has_model": "fcbcf165908dd18a9e49f7ff", +"60:orders_model_14.has_model": "fcbcf165908dd18a9e49f7ff", +"61:orders_model_14.has_star": "fcbcf165908dd18a9e49f7ff", +"62:orders_model_14.edge_count": "5feceb66ffc86f38d952786c", +"63:orders_model_14.targeting": "6786f18f6ff42aa577c99d86", +"64:orders_model_14.sourced": "6786f18f6ff42aa577c99d86", +"65:orders_model_2.has_model": "fcbcf165908dd18a9e49f7ff", +"66:orders_model_2.has_star": "fcbcf165908dd18a9e49f7ff", +"67:orders_model_2.edge_count": "5feceb66ffc86f38d952786c", +"68:orders_model_2.targeting": "6786f18f6ff42aa577c99d86", +"69:orders_model_2.sourced": "6786f18f6ff42aa577c99d86", +"6:orders_model_12.has_star": "fcbcf165908dd18a9e49f7ff", +"70:orders_model_5.has_model": "fcbcf165908dd18a9e49f7ff", +"71:orders_model_5.has_star": "fcbcf165908dd18a9e49f7ff", +"72:orders_model_5.edge_count": "5feceb66ffc86f38d952786c", +"73:orders_model_5.targeting": "6786f18f6ff42aa577c99d86", +"74:orders_model_5.sourced": "6786f18f6ff42aa577c99d86", +"75:orders_model_8.has_model": "b5bea41b6c623f7c09f1bf24", +"76:orders_model_8.has_star": "b5bea41b6c623f7c09f1bf24", +"77:orders_model_8.edge_count": "4b227777d4dd1fc61c6f884f", +"78:orders_model_8.targeting": "52ad3bd8074b30476404477a", +"79:orders_model_8.sourced": "6786f18f6ff42aa577c99d86", +"7:orders_model_12.edge_count": "5feceb66ffc86f38d952786c", +"80:models": "582bc1ad59a348db0ee52665", +"81:edges": "d24dafbe5842db03ac5ee2e0", +"8:orders_model_12.targeting": "6786f18f6ff42aa577c99d86", +"9:orders_model_12.sourced": "6786f18f6ff42aa577c99d86" +} +] +] diff --git a/tests/goldens/python_oracle/helper_reads_helper_cte_read_edges.json b/tests/goldens/python_oracle/helper_reads_helper_cte_read_edges.json new file mode 100644 index 0000000000..0bdad0d555 --- /dev/null +++ b/tests/goldens/python_oracle/helper_reads_helper_cte_read_edges.json @@ -0,0 +1,58 @@ +[ +[ +"helper_reads", +"aa8cdea031c78169cfcfc8cb" +], +[ +"helper_reads", +"7af39b7194de7feac7d049f8" +], +[ +"helper_reads", +"6786f18f6ff42aa577c99d86" +], +[ +"helper_reads", +"77d5413fc4891929962834c2" +], +[ +"helper_reads", +"aa8cdea031c78169cfcfc8cb" +], +[ +"helper_reads", +"6786f18f6ff42aa577c99d86" +], +[ +"helper_reads", +"6786f18f6ff42aa577c99d86" +], +[ +"helper_reads", +"74234e98afe7498fb5daf1f3" +], +[ +"helper_reads", +"4e5d6ec7534ff80d3cf04e61" +], +[ +"helper_reads", +"aa8cdea031c78169cfcfc8cb" +], +[ +"helper_reads", +"ed29b0da213826917a1d4a41" +], +[ +"helper_reads", +"6786f18f6ff42aa577c99d86" +], +[ +"helper_reads", +"74234e98afe7498fb5daf1f3" +], +[ +"helper_reads", +"77d5413fc4891929962834c2" +] +] diff --git a/tests/goldens/python_oracle/macro_expansion_nested_argument_scan_edges.json b/tests/goldens/python_oracle/macro_expansion_nested_argument_scan_edges.json new file mode 100644 index 0000000000..54a611d00c --- /dev/null +++ b/tests/goldens/python_oracle/macro_expansion_nested_argument_scan_edges.json @@ -0,0 +1,74 @@ +[ +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"ff90ea8ba463db2d44e11898" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"93f71518378ecde91e3e8c8d" +], +[ +"macro_expansion", +"7c07f5f9f04229f65bb035d7" +], +[ +"macro_expansion", +"bda69b2853d37294e288efba" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"1dcc828b6a4485636055d0b7" +], +[ +"macro_expansion", +"1d9a010df82079fdb5727766" +], +[ +"macro_expansion", +"1d9a010df82079fdb5727766" +], +[ +"macro_expansion", +"bda69b2853d37294e288efba" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"829fcd207b176ca0a12986da" +], +[ +"macro_expansion", +"ea0e6e81338954cb22c3c4dc" +], +[ +"macro_expansion", +"8ac37804f4d743d119f825ac" +] +] diff --git a/tests/goldens/python_oracle/macro_expansion_seeded_fragments.json b/tests/goldens/python_oracle/macro_expansion_seeded_fragments.json new file mode 100644 index 0000000000..0885790fdd --- /dev/null +++ b/tests/goldens/python_oracle/macro_expansion_seeded_fragments.json @@ -0,0 +1,12002 @@ +[ +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"8492f5fe387e297ad4ae5dc7" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"0c230469a45e34eec2879b8c" +], +[ +"macro_expansion", +"1b41ba12cab83c0008fda003" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"1d977e28728afd254797939f" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"9f53c356290a8bf357d82841" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"ebdfcc7a63f33420dff4bd19" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"9735456d035ed18ac8c19df7" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"9e1513683e7afcd2f6eb724a" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"e3e7143b3e63312f585ac6e2" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"1b328cda8111fab0b5acfe52" +], +[ +"macro_expansion", +"6502c7a0c709c1a02b6e162e" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"bd2092b5301ca29e9c5fb57d" +], +[ +"macro_expansion", +"a5c98870e77055f4a2a3e593" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"5af7940ab8b00a526f7e590a" +], +[ +"macro_expansion", +"97cfd31d6bf3e8831898c775" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"ea68a93e87ff00698f2e9da9" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"806838ba1b24f48b920a2f8b" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"2e14fa128ea5a6a48f33ad6a" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"476b8d029becdc2995ae4b8a" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"904f44478272ed5db716f5c5" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"cb7d7b30bc4c2b1e440d43ce" +], +[ +"macro_expansion", +"3212231559e8e1ab8d8408bc" +], +[ +"macro_expansion", +"904e1ab6b6adea69bd724ea5" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"bf51cbd252717f3e50590a4d" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"bedadf5ef3c77649b2ad3d3b" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"3e04713305c56ca9c9e92c99" +], +[ +"macro_expansion", +"6a3a2b6f125414f517f0b53f" +], +[ +"macro_expansion", +"0c266313abb6ce7afcf0be4d" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"0c230469a45e34eec2879b8c" +], +[ +"macro_expansion", +"7e57d97967f8de85df429faa" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"2395d4cf572b294a608b7ed9" +], +[ +"macro_expansion", +"b240dfdfbf0045237b40cd1d" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"5dcb5549c75f3c0d832bc21b" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"34fbbf92cb30fddc889428fc" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"bdbaff3eaa5af483e7548920" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"573323ede4bab77ff1f48380" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"dc7a13d13a5fe049636f0a1f" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"95dfecf96aba4125cf28623e" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"5af7940ab8b00a526f7e590a" +], +[ +"macro_expansion", +"2cf111f5cbbd1d08bc2d680d" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"2cf111f5cbbd1d08bc2d680d" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"fcc5f9d933370ac1c60842d0" +], +[ +"macro_expansion", +"f7a839a4af1bb3c0c085f366" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"14ecf6b080f8d1e0e9438a6e" +], +[ +"macro_expansion", +"d106354742d31c732c1b31c0" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"c4e30bf5422f1ed262b3d33c" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"cd6103ee256460b6ec6a523d" +], +[ +"macro_expansion", +"1515bf6a54892ce2cdf79b8c" +], +[ +"macro_expansion", +"0efc5b02fb690ab179ecbf58" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"80b6e57a5fb4b70359eba3f8" +], +[ +"macro_expansion", +"fd20bffb534e79d0fe7302da" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"e98e53e2fcb46a1525144a0d" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"e225408c824413460f58751f" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"7fa145786f24350ccc7b9c8c" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"d1c1a73b04f490391d60d629" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"c0fe5bf61fd0f0eeacb501e5" +], +[ +"macro_expansion", +"7bcac40c0857e84c2618ba3a" +], +[ +"macro_expansion", +"ccc0c057269b20aa4167d477" +], +[ +"macro_expansion", +"40cbc6d635d4415aecc6b764" +], +[ +"macro_expansion", +"c6c00ae654a804c64400c8e0" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"3b30ba4be263603b3f2421a5" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"288900edf7a27180893bfed4" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"0c230469a45e34eec2879b8c" +], +[ +"macro_expansion", +"bf7448f6ad7b94b1d4ab4d2d" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"42ebfbc1551ec293d91d8ebd" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"8e98b1f56eaa480fb3e856db" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"606438a77a147214f7b23530" +], +[ +"macro_expansion", +"c25901dd350bcf008c631d50" +], +[ +"macro_expansion", +"573323ede4bab77ff1f48380" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"f33a55b3d100368891337316" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"9e1522340b61f30407de9fba" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"c2f9a5c557e4b2b3cfee2743" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"ead253babbb3e0543d2cfce0" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"3adcb2bb552c5d5eb8a0e21e" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"eca3fc7a01658e134595005e" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"426de7e3d8e7c788fcf4087d" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"a5c5152975733367bacfad4a" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"9d07dc324ae7a0c50338986b" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"cef7c3a54006d9380fc99b36" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"9e7690091f83a24af6485c69" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"e56091c6a6fafec18d106d54" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"5f6d99f98d0a8ceac64c44bb" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"a7a034363ea97fe48fca7dfd" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"268d15147a2a6ddfd5f54ec4" +], +[ +"macro_expansion", +"12128364177af8a9bdce437b" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"ca141008a95bbef34cae81ef" +], +[ +"macro_expansion", +"d9d6f7586866a8ba2d6cd929" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"e1b20a24241be43a71ffc50c" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"e37f88df43e56c580c0c792a" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"00628c5012d22e71eda04a2c" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"d65d609a0a8539407f4d6229" +], +[ +"macro_expansion", +"adb7b7c3b3fdf0b88ae11f46" +], +[ +"macro_expansion", +"ad70ef0520652c786a077df2" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"230ff736623bef0af8321bdb" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"4edddfbc293d38086e0f775a" +], +[ +"macro_expansion", +"f1953d4d42c374eb2cc0a226" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"fc37a701e2d3d4279097b671" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"ce004a9cc57d9a31acd360f9" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"3951d6f04e3128ead5eae308" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"af4c2dd8de74c30dc9258ef4" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"cae7ed5ea9d501b52ffe5d3b" +], +[ +"macro_expansion", +"aabee86e8e9b92b767a91ade" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"30ea12990cf2bb3eabca5421" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"9bda70785e93c48439cae3d7" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"530373e9240bacfb1911ce91" +], +[ +"macro_expansion", +"7acdf6dd3122748b336fc88d" +], +[ +"macro_expansion", +"8f7759a1ee561a5461f22a17" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"b7d60461f4c405fa8611d54e" +], +[ +"macro_expansion", +"f484e36d98fb308fd8225d8e" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"cf708dee93e8a097ac49c5c3" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"a64f995b374854cddd80419f" +], +[ +"macro_expansion", +"09997a77e24da76e606a9d9b" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"95dfecf96aba4125cf28623e" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"606438a77a147214f7b23530" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"43b4303d27667fc6ba2a53d4" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"9044f28bdaf17b01cc554aee" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"9743438fb82a99f7df805167" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"2372aac9321f9bff66619246" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"4267a558aba31d125a880ca5" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"5af7940ab8b00a526f7e590a" +], +[ +"macro_expansion", +"b950e9fa139763df1b90af42" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"8fb68f98ae0a015ea9168d8e" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"b356bbe167977259c9ce4c24" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"315c91b4b6a6d5bfadcc2414" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"48d6b4a81b6f2a8b581acd52" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"041e46557774f89a01db4841" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"3854350382796f2dcb3a5ef9" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"d453e99dce3639765307c09c" +], +[ +"macro_expansion", +"65e9e8fb80b2c7ea58207ef9" +], +[ +"macro_expansion", +"1bcc45638e9cd7c315398f71" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"3854350382796f2dcb3a5ef9" +], +[ +"macro_expansion", +"3f5e2f385f932d4edc6311d6" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"efd3d1db961e5325f448c3af" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"794cbb4870baca6077a7dd3b" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"5282cc6d3bd1e2bd403db5ac" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"61cede9d44a051c13602fb75" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"202bdf56f293afb18ffce83b" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"9bec430a93ed18b87104b114" +], +[ +"macro_expansion", +"a282bfeeb38c0231588e58c5" +], +[ +"macro_expansion", +"9ce2fdd867deb5a2c7593992" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"e9595e847faf9dcf8bc653ad" +], +[ +"macro_expansion", +"05ae054012fa3356b4ec1b6b" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"6bc422f290e5fcb7528a60fd" +], +[ +"macro_expansion", +"907afea1470f7cc5bfe6901b" +], +[ +"macro_expansion", +"0f82d71af704591cffe51cc2" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"63985dae99cecffe1f8f7893" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"c90ff27d5c30f7e91ca0656b" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"e016c6baeaa86ae6b05c1745" +], +[ +"macro_expansion", +"21d81250d8e5cb403e624414" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"90905294a31a7dc3d53a44e2" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"42bff8a9cf4ea9528c256966" +], +[ +"macro_expansion", +"4a34962aee4df522c5fdd0c4" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"5bbb7a5746fb4f9c8ae3c467" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"ce5ce3261066331ef4cdcd17" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"30bb5cf1625c3005cff147b8" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"c361e6cd5310f78c22612a6d" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"e9488cc04bbbbeb305e58073" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"0efc5b02fb690ab179ecbf58" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"b44f027debfcfb1868da58fe" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"db9491893ddca90825516860" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"9e363021edc0431c23ac5259" +], +[ +"macro_expansion", +"e5eb667b1cb1abb53d1053d3" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"dd88b30af8ccb96a87e508a2" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"a67ec40268712e46048979bb" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"6aa36ddb03b106160706a558" +], +[ +"macro_expansion", +"75459f561d93657103660e62" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"96b4a4b376497b3f31051ad9" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"282e879db9f3821d8d8bad9d" +], +[ +"macro_expansion", +"95dfecf96aba4125cf28623e" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"735b08fc31c2d1280efe0975" +], +[ +"macro_expansion", +"91761b49c6da2c0fd26e1c85" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"c0fe5bf61fd0f0eeacb501e5" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"d940c9b2c3936faae4de250c" +], +[ +"macro_expansion", +"ec11f1066af204257a0da999" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"f7cec8a592d485155cec9c5f" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"00da12d674b27b036c626c39" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"72f6a690c9d424e58a38161a" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"d944663cd44cf64e65a57f92" +], +[ +"macro_expansion", +"50282b149370144e96b77645" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"3951d6f04e3128ead5eae308" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"767b6e01cf542abe2cf83da8" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"54301c4eb45c71958baace82" +], +[ +"macro_expansion", +"a6dee33ce3669ce5450f0f2b" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"fc9091788cfde12a7ba701fa" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"29d31dda5e3a066f4b51bf81" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"6cdcbd4cce635bcff23a5982" +], +[ +"macro_expansion", +"42ebfbc1551ec293d91d8ebd" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"13e11a4eee9f0558c33a6c4e" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"0a4edc72f828e832a0729ff5" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"a6e7b71340e150ee8ed2008c" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"2d169d881f35e2b418f6bdac" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"f08d26a52d463188498a677e" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"95dfecf96aba4125cf28623e" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"282e879db9f3821d8d8bad9d" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"9776ac25855b7168e2f1a4b8" +], +[ +"macro_expansion", +"5d5d4a6ac19fffb6a2f461ae" +], +[ +"macro_expansion", +"d527163e34dc20aeb98939db" +], +[ +"macro_expansion", +"b240dfdfbf0045237b40cd1d" +], +[ +"macro_expansion", +"d686bf0b64732149efa584a1" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"282e879db9f3821d8d8bad9d" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"9ee2ef94efaf270bd8baeb4d" +], +[ +"macro_expansion", +"4b3d9c0c6339bdbba06cc30a" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"0df1cad86e84826907808ff2" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"7c7b65713012d704bde6a882" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"8a50de3d51346b5af3a098b3" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"12de0ce01a4982b5251b1e9b" +], +[ +"macro_expansion", +"4e248c2e631c26a764a5283c" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"fc37a701e2d3d4279097b671" +], +[ +"macro_expansion", +"c73272cf0c295690bbb32e54" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"66baf65da6caede113cc2a54" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"d27ecc7198b1eded8c1a829e" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"1bcc45638e9cd7c315398f71" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"23d8c43f5b697263259ebb8c" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"757d9bb76c0e544011d32efc" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"7bcac40c0857e84c2618ba3a" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"d0e47567e5309ed001efd850" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"3854350382796f2dcb3a5ef9" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"c73272cf0c295690bbb32e54" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"766215f3d9b934bf1e679165" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"c336b9c71a741425e9db0663" +], +[ +"macro_expansion", +"f6c4e58328dae734df2ca799" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"11ffed324804b32211fa5b11" +], +[ +"macro_expansion", +"4ee887e620ec5304baae938b" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"fe6faf65ec9bc3c6d4c1a6da" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"c1b3ce4e9849ee8f8706ea4a" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"00d8424ac205c4e413ca73e0" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"cf0247b1c0b013bf389d4417" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"92b599681b953bd6433db495" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"573323ede4bab77ff1f48380" +], +[ +"macro_expansion", +"39946ca529365c17719f945e" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"5b04379e0c9239b6bacc18ca" +], +[ +"macro_expansion", +"f325c153945afe7d979aaa91" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"613711e7287fe770cbee88da" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"34f95877e0a555ec215c537f" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"0379fb5bf39080ba136b7b19" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"ea010e80dbdfe72b774f670a" +], +[ +"macro_expansion", +"aea57db73579ed2af4a301f9" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"6086226146bbfe67934b0258" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"bf36ba15685b129b87c9ee66" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"3e3453bfc58e03f585377140" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"d952d763ccee06d886f27052" +], +[ +"macro_expansion", +"6dfc7809ae3e71c32c74042f" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"63571aa3049006161341c23a" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"087d097a346559dc2ded9eb6" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"0397a13bcc997e9785b3811a" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"fc37a701e2d3d4279097b671" +], +[ +"macro_expansion", +"573323ede4bab77ff1f48380" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"3854350382796f2dcb3a5ef9" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"42ebfbc1551ec293d91d8ebd" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"151b8b5f3b1969637c598f66" +], +[ +"macro_expansion", +"81a6407d4a3efd1542e4591b" +], +[ +"macro_expansion", +"01aa87a852ff2fcbc9b379cd" +], +[ +"macro_expansion", +"f1953d4d42c374eb2cc0a226" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"d556dc5c94a3229f7d4d8f0c" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"5d933df0e28e49faa145278b" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"d64f4d785182868025b53a4c" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"68c208dc53ccda5635fc0e4a" +], +[ +"macro_expansion", +"bcee600e74d7d69822dd1c1b" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"882c21541c0c1f5bb9f4a920" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"bca7c6f515e3390b1596be86" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"387695025e0631f8721acc6b" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"0dc57fe6f11cf0fa51b7254d" +], +[ +"macro_expansion", +"72e29d14619ebaf708300b73" +], +[ +"macro_expansion", +"2044203bd2540a3d28406696" +], +[ +"macro_expansion", +"1d629067c9a85a8ce906a442" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"3854350382796f2dcb3a5ef9" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"ddbe6f8646e4cb8fcded9658" +], +[ +"macro_expansion", +"282e879db9f3821d8d8bad9d" +], +[ +"macro_expansion", +"3235af865dc17cfa5f49fad6" +], +[ +"macro_expansion", +"42ebfbc1551ec293d91d8ebd" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"1019d9e46ca51caab5e360a3" +], +[ +"macro_expansion", +"a75b0f69f3b085c175e6e07c" +], +[ +"macro_expansion", +"20c65634487dc803237c4acf" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"f3d56b53788b0bef1b076c72" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"9ebc028667916f630c2fd425" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"c73272cf0c295690bbb32e54" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"433b1320e40e009b41d0169b" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"3854350382796f2dcb3a5ef9" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"adf7b73617a5d1987060f08a" +], +[ +"macro_expansion", +"b2c6063f8d3b8854c9a43c09" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"1bcc45638e9cd7c315398f71" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"95dfecf96aba4125cf28623e" +], +[ +"macro_expansion", +"32da0a04e7f91c16d7d224ea" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"0c230469a45e34eec2879b8c" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"d3ac886fe49076058233540c" +], +[ +"macro_expansion", +"73a340634fb335e07be74c69" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"f1953d4d42c374eb2cc0a226" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"a957f5c447eea11c0bf77eb0" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"12128364177af8a9bdce437b" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"4d0f92be00645b8e47db28a2" +], +[ +"macro_expansion", +"2fd06f96b8e1eb3a1b5ec5c8" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"636ebba518f80d5f29958261" +], +[ +"macro_expansion", +"1e5ad78f684d638af97ff4c6" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"43d87665bb5dbef9310e621a" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"16ff947138c04a16088c5ee9" +], +[ +"macro_expansion", +"5897b74c0449d3a4a2dae3e4" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"98c103abcfe4f1bd61ddd37d" +], +[ +"macro_expansion", +"2bd5d2e2b3bf15fff5fa5ac5" +], +[ +"macro_expansion", +"e7bbb38da6e6bece5c29d312" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"3a318527d5a8ef79b3acad0c" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"91bc0a83436abc5379745ef1" +], +[ +"macro_expansion", +"7bcac40c0857e84c2618ba3a" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"43967e9758b7a25a04b9a5cb" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"5e5aa7412202bf4a25971cdc" +], +[ +"macro_expansion", +"50cce66403a054fa2654413a" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"27565b0da62ff1662bd8221c" +], +[ +"macro_expansion", +"71c871bce4b39c8f7211e18f" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"fc37a701e2d3d4279097b671" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"95dfecf96aba4125cf28623e" +], +[ +"macro_expansion", +"cf89ac3f0e6cc3a4053f8549" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"7c7b65713012d704bde6a882" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"4d1cdac664b2ee1fa8fa0d35" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"fc37a701e2d3d4279097b671" +], +[ +"macro_expansion", +"31e6dd03225eb7297caececd" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"95ee75ddc699238b87261603" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"5eac29f758f45303490884da" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"bb93281f586e1a5e212b2625" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"a78b6c3c26727704d3bdf98b" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"406eefda359b87d654a21b81" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"66a3d87c29f6a7da763c4c86" +], +[ +"macro_expansion", +"610c2c6160a3c1565c39323d" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"eb49d93b8b7236da680302a9" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"29cf03922ba1d65aba420297" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"4858450c4bbf8197b55bee96" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"34a3a695b2bf2f34eeac6762" +], +[ +"macro_expansion", +"78e95c23a261f0fbd0da8b71" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"72e787e63126f6c475fcc99d" +], +[ +"macro_expansion", +"2cf111f5cbbd1d08bc2d680d" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"c33b697c1dce1f0ea741b635" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"532da9c5be134097e781503e" +], +[ +"macro_expansion", +"2fd06f96b8e1eb3a1b5ec5c8" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"6a3a281b4166a6e51d52e8e6" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"339e526db6ef1a3e95cd3797" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"4d93abe9f51870e0795fef0e" +], +[ +"macro_expansion", +"14590c322ba20c645e9fc9fd" +], +[ +"macro_expansion", +"c73272cf0c295690bbb32e54" +], +[ +"macro_expansion", +"573323ede4bab77ff1f48380" +], +[ +"macro_expansion", +"b7ae6d5039eabf2d9f46d886" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"e4fe72ccb30e6e29eedb0cd3" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"b240dfdfbf0045237b40cd1d" +], +[ +"macro_expansion", +"478fb9ebc2d6633ee6f873be" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"644729663b19b456c400455b" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"a03f29f23122d71d8a0ea1b6" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"a37f9e852614334d1406db2b" +], +[ +"macro_expansion", +"112838a70f21bf971162ca3d" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"c7aca1bde5b37aa3826586eb" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"0efc5b02fb690ab179ecbf58" +], +[ +"macro_expansion", +"d649c46a230a88850c2c597f" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"8a8369c06404ff94937e6ca3" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"b02dcd5ebf1991bc19ecb141" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"50cce66403a054fa2654413a" +], +[ +"macro_expansion", +"eacdf4ea5db402c38b52fa3d" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"16f940d0bf1c3e117bbef9f8" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"258fccf1c97ef037dab74a86" +], +[ +"macro_expansion", +"2abadf304a71f2231d8ae0d2" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"4ee887e620ec5304baae938b" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"3b649768b4abe83d62ff56df" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"8e62dc0ca88856e26701d82d" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"f1953d4d42c374eb2cc0a226" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"de0736cf0d504840cafe2b43" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"3398acd17fb9b190a4f2d9f3" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"50cce66403a054fa2654413a" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"ad10e72968973f4149d54dfd" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"7b8b9b2ee0dfefb04809229b" +], +[ +"macro_expansion", +"f242ebca9bedd3e383a01845" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"e290f3ea906df7e037734fba" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"23db4bd63693a9560447c1f0" +], +[ +"macro_expansion", +"84bd5dc79017f77ef2bb22e6" +], +[ +"macro_expansion", +"26285f79acad0374be3d36c8" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"de822acdc5dc04706e31246e" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"bedadf5ef3c77649b2ad3d3b" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"c086a84c955083cba0a0751a" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"849555d449d7c6ff911629df" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"9df95ec2ac0de265ee7ac012" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"9c5838ad06dd051a008654ed" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"0f115d892b2f0f26514a8bf5" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"9f373385134941b8921a8f2e" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"ff5d2950ff9db93464cec0c8" +], +[ +"macro_expansion", +"8edf6cb5607b23bdbe1b6e17" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"573323ede4bab77ff1f48380" +], +[ +"macro_expansion", +"735b08fc31c2d1280efe0975" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"8732ce85f4553b86511a432c" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"dac1f00734838fa3881c7436" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"b240dfdfbf0045237b40cd1d" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"250be9ea3ae07816a2d4160d" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"543b1ce26cc6c79fcc591548" +], +[ +"macro_expansion", +"4ee887e620ec5304baae938b" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"4ee887e620ec5304baae938b" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"ce9920b0a0317f1464d78830" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"7fdaad1e670392e2ad1db597" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"bf5bad3bea71a4b1dd3e14e6" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"0c230469a45e34eec2879b8c" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"95dfecf96aba4125cf28623e" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"2b6cc6cda06fee90f3435146" +], +[ +"macro_expansion", +"e07f13aa84fb5b885af85a8b" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"b93a3342280f70503b8a8469" +], +[ +"macro_expansion", +"0055252313377ae62a620c69" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"3df2b8aa17bb720ea7762527" +], +[ +"macro_expansion", +"20c65634487dc803237c4acf" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"f151bc2e5824362d79ab715f" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"138e275a602413ffaf9de95a" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"1bcc45638e9cd7c315398f71" +], +[ +"macro_expansion", +"bbbee8807e67ec3e6c5bcb89" +], +[ +"macro_expansion", +"e6693e7bcf4339234917c079" +], +[ +"macro_expansion", +"666fe5f7ebca1f93891a7ca1" +], +[ +"macro_expansion", +"9743438fb82a99f7df805167" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"df4aee3ab175d2a88c959922" +], +[ +"macro_expansion", +"a563272efaf8c431c05cce88" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"50cce66403a054fa2654413a" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"bc811c5e961e8838e3e1ffc1" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"669f3530de2c9270fc3535e3" +], +[ +"macro_expansion", +"fe74b1e5bf2f68bf4f5e85bd" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"4d987f8eeb2873cd14c9550c" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"20c65634487dc803237c4acf" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"c73272cf0c295690bbb32e54" +], +[ +"macro_expansion", +"6d4bf74e857b3bb3c44e7a88" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"05d13d7f04ad308da56452aa" +], +[ +"macro_expansion", +"349cdee64721f2854ccc6005" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"0eaa441b753a3ca0df83893c" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"5a4640edd1593ad2d6ca54c1" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"2cf111f5cbbd1d08bc2d680d" +], +[ +"macro_expansion", +"7261719a85eb5092ad9fe476" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"0d47f3df4eafd08b678da0f0" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"c7d10ac2524cb1a6fa0d643d" +], +[ +"macro_expansion", +"6493c305c2da00b0fbc28a71" +], +[ +"macro_expansion", +"38514c09275d323d08251a4d" +], +[ +"macro_expansion", +"20c65634487dc803237c4acf" +], +[ +"macro_expansion", +"eac0564995737c83726622f3" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"3951d6f04e3128ead5eae308" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"975204688cf736f862e7f945" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"00743f79e70fd01297ff6588" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"8dc55647bac833692e333965" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"f1953d4d42c374eb2cc0a226" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"cfaee72fcbcd0a7d7f29984b" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"19231737737bfd80a4281a0c" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"d0aecc46fc3df425c1354b8e" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"27abca1ee74aa0693f203ebc" +], +[ +"macro_expansion", +"d6307e35e5376f92eb11bdcf" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"14ac38b50007d4bafc3590e9" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"e809cea57eaaef5cadd306ba" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"a9c5261e9283f88b038fd905" +], +[ +"macro_expansion", +"6f420309cb12642f387739f7" +], +[ +"macro_expansion", +"a859ad5dceaa1db72e7613bb" +], +[ +"macro_expansion", +"41d82d8d6bd7c825e165ecec" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"fd7eb1ad7b15865b2b770e31" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"6edcc18c34141bab7c1fba33" +], +[ +"macro_expansion", +"5a7520160ae82ec9b3955635" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"a91d3dfe6c9c9a595464b585" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"d5d296fd1ea1c044d2c13580" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"6edcc18c34141bab7c1fba33" +], +[ +"macro_expansion", +"c8a73c2a0a7c76182c64b25e" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"381da973073ea7c3d8d19d71" +], +[ +"macro_expansion", +"fe6faf65ec9bc3c6d4c1a6da" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"f1953d4d42c374eb2cc0a226" +], +[ +"macro_expansion", +"181440fc2852fa01e2cdc802" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"e20f741655fa9e1f4f4e30de" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"bad8df050a71f06367788974" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"0548448b8a0f98d9db57dadf" +], +[ +"macro_expansion", +"ff91c7071a4fd7c4097944ec" +], +[ +"macro_expansion", +"3f1801b11fcbbbb2bc2c5382" +], +[ +"macro_expansion", +"12128364177af8a9bdce437b" +], +[ +"macro_expansion", +"eb6ff5b555cdbff56ea34a4e" +], +[ +"macro_expansion", +"f0b31385bab8a3dbfb29a5e0" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"9ac2cd0b5b4155ec31cdeb0e" +], +[ +"macro_expansion", +"c46518cbe4c4007dc3179017" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"db648a62c7f800e953725973" +], +[ +"macro_expansion", +"12128364177af8a9bdce437b" +], +[ +"macro_expansion", +"a64556b3e76ee618baf546b0" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"f237480591a7d48db97b3f3a" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"d7fdcef38bc9d24c57989803" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"65dfacb21e97ca40c55876d1" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"c6acfc7f468c1ba2eb471dca" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"87c9142a265b1b9c5a8ac02f" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"0c230469a45e34eec2879b8c" +], +[ +"macro_expansion", +"70e8ab1e3ac17dc017271d9c" +], +[ +"macro_expansion", +"30bbdef47820b1bfc0c021b0" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"20c65634487dc803237c4acf" +], +[ +"macro_expansion", +"573323ede4bab77ff1f48380" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"04d0a903a3dbdbb03f03f513" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"adf7b73617a5d1987060f08a" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"fc37a701e2d3d4279097b671" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"c3f6bb293307054e98f53c06" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"2d27cba3a17204c7441b7dbf" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"d556dc5c94a3229f7d4d8f0c" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"573323ede4bab77ff1f48380" +], +[ +"macro_expansion", +"9ca3a8196b47db1f866f8be2" +], +[ +"macro_expansion", +"2307f2e5b07e0f2310d20c0a" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"7789c815eb1826794f1b6bf9" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"34a9d99ba32f73a693d0c4ac" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"95dfecf96aba4125cf28623e" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"537b1f0f8eafb363031b9862" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"65a805104d05e2b7ef352e64" +], +[ +"macro_expansion", +"c8702ba41c13f97821dfffa2" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"0e56638581cd087e49b6e59a" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"2d78f4fe8140113336f2f0a9" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"c0310883054b2b64958f1254" +], +[ +"macro_expansion", +"f0acb75e5e509e8ddd200884" +], +[ +"macro_expansion", +"9230083b66fead2b3bff7406" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"d1f9935484c75a11030106aa" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"4550c3058201b6fcd4151bf9" +], +[ +"macro_expansion", +"8397345bd749f67b0034e20a" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"f246b7c71a000dd83fe155e2" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"95dfecf96aba4125cf28623e" +], +[ +"macro_expansion", +"ec6ab80d54779a396ef4960d" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"e09c7be51b790fc1fd5e0648" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"c73272cf0c295690bbb32e54" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"36b6375e2241e89a936c0ce4" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"d04beb21a6f06c08af95d3a2" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"42ebfbc1551ec293d91d8ebd" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"ad749b5782299ef54e318192" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"d8dbbe954bda38b67a660a16" +], +[ +"macro_expansion", +"50b8dad468bae9538fc6c972" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"22fda6f8abb675dd60f6f4d9" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"282e879db9f3821d8d8bad9d" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"87d34dbe3a128787f05a8fb7" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"505e19d74a9b7b1e87dbec4b" +], +[ +"macro_expansion", +"9459aa90a392fb6b3da91501" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"e9a3c2cda95f42b5dbb7887b" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"f49dac27ed6e24cca9e76e6d" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"b66a4c321fb61aaca71e23a6" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"282e879db9f3821d8d8bad9d" +], +[ +"macro_expansion", +"ab03b1fbf84be96cd5ba6586" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"42ebfbc1551ec293d91d8ebd" +], +[ +"macro_expansion", +"ee8ac40262482b1292128fe7" +], +[ +"macro_expansion", +"56fc5dc9cb9c91aa949287c3" +], +[ +"macro_expansion", +"96c726415f44932183c1d3eb" +], +[ +"macro_expansion", +"708163c2d2a34e794fba3f23" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"04da2d68d5c949d16fee7831" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"b4bdbebedb94e92ffbe940fc" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"58b8c6cca568121e9fc3dfde" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"0549fab64641856555cec2ef" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"91bc0a83436abc5379745ef1" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"4c5ff3d596c02ac182847ee2" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"14cd47a33915178e478fca98" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"0744a16007480c5b127d7fef" +], +[ +"macro_expansion", +"28afbcd777e0b8e85ae6e83b" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"ab069beb29b1048b45d06ca5" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"12128364177af8a9bdce437b" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"6f7604a2682ae69e368f24ba" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"fa0df3f596a4f346230f433d" +], +[ +"macro_expansion", +"153cd9587b527d150225536c" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"c41157f595fb76cea0f76a16" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"8007aa8f04269b9f9aab0953" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"74fa1a89e5281bf446a53ac1" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"573323ede4bab77ff1f48380" +], +[ +"macro_expansion", +"e73ef0365857a5f8039024c4" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"a7d91066991331f02271e03c" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"7bcfe657ac8be4dc42287db0" +], +[ +"macro_expansion", +"fa982fa800374cd84e0fabf5" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"e8cf0d83de10936cd912a7d2" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"42ebfbc1551ec293d91d8ebd" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"50cce66403a054fa2654413a" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"bb747358561d926311e399ec" +], +[ +"macro_expansion", +"31678d1b96db7108fb4c96fe" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"c6e03b4bce40490b50fe5ea9" +], +[ +"macro_expansion", +"3216b16dfe54254bacb6fffa" +], +[ +"macro_expansion", +"7f174926143f1c0b29b45daf" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"cf678a2a66285cfbcf783827" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"91bc0a83436abc5379745ef1" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"cb475022f139466fb6e8f47c" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"95dfecf96aba4125cf28623e" +], +[ +"macro_expansion", +"e30dbdd55aba068730502480" +], +[ +"macro_expansion", +"3f1cafeb89ec76e6a0400412" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"2bd03a3362e9cac96dd0690d" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"c796f22f6b407c2faf93f4c3" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"2af83e772005de18b7ba7982" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"56840d920cfd040cde42282d" +], +[ +"macro_expansion", +"ab03b1fbf84be96cd5ba6586" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"91d0efa04f5eb2372beb8a3a" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"92ba4cd3f6a685df708c8e4b" +], +[ +"macro_expansion", +"745d473f3ed85a4a92502aa3" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"6d2685ca9e6bc22e6b790497" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"29fc33f4129f46edd947b09e" +], +[ +"macro_expansion", +"f92b54db9d030238b610128c" +], +[ +"macro_expansion", +"995afbc74b727ba9eac8b38a" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"f1953d4d42c374eb2cc0a226" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"bedadf5ef3c77649b2ad3d3b" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"3ce696cdfd84a1df26209a20" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"596c63429642c6299df023c7" +], +[ +"macro_expansion", +"50cce66403a054fa2654413a" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"2cf111f5cbbd1d08bc2d680d" +], +[ +"macro_expansion", +"6603fc6c4e0c6c5fc98171a2" +], +[ +"macro_expansion", +"4c1312f7546296273520e7f5" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"766215f3d9b934bf1e679165" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"e67a3a23038cc8c7303f8a39" +], +[ +"macro_expansion", +"6edcc18c34141bab7c1fba33" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"0c230469a45e34eec2879b8c" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"b63075bed3ff08308cc8f396" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"6e8a2d86c99dc15372172cad" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"493fcf8f424e072422a37edb" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"cb45ba71891316da00ec2634" +], +[ +"macro_expansion", +"c73272cf0c295690bbb32e54" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"adc75266412502cf10a392fa" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"acc4ec17882f296486c7e9f7" +], +[ +"macro_expansion", +"fc37a701e2d3d4279097b671" +], +[ +"macro_expansion", +"4538950d3b7c71d733b6b40b" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"91bc0a83436abc5379745ef1" +], +[ +"macro_expansion", +"c3396094b46dfbfca6713f71" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"6edcc18c34141bab7c1fba33" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"95def6b19a55ac2fb3bd01b1" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"ffe2157e418fc118e559fc78" +], +[ +"macro_expansion", +"4e34059d10f9b87d7c3deb78" +], +[ +"macro_expansion", +"12128364177af8a9bdce437b" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"766215f3d9b934bf1e679165" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"f1953d4d42c374eb2cc0a226" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"2d069b17a6d425091b1bddab" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"fb9d3555231be734c49749f5" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"313c42fe5b24af8225a754df" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"d28ce918ebecdf9464ca87a1" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"f25fb126e7a4adcab3dc11a1" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"b240dfdfbf0045237b40cd1d" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"1af19be251280ffe407b322c" +], +[ +"macro_expansion", +"1dc9207aefd2b4be6b224007" +], +[ +"macro_expansion", +"25a667fb1bb37a750bd958da" +], +[ +"macro_expansion", +"758f83b95bad59c14ecef42d" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"ebb78a63bced258d61484a48" +], +[ +"macro_expansion", +"d7ab80dc7ffef128375dbf12" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"8639e91e97492e81db9d0380" +], +[ +"macro_expansion", +"18e40a106446b22fa2abfd22" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"0e10d1591e0ea53582b8f9b0" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"a50785b9a8c65dc0341aa076" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"ecb57fc615749aed99172a04" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"80c6db09a5598755fdfae58e" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"4ec5893b37b14fd30f991abc" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"cbb141993cb3bccf9def83a7" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"8037fa44692d1eed510ea768" +], +[ +"macro_expansion", +"f50e25828a82c45f2343b227" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"c6aaabbc9280b9e469ed80a0" +], +[ +"macro_expansion", +"44abb6aa51d53866c583442c" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"8b7fe3beb76ab74ec2fa14a2" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"cacdfd52efbc506797837a67" +], +[ +"macro_expansion", +"d29b77fab08ba75b3a2ad1d9" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"81c1f8f616ec4254a66bb251" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"2e5ba9a82bcc78b5edd50ba8" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"066cc151ca00b76272d9ed3e" +], +[ +"macro_expansion", +"f7e618dc56eb5f62166c627b" +], +[ +"macro_expansion", +"6edcc18c34141bab7c1fba33" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"2de7e05291001cf6f82820e8" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"45b092eb05e9998555eca874" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"3a318527d5a8ef79b3acad0c" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"7cf5985adf472ff3b0f7e064" +], +[ +"macro_expansion", +"57ced0758458bb9c815278f3" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"91448bc85ff5bf37da4e2ddb" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"735b08fc31c2d1280efe0975" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"708163c2d2a34e794fba3f23" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"0c230469a45e34eec2879b8c" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"0efc5b02fb690ab179ecbf58" +], +[ +"macro_expansion", +"c73272cf0c295690bbb32e54" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"3951d6f04e3128ead5eae308" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"a7ca01bea83e83970857048f" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"2b44cfb903eccff556fa0231" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"2cf111f5cbbd1d08bc2d680d" +], +[ +"macro_expansion", +"1290db62a86f5196c70db736" +], +[ +"macro_expansion", +"12128364177af8a9bdce437b" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"20c65634487dc803237c4acf" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"a097b5e93e20fc520b926be1" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"2cf111f5cbbd1d08bc2d680d" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"7bcfe657ac8be4dc42287db0" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"5f4b41f6c2f154e8cfb5c26f" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"a577476dca83c194229d517b" +], +[ +"macro_expansion", +"bedadf5ef3c77649b2ad3d3b" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"344c343ab950c3b98cb6d972" +], +[ +"macro_expansion", +"5ac75025966e75abfd12d6a9" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"d6b4103375ad6ea870edfa1e" +], +[ +"macro_expansion", +"25f366f42199dd40c0766d10" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"f41f6772410d7f36bf97789a" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"8882bae993871070ad84c423" +], +[ +"macro_expansion", +"70ad91a0d9e6491d32ea726e" +], +[ +"macro_expansion", +"37ae90f053003a66661aa613" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"573323ede4bab77ff1f48380" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"bedadf5ef3c77649b2ad3d3b" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"6b823ffd6cb176dd32f41977" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"eedd92f6e33d1c9cc7838b0c" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"e131d98a9612df4edf0b3fc7" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"8b63f1609cafbab226b3af4f" +], +[ +"macro_expansion", +"c2f5a04352ba7270126b51e5" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"a270a6019369cf9d4e56d176" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"8b9371c390920b87e859fae8" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"c20bf40e32939f0a37e8f235" +], +[ +"macro_expansion", +"0efc5b02fb690ab179ecbf58" +], +[ +"macro_expansion", +"bd58a8e4cd096652f40ef732" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"0a8c0adbe729b5509f0c3a11" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"50cce66403a054fa2654413a" +], +[ +"macro_expansion", +"066f9f43296b1b2b28d782a9" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"744e5ebcb3aff2861135b53c" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"5dabbb70b40f259a0822f923" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"914587ed7b3250e62e270400" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"3854350382796f2dcb3a5ef9" +], +[ +"macro_expansion", +"bf1fd53a9d64160540ce9c29" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"e89288bbb924140884103452" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"c4ac13b2ed3448e47247bf51" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"12128364177af8a9bdce437b" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"9c2bc7cc62c666d9310f5ba6" +], +[ +"macro_expansion", +"d07386a1e5853201a3540a62" +], +[ +"macro_expansion", +"fed4b9630c80355e45c265be" +], +[ +"macro_expansion", +"09a088163d78ecda97033052" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"b804390cca1ab409b4c031e5" +], +[ +"macro_expansion", +"1a0710757a3fb2096f8bcf2d" +], +[ +"macro_expansion", +"bbed1c8f456d2d2ec0bc9f80" +], +[ +"macro_expansion", +"fa72da5603764a4bf3082971" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"b233f3ff5557cec77d5df249" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"2036ec4101a7cc976cb4af2b" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"387752d70fb7cbc7ce7db350" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"7c7b65713012d704bde6a882" +], +[ +"macro_expansion", +"d556dc5c94a3229f7d4d8f0c" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"766215f3d9b934bf1e679165" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"4a9a55b14f46d8461e4c4832" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"880b3b548c60ab8b15406d09" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"2e746ddbb634a85c18e816c0" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"c96d42cd2386a2d8c0b5a089" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"519255c2087d8c6708f79b16" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"aa7325c877fa94e46cd8931f" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"21857229d71e36d71e7b1bc3" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"7ddaf007022badc73e3c6e2f" +], +[ +"macro_expansion", +"b8ad7c906f6ac9f1a15946b2" +], +[ +"macro_expansion", +"0c230469a45e34eec2879b8c" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"d8e0594005d7f0906aefa669" +], +[ +"macro_expansion", +"b9ac8861ec1a0f78edb38129" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"b706c171d854c0878ee5f484" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"9f21f08f876e2cc418e3a4f4" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"2b370695d470b91d4019e3d5" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"0c230469a45e34eec2879b8c" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"00743f79e70fd01297ff6588" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"c0fe5bf61fd0f0eeacb501e5" +], +[ +"macro_expansion", +"39f96360548d052d01ec8fa8" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"c899f58121894b2bb80cc431" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"c4ac13b2ed3448e47247bf51" +], +[ +"macro_expansion", +"77bbc7f31496aea3a9c2b1d6" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"1976b6ce0075f4829eac7ade" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"b25636ebbf0e1830abdeeca8" +], +[ +"macro_expansion", +"1b42bb9b4f36e7c6bd990aca" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"8850168eaae50b974ebb7a64" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"12128364177af8a9bdce437b" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"8db6bbe77a8e14d45881eb67" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"4fa1dae22197bde7ba4d60bf" +], +[ +"macro_expansion", +"ad933b77748af43e2bc7e80c" +], +[ +"macro_expansion", +"b240dfdfbf0045237b40cd1d" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"e1998760a5347544a55123b2" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"8cf3ec4830de80e5c8ee30aa" +], +[ +"macro_expansion", +"d2083ad25bae0a748155e094" +], +[ +"macro_expansion", +"ff3562cb938baeccd8039b40" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"20c65634487dc803237c4acf" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"4738fac9196a87f01bf9010c" +], +[ +"macro_expansion", +"1e8183f68adf538b0180c605" +], +[ +"macro_expansion", +"72a7856a8dd186a82cb9b520" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"95dfecf96aba4125cf28623e" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"c1fac7cbf25354e4399e3f4e" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"71caaaac9301c8b902ca3780" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"70ded8434da4e9bd19af76b6" +], +[ +"macro_expansion", +"b5a89cc16f59a47768bf3427" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"7ae3476d2be61f9a83e0f922" +], +[ +"macro_expansion", +"adf7b73617a5d1987060f08a" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"adf7b73617a5d1987060f08a" +], +[ +"macro_expansion", +"86a7f614de860ea788eb7c56" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"4ee887e620ec5304baae938b" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"a9148d91ac2e665279c7c0e0" +], +[ +"macro_expansion", +"bac2a2c6ef3b17fd35f15b87" +], +[ +"macro_expansion", +"af2ecf9f087e54beedeb3efb" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"42ebfbc1551ec293d91d8ebd" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"e97f86b46776ced7f3ca46c0" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"0ce7db57c7405f7fd9a15732" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"fc37a701e2d3d4279097b671" +], +[ +"macro_expansion", +"766215f3d9b934bf1e679165" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"a9f6965e2512ba90b24e8f65" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"50cce66403a054fa2654413a" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"ef70f41a57ccba12f7375d9f" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"e81e229c44884a9ccb7f5d94" +], +[ +"macro_expansion", +"f1953d4d42c374eb2cc0a226" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"41456a90e056f4aaf5e0911d" +], +[ +"macro_expansion", +"91bc0a83436abc5379745ef1" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"5ccdce86c1ed7c5c277ca64d" +], +[ +"macro_expansion", +"aa4b4485077e90ba5e9c8324" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"735b08fc31c2d1280efe0975" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"2cf111f5cbbd1d08bc2d680d" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"8705603e6f5b44c3dda62eb0" +], +[ +"macro_expansion", +"a5ac5fdea8afa6b3b4e72b63" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"28eb402bf54d3451b17edd07" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"53e56a7403823277db61c8ef" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"7828f85a1ea610377560a7b4" +], +[ +"macro_expansion", +"40ecfe9e3f42575feb463f70" +], +[ +"macro_expansion", +"1bcc45638e9cd7c315398f71" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"fc37a701e2d3d4279097b671" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"6c04a4931640af6c62eb2fda" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"85588074e74837d186fbde4d" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"146079cc71b242d162abe6ba" +], +[ +"macro_expansion", +"a54102a11027175e3f4d3dd1" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"aad199d3b7ccdcc9c43c67fa" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"bedadf5ef3c77649b2ad3d3b" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"f1953d4d42c374eb2cc0a226" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"a9ff75fcd2601600ad8bfdf7" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"808ce9d6eb59cd3baa6f448f" +], +[ +"macro_expansion", +"0615e4fdd3c5135a2e3f3db1" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"3854350382796f2dcb3a5ef9" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"18224741933d84735e8c3345" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"7df52d1231c5454d77579169" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"bedadf5ef3c77649b2ad3d3b" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"42ebfbc1551ec293d91d8ebd" +], +[ +"macro_expansion", +"e13084549a40032a2c756aa1" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"7ef6feee59b86d669b5dfa4e" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"049a70c66a1dffaa8aff4e0b" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"18b7998b302ed083f943c5a4" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"a7a82142610ac883c6513e9b" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"c0fe5bf61fd0f0eeacb501e5" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"f3a186535d099608c832e2d8" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"3854350382796f2dcb3a5ef9" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"2d2be85d7b705ee69520f033" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"45f916243d6b5c85d1c1eb90" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"73aec4bca23b2f11791f3809" +], +[ +"macro_expansion", +"6dbba6958f7989e6d287cce6" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"e5e06a040d302f30a06c75cd" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"847066ca718b1fef56dbff64" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"87375f34cf5985036a42b98b" +], +[ +"macro_expansion", +"bfaadea0fc474bf6f954c9d3" +], +[ +"macro_expansion", +"adf7b73617a5d1987060f08a" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"d4e589adf0aeff647b5ffb96" +], +[ +"macro_expansion", +"96f3d99ff7407f5e50cf8226" +], +[ +"macro_expansion", +"fc37a701e2d3d4279097b671" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"4062cb6f81dd97301652f3ae" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"641accd0e6a36b4a712b828f" +], +[ +"macro_expansion", +"cace2f3ae0d36fe09d93f30a" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"333085a1d4f7733d849e1615" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"3558585e300e9f78d1d98610" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"8c9c8288479c03bb26b53989" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"282e879db9f3821d8d8bad9d" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"df054836981181079fdb1e23" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"8487af99c90d0cff829dc1e4" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"c0fe5bf61fd0f0eeacb501e5" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"573323ede4bab77ff1f48380" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"c73272cf0c295690bbb32e54" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"4efd59cfcc27d0185bef5492" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"227554d7184c4c824d7d9d85" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"7fa145786f24350ccc7b9c8c" +], +[ +"macro_expansion", +"6edcc18c34141bab7c1fba33" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"3649f6fe51ee9bf5bc61388e" +], +[ +"macro_expansion", +"8a53bfbad06c12ac937c5455" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"f223e62fd2bd28e21122dfb6" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"c0313345b5784b21baaf8b50" +], +[ +"macro_expansion", +"b040ddd442aa425a60f490cd" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"08867085ba3bc8ceab44c3e9" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"9a4e18e87760ade7db04ce4a" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"1a54bb06fe13478f03561dca" +], +[ +"macro_expansion", +"91bc0a83436abc5379745ef1" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"9320c79605d5f8f20f4f3900" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"80212d7b41eaf9dfb155e60d" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"447ca12d238dd43d6cf1d95f" +], +[ +"macro_expansion", +"710bdf26b1de9dacfff88df7" +], +[ +"macro_expansion", +"2bb4206306d572449528a7c2" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"ea6b40f2657cb4771447efdd" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"c165f08eb88e6d00006e05d9" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"735b08fc31c2d1280efe0975" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"25671f6b231d223979810296" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"95dfecf96aba4125cf28623e" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"fc37a701e2d3d4279097b671" +], +[ +"macro_expansion", +"fa9e39332847981e30b5cca4" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"e7c0fe9380a0201611fa5c6b" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"7c78d92c5e142131169759d6" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"fa3835aa2ea2380630dac4df" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"b240dfdfbf0045237b40cd1d" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"44b3c3adb885402b7f69188e" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"b881f2bf0e0305083986d059" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"ac936e3b930d7120425ccf2d" +], +[ +"macro_expansion", +"5e89dcfcddfc6ce859dbd9c4" +], +[ +"macro_expansion", +"006a2a36ae299628bf10134f" +], +[ +"macro_expansion", +"5432b9ee174fc51fcf1dcc76" +], +[ +"macro_expansion", +"92b6f68fdb316b8cc086eaa8" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"57853e2b33d99e83608fe8db" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"12e6c97b73d702dfa251a0d4" +], +[ +"macro_expansion", +"16ff947138c04a16088c5ee9" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"dd1d161e1c86ac30d9a698fd" +], +[ +"macro_expansion", +"46a3271f4ff67656bf00cbf1" +], +[ +"macro_expansion", +"90b9145be8158b3c3756dad9" +], +[ +"macro_expansion", +"3df0f02d5862f8e508ca1b8f" +], +[ +"macro_expansion", +"157bff5a86f07eea0bf7b8d1" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"4240447b25b4c3e66cb9d165" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +], +[ +"macro_expansion", +"6edcc18c34141bab7c1fba33" +], +[ +"macro_expansion", +"f1f833fc0def352bfaed9e4c" +], +[ +"macro_expansion", +"fea4e2213e8e44ce19e18c73" +], +[ +"macro_expansion", +"ace5e876fb1ebaa1aa0bb767" +], +[ +"macro_expansion", +"1a7a4ebf8e788582eea12c43" +], +[ +"macro_expansion", +"70cefe52ce63334596757a57" +], +[ +"macro_expansion", +"5aac3de3214439ab08b7af7a" +], +[ +"macro_expansion", +"ffa947079a883f1805686b58" +] +] diff --git a/tests/goldens/python_oracle/metadata_formerly_deferred_non_ascii_names_and_comments_new_and_unknown_dialects.json b/tests/goldens/python_oracle/metadata_formerly_deferred_non_ascii_names_and_comments_new_and_unknown_dialects.json new file mode 100644 index 0000000000..c1e0c0cba7 --- /dev/null +++ b/tests/goldens/python_oracle/metadata_formerly_deferred_non_ascii_names_and_comments_new_and_unknown_dialects.json @@ -0,0 +1,42 @@ +[ +[ +"metadata", +{ +"None": "257eadf2980dd54d687bb376", +"duckdb": "d1d66a9dd0325471cc034afd", +"mysql": "257eadf2980dd54d687bb376", +"nonsense": "6f6079f31e12e028922d40f2", +"tsql": "257eadf2980dd54d687bb376" +} +], +[ +"metadata", +{ +"None": "c9f66e2829627aeb5e4728db", +"duckdb": "0ed0773a2a4a6fca23c1dcac", +"mysql": "c9f66e2829627aeb5e4728db", +"nonsense": "6f6079f31e12e028922d40f2", +"tsql": "c9f66e2829627aeb5e4728db" +} +], +[ +"metadata", +{ +"None": "a86fc9ef8fd7f46e7110dff4", +"duckdb": "30c78fd5afb3d05479d6c4ca", +"mysql": "a86fc9ef8fd7f46e7110dff4", +"nonsense": "6f6079f31e12e028922d40f2", +"tsql": "a86fc9ef8fd7f46e7110dff4" +} +], +[ +"metadata", +{ +"None": "9225fd40168382c4100e98c3", +"duckdb": "55da090c1795767af58252eb", +"mysql": "9225fd40168382c4100e98c3", +"nonsense": "6f6079f31e12e028922d40f2", +"tsql": "9225fd40168382c4100e98c3" +} +] +] diff --git a/tests/goldens/python_oracle/metadata_generated_function_calls_config_references_cursors_audits_and_sql_tests.json b/tests/goldens/python_oracle/metadata_generated_function_calls_config_references_cursors_audits_and_sql_tests.json new file mode 100644 index 0000000000..97b71711ec --- /dev/null +++ b/tests/goldens/python_oracle/metadata_generated_function_calls_config_references_cursors_audits_and_sql_tests.json @@ -0,0 +1,74 @@ +[ +[ +"metadata", +{ +"bigquery": "3a936fb881b69845cbf281ea", +"duckdb": "3b771f6b2fe8c3590fa58424", +"postgres": "b0a7df99618a9706e15fffef", +"snowflake": "b0a7df99618a9706e15fffef" +} +], +[ +"metadata", +{ +"bigquery": "0a4ff65b0383da513b81728e", +"duckdb": "0347352e059171438345cdc3", +"postgres": "6fc977a6058882760800a845", +"snowflake": "6fc977a6058882760800a845" +} +], +[ +"metadata", +{ +"bigquery": "6188d55225fc3355ee350d93", +"duckdb": "7f34dcf40c6392f554ea91da", +"postgres": "2e203d99e28ab5cbdfd8cfb6", +"snowflake": "2e203d99e28ab5cbdfd8cfb6" +} +], +[ +"metadata", +{ +"bigquery": "c582c97bec0387c38abb4d4d", +"duckdb": "5248ff1ce3518aeed27d1ecd", +"postgres": "94e4aae33c04503253db41a4", +"snowflake": "94e4aae33c04503253db41a4" +} +], +[ +"metadata", +{ +"bigquery": "d1229780b7935d9acac4c6fa", +"duckdb": "f58eecbca144a88bbd6c7eef", +"postgres": "ad4229629c684797c3e9e363", +"snowflake": "ad4229629c684797c3e9e363" +} +], +[ +"metadata", +{ +"bigquery": "8a38d3db16cbefe4251c8244", +"duckdb": "d3057408147f96cf1aef3b61", +"postgres": "8bd1331b85712d5a5bed65b2", +"snowflake": "8bd1331b85712d5a5bed65b2" +} +], +[ +"metadata", +{ +"bigquery": "76c9a91c06ccf970b8cf8823", +"duckdb": "30c095b3a216c510c92743c5", +"postgres": "83535238d4bee99c5079d1f1", +"snowflake": "83535238d4bee99c5079d1f1" +} +], +[ +"metadata", +{ +"bigquery": "7b052937b7f3b212908fa289", +"duckdb": "31c36219fc8d6894d50fd2a6", +"postgres": "c6df91db98ed3db9d24d2dfc", +"snowflake": "c6df91db98ed3db9d24d2dfc" +} +] +] diff --git a/tests/goldens/python_oracle/project_assembly_error_and_python_value_edges.json b/tests/goldens/python_oracle/project_assembly_error_and_python_value_edges.json new file mode 100644 index 0000000000..c8a3d30096 --- /dev/null +++ b/tests/goldens/python_oracle/project_assembly_error_and_python_value_edges.json @@ -0,0 +1,122 @@ +[ +[ +"project_assembly", +"b0da4db3b091cc425f7fbe09" +], +[ +"project_assembly", +"a1d218340a8a83ce8681f2b2" +], +[ +"project_assembly", +"8a47cd3642ace755a7c46b94" +], +[ +"project_assembly", +"22b5e7c6bf3587610e7b1b7e" +], +[ +"project_assembly", +"ac339c15fbbcb948eb69da7e" +], +[ +"project_assembly", +"56459e971d6fe0e49ff51ed5" +], +[ +"project_assembly", +"568de5c3f4f1b83304fab4cb" +], +[ +"project_assembly", +"c7887fba33496eea6d479a73" +], +[ +"project_assembly", +"bddc5553ccdd80aea43a1dc2" +], +[ +"project_assembly", +"cad31f1d08d77478fa7b2ae6" +], +[ +"project_assembly", +"bddc5553ccdd80aea43a1dc2" +], +[ +"project_assembly", +"e2a1f01e91327cd87c4ce2df" +], +[ +"project_assembly", +"800a1eb0f3c23e14edfd39d9" +], +[ +"project_assembly", +"b1951da418d038d9394fa019" +], +[ +"project_assembly", +"9d5591dd12ddd428dc6c8e56" +], +[ +"project_assembly", +"bddc5553ccdd80aea43a1dc2" +], +[ +"project_assembly", +"f0a5ab0aedffce53d0bac0bf" +], +[ +"project_assembly", +"44cdecb987fae0e4644b1a08" +], +[ +"project_assembly", +"b5a2c667add3dec4527f8ef7" +], +[ +"project_assembly", +"1a55871ff35d8dc0260773bd" +], +[ +"project_assembly", +"2df742bfc91738b084725927" +], +[ +"project_assembly", +"bcc774439d9bbe2be64ac4b2" +], +[ +"project_assembly", +"040cd531ebc642bf4de669da" +], +[ +"project_assembly", +"7ee2dc900563b2b129038429" +], +[ +"project_assembly", +"8bca33d40133968f5dab80e4" +], +[ +"project_assembly", +"b6f56c4fa9f2885afc8f713e" +], +[ +"project_assembly", +"f0a5ab0aedffce53d0bac0bf" +], +[ +"project_assembly", +"9ab8c9ca08cfda43b74ff42f" +], +[ +"project_assembly", +"891503d02bf0c99bc3bc98c7" +], +[ +"project_assembly", +"cdd9d32ea79d9111e6be4551" +] +] diff --git a/tests/goldens/python_oracle/project_assembly_managed_sources_templated_seeds_and_targets_hooks_audits_a_function.json b/tests/goldens/python_oracle/project_assembly_managed_sources_templated_seeds_and_targets_hooks_audits_a_function.json new file mode 100644 index 0000000000..e03d4f59aa --- /dev/null +++ b/tests/goldens/python_oracle/project_assembly_managed_sources_templated_seeds_and_targets_hooks_audits_a_function.json @@ -0,0 +1,34 @@ +[ +[ +"project_assembly", +"c624532f45ee2f49f32bb014" +], +[ +"project_assembly", +"e8f758602c1eff42b55ae130" +], +[ +"project_assembly", +"c864759e0faad475584471c2" +], +[ +"project_assembly", +"bef8fb45b929dfd76002a363" +], +[ +"project_assembly", +"72eebcec28c52bab2cfaff77" +], +[ +"project_assembly", +"545af810ba171c3734719656" +], +[ +"project_assembly", +"69e7548205912c60d17e51ba" +], +[ +"project_assembly", +"2d3e75fa9a354fbf256f6bcb" +] +] diff --git a/tests/goldens/python_oracle/projection_facts_fixture_projection_edges.json b/tests/goldens/python_oracle/projection_facts_fixture_projection_edges.json new file mode 100644 index 0000000000..bc68922b05 --- /dev/null +++ b/tests/goldens/python_oracle/projection_facts_fixture_projection_edges.json @@ -0,0 +1,66 @@ +[ +[ +"projection_facts", +"6da442e97bb6c306b9c2f819" +], +[ +"projection_facts", +"a1e82c6e27da412dd6c97a45" +], +[ +"projection_facts", +"3eba916f73c3192f9824b709" +], +[ +"projection_facts", +"150e095633f5482a909c0f88" +], +[ +"projection_facts", +"150e095633f5482a909c0f88" +], +[ +"projection_facts", +"8d71ffb25f3a586e8521356b" +], +[ +"projection_facts", +"15340dd7914c4d047a966415" +], +[ +"projection_facts", +"24213e6d5dbdc0914977176a" +], +[ +"projection_facts", +"7f5d3f1706af5144062e2050" +], +[ +"projection_facts", +"150e095633f5482a909c0f88" +], +[ +"projection_facts", +"150e095633f5482a909c0f88" +], +[ +"projection_facts", +"727b5e58480115a8d28d47d5" +], +[ +"projection_facts", +"e2e814e9aa9661dae2c19a7c" +], +[ +"projection_facts", +"150e095633f5482a909c0f88" +], +[ +"projection_facts", +"0481f2753e03358cd1c77e95" +], +[ +"projection_facts", +"1edb014872e2983e44bab225" +] +] diff --git a/tests/goldens/python_oracle/relation_names_hard_coded_relation_edges.json b/tests/goldens/python_oracle/relation_names_hard_coded_relation_edges.json new file mode 100644 index 0000000000..697a5f89ba --- /dev/null +++ b/tests/goldens/python_oracle/relation_names_hard_coded_relation_edges.json @@ -0,0 +1,90 @@ +[ +[ +"relation_names", +"97441cac529281e0cc24ca91" +], +[ +"relation_names", +"6f6f17d74a2d182dcca715ec" +], +[ +"relation_names", +"97441cac529281e0cc24ca91" +], +[ +"relation_names", +"acde9a115a0ac703bd3bd3df" +], +[ +"relation_names", +"694deb3886fa7a4e11705220" +], +[ +"relation_names", +"fd0c7b14bc139764127543a4" +], +[ +"relation_names", +"a180f2e81ae38757d5ea840f" +], +[ +"relation_names", +"f39469d6dfe3c4cfac5789b7" +], +[ +"relation_names", +"e3d90a5ec29167469993355c" +], +[ +"relation_names", +"74234e98afe7498fb5daf1f3" +], +[ +"relation_names", +"9806faa1ab31111cd5e23f82" +], +[ +"relation_names", +"dbcb2fcbc05164b64760b437" +], +[ +"relation_names", +"5d90e126c6a171a0fbfe84a1" +], +[ +"relation_names", +"055cec2fa05c4ab0814c218f" +], +[ +"relation_names", +"8c3a356da4dd363b47295607" +], +[ +"relation_names", +"250261fc57ae6a030cc265bb" +], +[ +"relation_names", +"ef3355ab56c0f05febbf677c" +], +[ +"relation_names", +"9806faa1ab31111cd5e23f82" +], +[ +"relation_names", +"bf001523fcaedb3d64a3d9a3" +], +[ +"relation_names", +"c272291db0662682b6651d41" +], +[ +"relation_names", +"9806faa1ab31111cd5e23f82" +], +[ +"relation_names", +"9bc7c81e3b3ef877d35f3b22" +] +] diff --git a/tests/goldens/python_oracle/relationship_scan_backslash_triple_raw_dialect.json b/tests/goldens/python_oracle/relationship_scan_backslash_triple_raw_dialect.json new file mode 100644 index 0000000000..30c61e79b5 --- /dev/null +++ b/tests/goldens/python_oracle/relationship_scan_backslash_triple_raw_dialect.json @@ -0,0 +1,12002 @@ +[ +[ +"relationship_scan", +"8447c5b3d02d60ba962f5b9e" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"724ba6d2f238cbc21a387b05" +], +[ +"relationship_scan", +"20fd14152c40e79bab186d6d" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"17a892812df25d578bb36131" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"a4653aa9db1418b0b42c4c42" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"580885eecbd90bb1f82597e5" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"1ebfd73c2d8073d2e95ad475" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"4bc7209f45e938dbe9a06f53" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"e1d1343ec914619c569ce471" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"69bc751e081ba4c8413c0d35" +], +[ +"relationship_scan", +"2d43e0d3c7f4c6caaaa918c3" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"8c0f9f15d1e2f623e9759fd2" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"58f3cfdc7ad9b9f596472330" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"580885eecbd90bb1f82597e5" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"a79adccd4afe1fecf50a966f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"f94586774bff2f36b9438389" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"dc44f67c5bc66fc79bcb9fdd" +], +[ +"relationship_scan", +"0ea9d405ffd41f31e9a1692d" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"26ec172c59ec2e1c73aeb2f3" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"7d501e0244f982810a12eded" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"fb498f81d96450b36c3b1229" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"de0ae912351f1f8fea343321" +], +[ +"relationship_scan", +"af2642902d40879fb19181d1" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"08ab0d6cd271c9ff459a997a" +], +[ +"relationship_scan", +"dc44f67c5bc66fc79bcb9fdd" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"df22a74dae6ef996dff2874b" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"724ba6d2f238cbc21a387b05" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"7d501e0244f982810a12eded" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"e3205ce3009d03e1dd3a9599" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"c0d6997a660484365c6f5537" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"543d5570b0cda50002ca64bb" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"69e837eeb62e494a2e6d95da" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"4c120d9637afb9b0c1790b0b" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"6dc3ebeece372d0bc9139ac1" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"c0d6997a660484365c6f5537" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"e91139fd35b64d91435ccb66" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1ebfd73c2d8073d2e95ad475" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"73c0fe393e5b5690d3fca531" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"69e837eeb62e494a2e6d95da" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"9e3f94fe8fa71cab098c2be0" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"26ec172c59ec2e1c73aeb2f3" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"0ca76698a3a51c0e0d0d0426" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"c516f3539ca9c5c120d82566" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"5b3198d25393608c9e54a38d" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"64cf60943772eda8c4ab4076" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"7d501e0244f982810a12eded" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"4f6de364740ae3b332ff48cb" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"e7de380006ea3938f0a5e3a4" +], +[ +"relationship_scan", +"5432b628257450440b1253b7" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"7982bfc31674d7e1e8b8ce0a" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"783c75eb5640db2d5f2b290f" +], +[ +"relationship_scan", +"af1783d1aa394d8dc8efac46" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"5e5289dfdac0521ab6db3aec" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"c0d6997a660484365c6f5537" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"c256bf13c7f77220367ed629" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"a00a6ea595d3733ae6bdecbe" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"dff1a4bd99dcd89fb96e7471" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"17e8c4a71f6c0e623d85825c" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"e91139fd35b64d91435ccb66" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"7d501e0244f982810a12eded" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"26ec172c59ec2e1c73aeb2f3" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"c0d6997a660484365c6f5537" +], +[ +"relationship_scan", +"fe4cb0a45939795e3facf67c" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"51527d8b491717ed466b0d43" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"d0c61822c7e15f75af772474" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"69e837eeb62e494a2e6d95da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"724ba6d2f238cbc21a387b05" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"a3b8d8894423895f21677109" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"a4147dd89bb60bf698a8a3c1" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"0ec2081efe68a33434ad7a1e" +], +[ +"relationship_scan", +"5cabb4f8e322e91025151b4d" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"83c936d9211631eb5da3224c" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"f9178d68ee95a5714fae4914" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"555298220ce6380b9c52ef77" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"69e837eeb62e494a2e6d95da" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"830f877a7d54c5cdba7c8b2f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"df365c3cfbb96c32816aaf77" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"83c936d9211631eb5da3224c" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"724ba6d2f238cbc21a387b05" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"83c936d9211631eb5da3224c" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"7982bfc31674d7e1e8b8ce0a" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"26ec172c59ec2e1c73aeb2f3" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"7982bfc31674d7e1e8b8ce0a" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"26ec172c59ec2e1c73aeb2f3" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"7a4dc202a4e5e510088b04c6" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"83c936d9211631eb5da3224c" +], +[ +"relationship_scan", +"7d501e0244f982810a12eded" +], +[ +"relationship_scan", +"4cefa2f3c0730b3cb42b8aef" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"213d712724f65014f14e9b98" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"73859dae82bee9b7dfa986bd" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"992b5778bb655a00da7d71e4" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"ef9e51bcdb987473521c94b9" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"6f593e6dcbb047ef5565db50" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"73c0fe393e5b5690d3fca531" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"ed176f8d666276a5c6c60ffb" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"4c120d9637afb9b0c1790b0b" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"9bef9351cf392c35fd43da6e" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"52bd814df2a5a9a64788baab" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"d846a400d539e830953b3f82" +], +[ +"relationship_scan", +"64598a60cf2fbab0e3e8f516" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"83c936d9211631eb5da3224c" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"08ab0d6cd271c9ff459a997a" +], +[ +"relationship_scan", +"8bfa6cf7d9f39cd5efb8f5fb" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1f73e33089aaefd0bc70dbf9" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"7d501e0244f982810a12eded" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"606308e2aa33431d356159c9" +], +[ +"relationship_scan", +"7153501910989191773c2c43" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"ce1e0e4a2b6ca04edfa58d52" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"7d501e0244f982810a12eded" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"f94586774bff2f36b9438389" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"f480b40ea3d74cda1b658593" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"724ba6d2f238cbc21a387b05" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"83c936d9211631eb5da3224c" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"42b8b3003860b0f0d61c19a6" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"69e837eeb62e494a2e6d95da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"dc44f67c5bc66fc79bcb9fdd" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"505dad1e8e5daeb805d46095" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"536d660abb33441e8e64a8de" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1680474ecfff72ab3b69096c" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"11d5220b939f393a21b19853" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"7d501e0244f982810a12eded" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"fff031d3d2fb57915e8bf0ae" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"dade70c8b81f99f201b9068c" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"c84551422825b00d07db0592" +], +[ +"relationship_scan", +"69e837eeb62e494a2e6d95da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"f5c6d72e6f10acc72866da36" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"6f53dbfbb6c12cd1475ed1f6" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"6f53dbfbb6c12cd1475ed1f6" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"33026aa7b75cdb1184ce1ace" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"83c936d9211631eb5da3224c" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"7d501e0244f982810a12eded" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"992b5778bb655a00da7d71e4" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"bb031880975a3b9156bce982" +], +[ +"relationship_scan", +"288e394b18c5df920f74c7f5" +], +[ +"relationship_scan", +"54c589e2944ccbc645adbc86" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"606b918a65b03052f2f21ab7" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"fe30dd97c721722f8743b30e" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"f94586774bff2f36b9438389" +], +[ +"relationship_scan", +"724ba6d2f238cbc21a387b05" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"549aa256efc9f908b87da677" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"4f6de364740ae3b332ff48cb" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"7982bfc31674d7e1e8b8ce0a" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"7f242f3ffb1c5e1da26bbe7e" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"897ab311321534391158d3b0" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"4c120d9637afb9b0c1790b0b" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"69e837eeb62e494a2e6d95da" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"c7963ccd56cf0b7e5f4f246f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"e91139fd35b64d91435ccb66" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"5b3198d25393608c9e54a38d" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"dc44f67c5bc66fc79bcb9fdd" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"4808bcf68fdc429cddb10fa4" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"64cf60943772eda8c4ab4076" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1d3e74fab3790fae55c416b1" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"38de4f50e1c3272b43d3b059" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"c516f3539ca9c5c120d82566" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"288e394b18c5df920f74c7f5" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"4c120d9637afb9b0c1790b0b" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"5b3198d25393608c9e54a38d" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"213d712724f65014f14e9b98" +], +[ +"relationship_scan", +"dc44f67c5bc66fc79bcb9fdd" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"b32930a0267a47ca0fcf72e0" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"69e837eeb62e494a2e6d95da" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"b415c68a0a1b97c7dea5db67" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"de0dbe3d87a63aed00766035" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"83c936d9211631eb5da3224c" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"c0d6997a660484365c6f5537" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"06ea59a7166830e1d0ec1f76" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"e842e2e3b78e944c129d107e" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"880c396b85f8d86911a82630" +], +[ +"relationship_scan", +"614f6c9f560555ab0c234bc0" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"82ce88ed999caa1eae0d785f" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"c516f3539ca9c5c120d82566" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"64cf60943772eda8c4ab4076" +], +[ +"relationship_scan", +"1c6c2f444102d71b283e314d" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"c0d6997a660484365c6f5537" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"7d501e0244f982810a12eded" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"724ba6d2f238cbc21a387b05" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"dc44f67c5bc66fc79bcb9fdd" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"052573eaa0390a6201a217ae" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"04e523c88f76e02c31cbded8" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"dc44f67c5bc66fc79bcb9fdd" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"de78bc9086c39bc8c6aadba5" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"6c7fc6500a61e035867e41ef" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"f9cdf97aade5823a9831739c" +], +[ +"relationship_scan", +"47af4bdcf2a297d8e823591c" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"966921a8b19f4c77f561b736" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"73c0fe393e5b5690d3fca531" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"f80e1001d0ae21ad419b95aa" +], +[ +"relationship_scan", +"11f31172b8d083f5dbe63cfe" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"724ba6d2f238cbc21a387b05" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"5ee866e3ecad7a6c82ae9e19" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"c0d6997a660484365c6f5537" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"56c16bd68c6dc1ff611ea08d" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"724ba6d2f238cbc21a387b05" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"9cfff16329099ef7f2c0b576" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"549aa256efc9f908b87da677" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"f94586774bff2f36b9438389" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"73a59804fb25f0ecae4f2c72" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"4f6de364740ae3b332ff48cb" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"69e837eeb62e494a2e6d95da" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"4c4f5ae247068467caf252fa" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"9cfff16329099ef7f2c0b576" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"e1d1343ec914619c569ce471" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"7d501e0244f982810a12eded" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"76d0a7e7207a20a7b59b9a17" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"580885eecbd90bb1f82597e5" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"11d5220b939f393a21b19853" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"7a4dc202a4e5e510088b04c6" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"eccb676ecff82b2bfca75c3d" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"5432b628257450440b1253b7" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"7d501e0244f982810a12eded" +], +[ +"relationship_scan", +"7d501e0244f982810a12eded" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"d1d91eeb5e485391898fe52b" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"a230fa415db6587626387775" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"92392e036493fb8448722543" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"3ee047a3fc52f1bf759b7fd2" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"69e837eeb62e494a2e6d95da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"724ba6d2f238cbc21a387b05" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"fb498f81d96450b36c3b1229" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"7d501e0244f982810a12eded" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"26ec172c59ec2e1c73aeb2f3" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"26ec172c59ec2e1c73aeb2f3" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"c0d6997a660484365c6f5537" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"17e8c4a71f6c0e623d85825c" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"1c86943c728dd0e561dd3c39" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"797f5cd74865d4607e0b8048" +], +[ +"relationship_scan", +"7d501e0244f982810a12eded" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"83c936d9211631eb5da3224c" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"33026aa7b75cdb1184ce1ace" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"ef9e51bcdb987473521c94b9" +], +[ +"relationship_scan", +"3fed1d8c3459cb44ba949b28" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"7d501e0244f982810a12eded" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"69e837eeb62e494a2e6d95da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"c0d6997a660484365c6f5537" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"fe4cb0a45939795e3facf67c" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"3e9a03554f568256aaa5d3aa" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"dc44f67c5bc66fc79bcb9fdd" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"83c936d9211631eb5da3224c" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"dc44f67c5bc66fc79bcb9fdd" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"92392e036493fb8448722543" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"7d501e0244f982810a12eded" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"724ba6d2f238cbc21a387b05" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"b464c18ae7256268e8ec2f11" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"629f65959f74972fd7ad7778" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"06ea59a7166830e1d0ec1f76" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"55389af9cfecc685ef308d22" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"26ec172c59ec2e1c73aeb2f3" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"d3dbe8880616f489884e8866" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"7a4dc202a4e5e510088b04c6" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"c0d6997a660484365c6f5537" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"ae6eef41cfc22cbbb10542e9" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"7153501910989191773c2c43" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"86e69d42c808254305a204d2" +], +[ +"relationship_scan", +"231f497d98edbebd3ddc13f5" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"893ce6832bc154cb5183f62b" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"7d501e0244f982810a12eded" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"6e1ab31b695a7c38732c4a65" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"3cbedd37a1030927767aa6b5" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"724ba6d2f238cbc21a387b05" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"d3dbe8880616f489884e8866" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"7982bfc31674d7e1e8b8ce0a" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"af0445d34e4ff8bad6074673" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"7d501e0244f982810a12eded" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"3cd7e1c2532296723b94064f" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"64cf60943772eda8c4ab4076" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"26ec172c59ec2e1c73aeb2f3" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"580885eecbd90bb1f82597e5" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"5b3198d25393608c9e54a38d" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"910b57542880dacde669355e" +], +[ +"relationship_scan", +"dc44f67c5bc66fc79bcb9fdd" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"dc44f67c5bc66fc79bcb9fdd" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"ba699be7b74774fea43c8058" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"26ec172c59ec2e1c73aeb2f3" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"7cfb2c910ada4d047a7f62f7" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"a79adccd4afe1fecf50a966f" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"724ba6d2f238cbc21a387b05" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"e54dbe5595d90c5d037291cc" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"c7cc1e5a5e200c04725ff145" +], +[ +"relationship_scan", +"c516f3539ca9c5c120d82566" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"724ba6d2f238cbc21a387b05" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"9e3f94fe8fa71cab098c2be0" +], +[ +"relationship_scan", +"83c936d9211631eb5da3224c" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"ed359145aef9a571027b602a" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"3ba44dc5f271046bfede6ae5" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"38552ebbed4cb596e0df160d" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"dc44f67c5bc66fc79bcb9fdd" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"af1783d1aa394d8dc8efac46" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"3ee047a3fc52f1bf759b7fd2" +], +[ +"relationship_scan", +"3a2404c3ab2643b07d458ec5" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"7982bfc31674d7e1e8b8ce0a" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"df7693f1f1d37a6d9b92bf58" +], +[ +"relationship_scan", +"dc44f67c5bc66fc79bcb9fdd" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"ac1d68abdc2de55d48de177b" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"8b2bae733049d89d0ac81f8d" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"c0d6997a660484365c6f5537" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"dc44f67c5bc66fc79bcb9fdd" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"287e5c659b5091e149572c2e" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"761cdc5795167b2974d82e0a" +], +[ +"relationship_scan", +"d5de02525a64fd43f3bcb975" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"e2deae92e09652b5dddd22ce" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"7a4dc202a4e5e510088b04c6" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"7a0e430bbbb4a1d617cd4846" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"e7de380006ea3938f0a5e3a4" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"69e837eeb62e494a2e6d95da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"7982bfc31674d7e1e8b8ce0a" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"6aff29234ed3941f837bd085" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"2f0bda8681f57fb16dec5064" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"69e837eeb62e494a2e6d95da" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"5b3198d25393608c9e54a38d" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"e0ce9b63b4dfa81cf1d56a26" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"9bcec4aa33189fcd5df13f3c" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"906fa0da3d0b30c475146a81" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"fe5d1c1d9aebdf87855c0d23" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"58bf151da3f8b86619e2f0c6" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"379733af007d8fcc170829ba" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"e54dbe5595d90c5d037291cc" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"62c8dc4dab68343e4c90a583" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1194ba125c6d193f69354e30" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"ed0d3961b0d9591a9a995327" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"10ec4ab1bda9423660df12bb" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"5b3198d25393608c9e54a38d" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"ac1d68abdc2de55d48de177b" +], +[ +"relationship_scan", +"64cf60943772eda8c4ab4076" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"7d501e0244f982810a12eded" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"7982bfc31674d7e1e8b8ce0a" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"26ec172c59ec2e1c73aeb2f3" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"724ba6d2f238cbc21a387b05" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"aa9545fe77413bbffbc7b330" +], +[ +"relationship_scan", +"65356ad7a7360fa11cc6a4e9" +], +[ +"relationship_scan", +"ff5c10defd431b61508f48a6" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"65356ad7a7360fa11cc6a4e9" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"11d5220b939f393a21b19853" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"ccca0a0f5edee67e34ce5bbf" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"e842e2e3b78e944c129d107e" +], +[ +"relationship_scan", +"af2af28fb49fe10a135f75ce" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"42810d8775a639e0dba1719b" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"c0d6997a660484365c6f5537" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"7d501e0244f982810a12eded" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"724ba6d2f238cbc21a387b05" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"5bfe6db1bad784ca11c8c984" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"83c936d9211631eb5da3224c" +], +[ +"relationship_scan", +"3cd7e1c2532296723b94064f" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"7bb9e13b769a50cc6b24f7da" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"26ec172c59ec2e1c73aeb2f3" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"69e837eeb62e494a2e6d95da" +], +[ +"relationship_scan", +"500f77463140cf75f0f175c3" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"83c936d9211631eb5da3224c" +], +[ +"relationship_scan", +"ae91faaf159c10db1dcbbbcb" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"041d0b2907f81598f7fb0981" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"17d67719454e05f3ef4e9426" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"265149cba0f6684083cf893d" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"26ec172c59ec2e1c73aeb2f3" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"c0d6997a660484365c6f5537" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"d3dbe8880616f489884e8866" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"dc44f67c5bc66fc79bcb9fdd" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"a326890560b53a2db1873674" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"7a4dc202a4e5e510088b04c6" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"0d757ab7d752d05d7bcf6ede" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"83c936d9211631eb5da3224c" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"a4653aa9db1418b0b42c4c42" +], +[ +"relationship_scan", +"dc44f67c5bc66fc79bcb9fdd" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"69e837eeb62e494a2e6d95da" +], +[ +"relationship_scan", +"c0d6997a660484365c6f5537" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"26ec172c59ec2e1c73aeb2f3" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"79460b6734cbe299de16f443" +], +[ +"relationship_scan", +"e54dbe5595d90c5d037291cc" +], +[ +"relationship_scan", +"e842e2e3b78e944c129d107e" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"7e72d6cdac7555095154d1ef" +], +[ +"relationship_scan", +"724ba6d2f238cbc21a387b05" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"6fe7903e6f9c7569d0ebef5e" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"4ac473d5a38f415f6efab2d7" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"0bf222b5d31c4701f203fd94" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"fe30dd97c721722f8743b30e" +], +[ +"relationship_scan", +"5ee866e3ecad7a6c82ae9e19" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"48a7f368217e6f90f0a5c729" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"a3b8d8894423895f21677109" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"29dee6c6cfd31e3ee369b9d8" +], +[ +"relationship_scan", +"213d712724f65014f14e9b98" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"fe4cb0a45939795e3facf67c" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"d4bbd58d7ad9570e86406c6c" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"992b5778bb655a00da7d71e4" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"f63da3ccd846e9db1a7f3007" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"724ba6d2f238cbc21a387b05" +], +[ +"relationship_scan", +"5432b628257450440b1253b7" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"7dfb2bb6ad1517422cf4e853" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"b6940b3438bb9ec17ae2f3d9" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"e91139fd35b64d91435ccb66" +], +[ +"relationship_scan", +"1051135bd47bdc9b22964827" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"26ec172c59ec2e1c73aeb2f3" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"8bfa6cf7d9f39cd5efb8f5fb" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"231f497d98edbebd3ddc13f5" +], +[ +"relationship_scan", +"c0d6997a660484365c6f5537" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"cb774b4dd7c6429c3c521d9c" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"27c59d3365ae9086cdf151ab" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"64cf60943772eda8c4ab4076" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"832f6e23b1252077129a8394" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"7d501e0244f982810a12eded" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"7b79640ade4bb8b1f7f3c19c" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"65356ad7a7360fa11cc6a4e9" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"a4653aa9db1418b0b42c4c42" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +] +] diff --git a/tests/goldens/python_oracle/relationship_scan_escape_prefix_dialect.json b/tests/goldens/python_oracle/relationship_scan_escape_prefix_dialect.json new file mode 100644 index 0000000000..00ca39beb6 --- /dev/null +++ b/tests/goldens/python_oracle/relationship_scan_escape_prefix_dialect.json @@ -0,0 +1,12002 @@ +[ +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"c0d6997a660484365c6f5537" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"5ce261e2e6f23671f6aed2fc" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"c0d6997a660484365c6f5537" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"f7f0ff1cf2ee32bd97a12f06" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"1cd29f2eb8b48a2f903f2e97" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"724ba6d2f238cbc21a387b05" +], +[ +"relationship_scan", +"606308e2aa33431d356159c9" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"6f53dbfbb6c12cd1475ed1f6" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"26ec172c59ec2e1c73aeb2f3" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"83c936d9211631eb5da3224c" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"69e837eeb62e494a2e6d95da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"f14acd6c8b16faa02717acd8" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"92392e036493fb8448722543" +], +[ +"relationship_scan", +"69e837eeb62e494a2e6d95da" +], +[ +"relationship_scan", +"65356ad7a7360fa11cc6a4e9" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"13109da9c5f39f4f81898de1" +], +[ +"relationship_scan", +"2a4a7e955a8f7c0b4ff654e2" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"5432b628257450440b1253b7" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"213d712724f65014f14e9b98" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"7982bfc31674d7e1e8b8ce0a" +], +[ +"relationship_scan", +"69e837eeb62e494a2e6d95da" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"2d6175f0bf2d9b24780f45e9" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"33026aa7b75cdb1184ce1ace" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"13109da9c5f39f4f81898de1" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"65d0ed6f5d7e6e1fa23102f1" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"f819672b210717ae9b523d98" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"d92b143d665d91db8416c45c" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"60d4b932330a20cd124fefbe" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"69e837eeb62e494a2e6d95da" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"33026aa7b75cdb1184ce1ace" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"9cfff16329099ef7f2c0b576" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"7d501e0244f982810a12eded" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"13109da9c5f39f4f81898de1" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"7982bfc31674d7e1e8b8ce0a" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"2ecec7aced14188b31208db9" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"770ea29fc3404ccbab3ee05c" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"65356ad7a7360fa11cc6a4e9" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"26ec172c59ec2e1c73aeb2f3" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"0d25f34557b281b296f591ef" +], +[ +"relationship_scan", +"b66006fb8ef92c561b80af50" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"724ba6d2f238cbc21a387b05" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"363d6f8d3c3046dd2a97a90b" +], +[ +"relationship_scan", +"34cf1ade0acbbdd0ea219dc2" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"e2deae92e09652b5dddd22ce" +], +[ +"relationship_scan", +"dc44f67c5bc66fc79bcb9fdd" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"73c0fe393e5b5690d3fca531" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"7d501e0244f982810a12eded" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"ba5a2bfdc95eb5d95c5846a4" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"0e385439bc0f8b93815c9e16" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"5432b628257450440b1253b7" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"3209a262594086c9a1459e2c" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"17e8c4a71f6c0e623d85825c" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"de0dbe3d87a63aed00766035" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"7d501e0244f982810a12eded" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"9cfff16329099ef7f2c0b576" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"c577cd193800695d1504fd71" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"5ee866e3ecad7a6c82ae9e19" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"73c0fe393e5b5690d3fca531" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"13109da9c5f39f4f81898de1" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"513a9dfe3a73e6a9d3a0ceea" +], +[ +"relationship_scan", +"dc44f67c5bc66fc79bcb9fdd" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"ae91faaf159c10db1dcbbbcb" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"7d501e0244f982810a12eded" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"675d3dfdec9bb05af7d9220a" +], +[ +"relationship_scan", +"4c120d9637afb9b0c1790b0b" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"7d501e0244f982810a12eded" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"2fe96ca5fd45b3cfa63434c7" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"21881cd361793fc630acf106" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"e91139fd35b64d91435ccb66" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"c0d6997a660484365c6f5537" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"2ac71f0f5ddec54c1d1bf172" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"2142d8612ed44bd5af78af2c" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"13109da9c5f39f4f81898de1" +], +[ +"relationship_scan", +"832f6e23b1252077129a8394" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"9cfff16329099ef7f2c0b576" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"606308e2aa33431d356159c9" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"65356ad7a7360fa11cc6a4e9" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"724ba6d2f238cbc21a387b05" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"ec5dfa9a714ae4439347f68a" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"d9f1191ff3eb9698719d9dd6" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"4265a4adb9d0715c722d44c6" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"13109da9c5f39f4f81898de1" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"fe4cb0a45939795e3facf67c" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"8bfa6cf7d9f39cd5efb8f5fb" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"c0d6997a660484365c6f5537" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"7d501e0244f982810a12eded" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"28e20f537dd7d89dfe99310f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"c0d6997a660484365c6f5537" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"7d501e0244f982810a12eded" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"c0d6997a660484365c6f5537" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"08ab0d6cd271c9ff459a997a" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1e4b047df777a9b408e61184" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"1ebfd73c2d8073d2e95ad475" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"69e837eeb62e494a2e6d95da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"69e837eeb62e494a2e6d95da" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"dc44f67c5bc66fc79bcb9fdd" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"26ec172c59ec2e1c73aeb2f3" +], +[ +"relationship_scan", +"7982bfc31674d7e1e8b8ce0a" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"08046bb3714c23b81ea23a52" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"26ec172c59ec2e1c73aeb2f3" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"a5fd9c8946bfbab2f1393cdf" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"d1d91eeb5e485391898fe52b" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"dc44f67c5bc66fc79bcb9fdd" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"559a746f5e3da3ab0dda8d0f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"de78bc9086c39bc8c6aadba5" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"4c25c24f82baa873429deae9" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"07b9e30b1bbf527173f0ea46" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"559a746f5e3da3ab0dda8d0f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"26ec172c59ec2e1c73aeb2f3" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"724ba6d2f238cbc21a387b05" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"7153501910989191773c2c43" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"fb498f81d96450b36c3b1229" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"f9cdf97aade5823a9831739c" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"eb4316081cae2bd97903b2ba" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"bf1bef6516960b5981f26b31" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"2c313746f045ad664a574b92" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"1ebfd73c2d8073d2e95ad475" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"7982bfc31674d7e1e8b8ce0a" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"549aa256efc9f908b87da677" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"af2af28fb49fe10a135f75ce" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"26ec172c59ec2e1c73aeb2f3" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"877136ece2f20d46356094fe" +], +[ +"relationship_scan", +"7e54d08512a39b4990e2e099" +], +[ +"relationship_scan", +"11d5220b939f393a21b19853" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"3a77c1fe21582b19ebf38c7a" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"a79adccd4afe1fecf50a966f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"5ce261e2e6f23671f6aed2fc" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"9cfff16329099ef7f2c0b576" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"4c4f5ae247068467caf252fa" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"e9f0324db7bd5811b7b965dc" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"6fc14b29b6546f40d1575186" +], +[ +"relationship_scan", +"33026aa7b75cdb1184ce1ace" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"992b5778bb655a00da7d71e4" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"231f497d98edbebd3ddc13f5" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"7982bfc31674d7e1e8b8ce0a" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"4ac473d5a38f415f6efab2d7" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"5b3198d25393608c9e54a38d" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"7982bfc31674d7e1e8b8ce0a" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"a79adccd4afe1fecf50a966f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"347d0d28d3079fc3524d0cd0" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"26ec172c59ec2e1c73aeb2f3" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"65356ad7a7360fa11cc6a4e9" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"07d1a42055fd2133f9a1eac4" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"718ab5b61cf444754073ad22" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"a00a6ea595d3733ae6bdecbe" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"17e8c4a71f6c0e623d85825c" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"d3f5e315793b71e0bc0c88f1" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"559a746f5e3da3ab0dda8d0f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"af2642902d40879fb19181d1" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"64cf60943772eda8c4ab4076" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"13109da9c5f39f4f81898de1" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"13109da9c5f39f4f81898de1" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"5a2103b44feef37480ab2ea1" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"c577cd193800695d1504fd71" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"724ba6d2f238cbc21a387b05" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"724ba6d2f238cbc21a387b05" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"d23e4166db358cde2a360a8a" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"3cd7e1c2532296723b94064f" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"10ec4ab1bda9423660df12bb" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"dc44f67c5bc66fc79bcb9fdd" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"41e029dfde2d049ef33b3db6" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"69e837eeb62e494a2e6d95da" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"7d501e0244f982810a12eded" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"231f497d98edbebd3ddc13f5" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"af2af28fb49fe10a135f75ce" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"c0d6997a660484365c6f5537" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"dc44f67c5bc66fc79bcb9fdd" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"78552c21ada2e56e1548e0ff" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"4c4f5ae247068467caf252fa" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1e92a83fb635e62241cbb96f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"26ec172c59ec2e1c73aeb2f3" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"cc16066bee96ae92eaba8827" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"675d3dfdec9bb05af7d9220a" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"614aac759df804db887aa5f5" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"9113c81739d3662514aa74fb" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"7982bfc31674d7e1e8b8ce0a" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"c0d6997a660484365c6f5537" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"5ce261e2e6f23671f6aed2fc" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"7982bfc31674d7e1e8b8ce0a" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"724ba6d2f238cbc21a387b05" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"7d501e0244f982810a12eded" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"f7f0ff1cf2ee32bd97a12f06" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"4c120d9637afb9b0c1790b0b" +], +[ +"relationship_scan", +"7038314250df83bbd8a46b25" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1edfe1217ef6816ea05cda35" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"26ec172c59ec2e1c73aeb2f3" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"33026aa7b75cdb1184ce1ace" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"c0d6997a660484365c6f5537" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"dc44f67c5bc66fc79bcb9fdd" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"26ec172c59ec2e1c73aeb2f3" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"00769da5cbe0dd726dfeacec" +], +[ +"relationship_scan", +"607320f8f2161c9d1ac7a0d8" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"83c936d9211631eb5da3224c" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"c0d6997a660484365c6f5537" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"62c8dc4dab68343e4c90a583" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"231f497d98edbebd3ddc13f5" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"b2656fe5f2b7135a2ccdbddd" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"a3b8d8894423895f21677109" +], +[ +"relationship_scan", +"06ea59a7166830e1d0ec1f76" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"9350732a71a21c9be2e3c843" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"c577cd193800695d1504fd71" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"de78bc9086c39bc8c6aadba5" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"8bfa6cf7d9f39cd5efb8f5fb" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"b405fc70ae01cd0f91c23231" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"83c936d9211631eb5da3224c" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"de78bc9086c39bc8c6aadba5" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"f94586774bff2f36b9438389" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"d846a400d539e830953b3f82" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"231f497d98edbebd3ddc13f5" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"724ba6d2f238cbc21a387b05" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"f7f0ff1cf2ee32bd97a12f06" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"7982bfc31674d7e1e8b8ce0a" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"7982bfc31674d7e1e8b8ce0a" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"3cd7e1c2532296723b94064f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"65356ad7a7360fa11cc6a4e9" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"ae91faaf159c10db1dcbbbcb" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"c2477534e4970a872fdb0ca7" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"fdf6f40489fe7e6ad9f20429" +], +[ +"relationship_scan", +"69e837eeb62e494a2e6d95da" +], +[ +"relationship_scan", +"69e837eeb62e494a2e6d95da" +], +[ +"relationship_scan", +"73c0fe393e5b5690d3fca531" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"74cede495a57877557a9bc0f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"8bfa6cf7d9f39cd5efb8f5fb" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"69e837eeb62e494a2e6d95da" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"26ec172c59ec2e1c73aeb2f3" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"e2deae92e09652b5dddd22ce" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"4c3d399dbfa6d42506702f94" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"33026aa7b75cdb1184ce1ace" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"ad8fac018ec753fcd018cfa1" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"f9cdf97aade5823a9831739c" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"83c936d9211631eb5da3224c" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"559a746f5e3da3ab0dda8d0f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"bdf8273dcb44c1f3504a7280" +], +[ +"relationship_scan", +"a3b8d8894423895f21677109" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"f5c6d72e6f10acc72866da36" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"ae91faaf159c10db1dcbbbcb" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"4ac473d5a38f415f6efab2d7" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"f5c6d72e6f10acc72866da36" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"4ac473d5a38f415f6efab2d7" +], +[ +"relationship_scan", +"d4bbd58d7ad9570e86406c6c" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"bdf8273dcb44c1f3504a7280" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"26ec172c59ec2e1c73aeb2f3" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"69e837eeb62e494a2e6d95da" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"4f88e39c11cc2545a6cafeac" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"b6940b3438bb9ec17ae2f3d9" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"ae1c14e02f29783528c696a1" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"0cf19608ce42f415ab4c4277" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"606308e2aa33431d356159c9" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"83c936d9211631eb5da3224c" +], +[ +"relationship_scan", +"008302ab1acc71079861b7ae" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"213d712724f65014f14e9b98" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"5b3198d25393608c9e54a38d" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"26ec172c59ec2e1c73aeb2f3" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"52920ee4f817a70beec3f4aa" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"7153501910989191773c2c43" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"e281646bb23af2c4fc40588b" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"4f6de364740ae3b332ff48cb" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"c0d6997a660484365c6f5537" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"ff724e1df1972bc99758a258" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"cefab3931dfa14415586f93a" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +] +] diff --git a/tests/goldens/python_oracle/relationship_scan_generic_dialect.json b/tests/goldens/python_oracle/relationship_scan_generic_dialect.json new file mode 100644 index 0000000000..5eda903a4e --- /dev/null +++ b/tests/goldens/python_oracle/relationship_scan_generic_dialect.json @@ -0,0 +1,12002 @@ +[ +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1d02a84d63fafde4d1bf3c06" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"45cd070c5582dc2830666944" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"c0d6997a660484365c6f5537" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"af9df42033a59ef1acac0c5d" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"724ba6d2f238cbc21a387b05" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"c0d6997a660484365c6f5537" +], +[ +"relationship_scan", +"83c936d9211631eb5da3224c" +], +[ +"relationship_scan", +"26ec172c59ec2e1c73aeb2f3" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"0695ad775cda6a467737a85f" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"c502ad4c8c29037ccd22912c" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"f4c1b738d4f1d2042ed5679f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"7982bfc31674d7e1e8b8ce0a" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"73c0fe393e5b5690d3fca531" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"13109da9c5f39f4f81898de1" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"eb6fd68a9cc723906f798e66" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"e2deae92e09652b5dddd22ce" +], +[ +"relationship_scan", +"33026aa7b75cdb1184ce1ace" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"dc44f67c5bc66fc79bcb9fdd" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"13109da9c5f39f4f81898de1" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"73c0fe393e5b5690d3fca531" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"fb498f81d96450b36c3b1229" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"69e837eeb62e494a2e6d95da" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1d02a84d63fafde4d1bf3c06" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"bdf8273dcb44c1f3504a7280" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"fe30dd97c721722f8743b30e" +], +[ +"relationship_scan", +"af2642902d40879fb19181d1" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"56dfc6169508717e7934e690" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"5432b628257450440b1253b7" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"fe4cb0a45939795e3facf67c" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"549aa256efc9f908b87da677" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"b88a7165b6052597f2c14b38" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"555298220ce6380b9c52ef77" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"06ea59a7166830e1d0ec1f76" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"26ec172c59ec2e1c73aeb2f3" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"13109da9c5f39f4f81898de1" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"13109da9c5f39f4f81898de1" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"c0d6997a660484365c6f5537" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"13109da9c5f39f4f81898de1" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"13109da9c5f39f4f81898de1" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"f9cdf97aade5823a9831739c" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"0d384f77d21a2ffac753a2a0" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"6f53dbfbb6c12cd1475ed1f6" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"fe4cb0a45939795e3facf67c" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"b6940b3438bb9ec17ae2f3d9" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"79460b6734cbe299de16f443" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"0e1b72e7af07618fe11d5055" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"bdf8273dcb44c1f3504a7280" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"13109da9c5f39f4f81898de1" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"bdf8273dcb44c1f3504a7280" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"b04eeb496808dd48c0995cc1" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"83c936d9211631eb5da3224c" +], +[ +"relationship_scan", +"ec82330e6542e639287beefa" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"01155d7e523b69b1f5520d00" +], +[ +"relationship_scan", +"1ebfd73c2d8073d2e95ad475" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"69e837eeb62e494a2e6d95da" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"724ba6d2f238cbc21a387b05" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"f7f0ff1cf2ee32bd97a12f06" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"6f53dbfbb6c12cd1475ed1f6" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"65356ad7a7360fa11cc6a4e9" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"3cd7e1c2532296723b94064f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"13109da9c5f39f4f81898de1" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"7d501e0244f982810a12eded" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"13109da9c5f39f4f81898de1" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"13109da9c5f39f4f81898de1" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"231f497d98edbebd3ddc13f5" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"a3b8d8894423895f21677109" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"69e837eeb62e494a2e6d95da" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"5432b628257450440b1253b7" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"ef9e51bcdb987473521c94b9" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"7d501e0244f982810a12eded" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"dc44f67c5bc66fc79bcb9fdd" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"dc44f67c5bc66fc79bcb9fdd" +], +[ +"relationship_scan", +"13109da9c5f39f4f81898de1" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"26ec172c59ec2e1c73aeb2f3" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"3cd7e1c2532296723b94064f" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"c0d6997a660484365c6f5537" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"7982bfc31674d7e1e8b8ce0a" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"213d712724f65014f14e9b98" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"7d501e0244f982810a12eded" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"42dc5b5aeb1c895417c18db2" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"64cf60943772eda8c4ab4076" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"f180a47eeb9c4933f8bee33f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"dc44f67c5bc66fc79bcb9fdd" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"3d909c2159a4a3b9a4c539fc" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"13109da9c5f39f4f81898de1" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"c0d6997a660484365c6f5537" +], +[ +"relationship_scan", +"b7d4cfb0bc6a45e263680da2" +], +[ +"relationship_scan", +"62c8dc4dab68343e4c90a583" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"dc44f67c5bc66fc79bcb9fdd" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"2c829b9d8cb3cd47408a0bed" +], +[ +"relationship_scan", +"e308f6216b2dd3ba3828cc32" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"ca27a2b38f4b19dd3d4322d3" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"f94586774bff2f36b9438389" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"69e837eeb62e494a2e6d95da" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"83c936d9211631eb5da3224c" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"5b3198d25393608c9e54a38d" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"83c936d9211631eb5da3224c" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"de78bc9086c39bc8c6aadba5" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"26ec172c59ec2e1c73aeb2f3" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"a6f8c1a212c77be5ac3759e9" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"7982bfc31674d7e1e8b8ce0a" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"26ec172c59ec2e1c73aeb2f3" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"5d98b8e0e275880a9236dd2e" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"7d501e0244f982810a12eded" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"c0d6997a660484365c6f5537" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"dc44f67c5bc66fc79bcb9fdd" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"dc44f67c5bc66fc79bcb9fdd" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"17e8c4a71f6c0e623d85825c" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"13109da9c5f39f4f81898de1" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"13109da9c5f39f4f81898de1" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"17e8c4a71f6c0e623d85825c" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"f408b50c0152ec835ccd64bf" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"3d48a90a6497543a3f053ae8" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"56f60cfcd71aac7e53b65b2d" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"13109da9c5f39f4f81898de1" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"83c936d9211631eb5da3224c" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"7d501e0244f982810a12eded" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"421149d6558d5646f2d93b9e" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"dc44f67c5bc66fc79bcb9fdd" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"b6940b3438bb9ec17ae2f3d9" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"ff5c10defd431b61508f48a6" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"10ec4ab1bda9423660df12bb" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"17e8c4a71f6c0e623d85825c" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"81769b5710db4312df85e609" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"c23fa4b659ff804e3569ec1b" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"e76cf9f966c509e56b89b14d" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"dc44f67c5bc66fc79bcb9fdd" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"dc44f67c5bc66fc79bcb9fdd" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"d1d91eeb5e485391898fe52b" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"c516f3539ca9c5c120d82566" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"0cc07a9671517c44dc77d2ae" +], +[ +"relationship_scan", +"94360c70a849843e2105681f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"83c936d9211631eb5da3224c" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"13109da9c5f39f4f81898de1" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"c516f3539ca9c5c120d82566" +], +[ +"relationship_scan", +"7982bfc31674d7e1e8b8ce0a" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"26ec172c59ec2e1c73aeb2f3" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"f94586774bff2f36b9438389" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"cfbef8434b87e0a38d8a6dce" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"5b3198d25393608c9e54a38d" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"7982bfc31674d7e1e8b8ce0a" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"3114a6e9b2872c958344da6e" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"559a746f5e3da3ab0dda8d0f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"73c0fe393e5b5690d3fca531" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"e9e1fc62de3c6c54842a79de" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"f7562ce4c8a86cc6289690eb" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"7d501e0244f982810a12eded" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"3cd7e1c2532296723b94064f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"00769da5cbe0dd726dfeacec" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"a937980669efb123cb98aa5a" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"ac6e10b0a10fe85785865011" +], +[ +"relationship_scan", +"d1d91eeb5e485391898fe52b" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"13109da9c5f39f4f81898de1" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"69e837eeb62e494a2e6d95da" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"69e837eeb62e494a2e6d95da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"af2af28fb49fe10a135f75ce" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"13109da9c5f39f4f81898de1" +], +[ +"relationship_scan", +"f94586774bff2f36b9438389" +], +[ +"relationship_scan", +"ecc094c9096205362b06f0d0" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"7d501e0244f982810a12eded" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"c0d6997a660484365c6f5537" +], +[ +"relationship_scan", +"5ee866e3ecad7a6c82ae9e19" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"ff5c10defd431b61508f48a6" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"13109da9c5f39f4f81898de1" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"83c936d9211631eb5da3224c" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"81461167c67d7f609e67751b" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"f618cc4170841e083fc9e811" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"f5c6d72e6f10acc72866da36" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"fe4cb0a45939795e3facf67c" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"92392e036493fb8448722543" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"26ec172c59ec2e1c73aeb2f3" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"13109da9c5f39f4f81898de1" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"83c936d9211631eb5da3224c" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"69e837eeb62e494a2e6d95da" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"7982bfc31674d7e1e8b8ce0a" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"7982bfc31674d7e1e8b8ce0a" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"19296bb3b2ec52e6ed45792b" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"26ec172c59ec2e1c73aeb2f3" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"1d02a84d63fafde4d1bf3c06" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"ff5c10defd431b61508f48a6" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"7d501e0244f982810a12eded" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"be4802cb587fb93df0677e63" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"a00a6ea595d3733ae6bdecbe" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"83c936d9211631eb5da3224c" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"83c936d9211631eb5da3224c" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"dc44f67c5bc66fc79bcb9fdd" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"26ec172c59ec2e1c73aeb2f3" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1d02a84d63fafde4d1bf3c06" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"69e837eeb62e494a2e6d95da" +], +[ +"relationship_scan", +"a3b8d8894423895f21677109" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"9e3f94fe8fa71cab098c2be0" +], +[ +"relationship_scan", +"c0d6997a660484365c6f5537" +], +[ +"relationship_scan", +"098ce8c721eec02b0e5497d4" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"b01ff70c7c8024ca83424077" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"e7de380006ea3938f0a5e3a4" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"69e837eeb62e494a2e6d95da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"f9cdf97aade5823a9831739c" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"7982bfc31674d7e1e8b8ce0a" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"fb0039315b28e93c8d46e1a5" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"ae91faaf159c10db1dcbbbcb" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"62c8dc4dab68343e4c90a583" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"69e837eeb62e494a2e6d95da" +], +[ +"relationship_scan", +"13109da9c5f39f4f81898de1" +], +[ +"relationship_scan", +"13109da9c5f39f4f81898de1" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"dc44f67c5bc66fc79bcb9fdd" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"33026aa7b75cdb1184ce1ace" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"e2deae92e09652b5dddd22ce" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"f94586774bff2f36b9438389" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"7a47bd6ad794289ee181deff" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"7d501e0244f982810a12eded" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"3cd7e1c2532296723b94064f" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"74a57c70aadf57b9d735b0e4" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"26ec172c59ec2e1c73aeb2f3" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"13109da9c5f39f4f81898de1" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"ff5c10defd431b61508f48a6" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"83c936d9211631eb5da3224c" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"3cd7e1c2532296723b94064f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"861af9d427d640309f55157e" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"7982bfc31674d7e1e8b8ce0a" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"724ba6d2f238cbc21a387b05" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"c0d6997a660484365c6f5537" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"ef968a9f52aee92bb99846ee" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"26ec172c59ec2e1c73aeb2f3" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"13109da9c5f39f4f81898de1" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"ca27a2b38f4b19dd3d4322d3" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"a3b8d8894423895f21677109" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"ca27a2b38f4b19dd3d4322d3" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"69e837eeb62e494a2e6d95da" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"69e837eeb62e494a2e6d95da" +], +[ +"relationship_scan", +"4c25ae7899236b090835c6db" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"7982bfc31674d7e1e8b8ce0a" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"69e837eeb62e494a2e6d95da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"dc44f67c5bc66fc79bcb9fdd" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"fe30dd97c721722f8743b30e" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"69e837eeb62e494a2e6d95da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"de77dfae78a7ab4950c16075" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1d02a84d63fafde4d1bf3c06" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"73c0fe393e5b5690d3fca531" +], +[ +"relationship_scan", +"00769da5cbe0dd726dfeacec" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"724ba6d2f238cbc21a387b05" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"c901777d081de9e0e1000ff4" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"b21427bca0b4b8ab3853dfce" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"d1d91eeb5e485391898fe52b" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"c577cd193800695d1504fd71" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"fe4cb0a45939795e3facf67c" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"de78bc9086c39bc8c6aadba5" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"7982bfc31674d7e1e8b8ce0a" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"724ba6d2f238cbc21a387b05" +], +[ +"relationship_scan", +"b6940b3438bb9ec17ae2f3d9" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"5693addc29c47d33bebf4dcb" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"62c8dc4dab68343e4c90a583" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"fe30dd97c721722f8743b30e" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"724ba6d2f238cbc21a387b05" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"ae91faaf159c10db1dcbbbcb" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"fb498f81d96450b36c3b1229" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"580885eecbd90bb1f82597e5" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"26ec172c59ec2e1c73aeb2f3" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"fe30dd97c721722f8743b30e" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"47e0b66f32a4e57dcd3d3b1f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +] +] diff --git a/tests/goldens/python_oracle/relationship_scan_nested_comments_dialect.json b/tests/goldens/python_oracle/relationship_scan_nested_comments_dialect.json new file mode 100644 index 0000000000..665a7d0854 --- /dev/null +++ b/tests/goldens/python_oracle/relationship_scan_nested_comments_dialect.json @@ -0,0 +1,12002 @@ +[ +[ +"relationship_scan", +"13109da9c5f39f4f81898de1" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"e7de380006ea3938f0a5e3a4" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"13109da9c5f39f4f81898de1" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"83c936d9211631eb5da3224c" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"8bfa6cf7d9f39cd5efb8f5fb" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"3cd7e1c2532296723b94064f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"26ec172c59ec2e1c73aeb2f3" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"13109da9c5f39f4f81898de1" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"dc44f67c5bc66fc79bcb9fdd" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"724ba6d2f238cbc21a387b05" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"92392e036493fb8448722543" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"7d501e0244f982810a12eded" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"a3b8d8894423895f21677109" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"13109da9c5f39f4f81898de1" +], +[ +"relationship_scan", +"fe4cb0a45939795e3facf67c" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1d02a84d63fafde4d1bf3c06" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"26ec172c59ec2e1c73aeb2f3" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"992b5778bb655a00da7d71e4" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"675d3dfdec9bb05af7d9220a" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"724ba6d2f238cbc21a387b05" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"11d5220b939f393a21b19853" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"73c0fe393e5b5690d3fca531" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"4c4f5ae247068467caf252fa" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"7982bfc31674d7e1e8b8ce0a" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"c516f3539ca9c5c120d82566" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"ed589f77ea8fa21c00ac776e" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"13109da9c5f39f4f81898de1" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"5ce261e2e6f23671f6aed2fc" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"00769da5cbe0dd726dfeacec" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"c0d6997a660484365c6f5537" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"28676bc57d6cb5224c2eaabb" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"84f221397a9eab21b448d893" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"33026aa7b75cdb1184ce1ace" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"d4bbd58d7ad9570e86406c6c" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"a3b8d8894423895f21677109" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"b6940b3438bb9ec17ae2f3d9" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"691ed5633cde0a0b8352bfbc" +], +[ +"relationship_scan", +"f9cdf97aade5823a9831739c" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"675d3dfdec9bb05af7d9220a" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"92392e036493fb8448722543" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"d81b7bf0b3424a4ee174a60e" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"580885eecbd90bb1f82597e5" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"bdf8273dcb44c1f3504a7280" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"7982bfc31674d7e1e8b8ce0a" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"5d98b8e0e275880a9236dd2e" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"83c936d9211631eb5da3224c" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"7a4dc202a4e5e510088b04c6" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"0ef81c9272b362eae36af07e" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"c0d6997a660484365c6f5537" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"ae91faaf159c10db1dcbbbcb" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"4c4f5ae247068467caf252fa" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"83c936d9211631eb5da3224c" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"17e8c4a71f6c0e623d85825c" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"13109da9c5f39f4f81898de1" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"ca27a2b38f4b19dd3d4322d3" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"b8d200bc9a5e36062e460c3f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"2a1ba2f1651971d6a1558949" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"73c0fe393e5b5690d3fca531" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"93413d4e0eb0e35d2cd5aa1c" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"4ac473d5a38f415f6efab2d7" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"33026aa7b75cdb1184ce1ace" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"0f1137297486fd3082ab549e" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"4ac473d5a38f415f6efab2d7" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"bf1bef6516960b5981f26b31" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"26ec172c59ec2e1c73aeb2f3" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"69e837eeb62e494a2e6d95da" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"c0d6997a660484365c6f5537" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"83c936d9211631eb5da3224c" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"26ec172c59ec2e1c73aeb2f3" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"92392e036493fb8448722543" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"7d501e0244f982810a12eded" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"dc44f67c5bc66fc79bcb9fdd" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"06ea59a7166830e1d0ec1f76" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"e2deae92e09652b5dddd22ce" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"951de7c6a9695b79eab5d68c" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"7a4dc202a4e5e510088b04c6" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"ae91faaf159c10db1dcbbbcb" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"f2a94373ac6b847e63a99c04" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"68ab9a875e02dd7306004d3b" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"724ba6d2f238cbc21a387b05" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"10ec4ab1bda9423660df12bb" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"f6f5bcbd7893eb406b8e86be" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"7a4dc202a4e5e510088b04c6" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"c0d6997a660484365c6f5537" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"7986290462d8b3e2587f7244" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"5e1d6804fe374eae91bf3159" +], +[ +"relationship_scan", +"3a440536928439156fd530cf" +], +[ +"relationship_scan", +"af2af28fb49fe10a135f75ce" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"5d98b8e0e275880a9236dd2e" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"13109da9c5f39f4f81898de1" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"5b3198d25393608c9e54a38d" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"c0d6997a660484365c6f5537" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"ff5c10defd431b61508f48a6" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"13109da9c5f39f4f81898de1" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"26ec172c59ec2e1c73aeb2f3" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"c0d6997a660484365c6f5537" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"dc44f67c5bc66fc79bcb9fdd" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"1ebfd73c2d8073d2e95ad475" +], +[ +"relationship_scan", +"7982bfc31674d7e1e8b8ce0a" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"13109da9c5f39f4f81898de1" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"cad211a8dc36cff5f814a54b" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"724ba6d2f238cbc21a387b05" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"363d6f8d3c3046dd2a97a90b" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"d846a400d539e830953b3f82" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"69e837eeb62e494a2e6d95da" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"13109da9c5f39f4f81898de1" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"af2642902d40879fb19181d1" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"559a746f5e3da3ab0dda8d0f" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"92392e036493fb8448722543" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"18e4ff53db33185111821443" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"7d501e0244f982810a12eded" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"de78bc9086c39bc8c6aadba5" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"c0d6997a660484365c6f5537" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"ae91faaf159c10db1dcbbbcb" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"c0d6997a660484365c6f5537" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"dc44f67c5bc66fc79bcb9fdd" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"97ea34a4d7b0e6b1f9bb6754" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"7982bfc31674d7e1e8b8ce0a" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"8508a1e58836e346dee9eeaa" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"832f6e23b1252077129a8394" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"4c4f5ae247068467caf252fa" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"d4bbd58d7ad9570e86406c6c" +], +[ +"relationship_scan", +"dc44f67c5bc66fc79bcb9fdd" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"724ba6d2f238cbc21a387b05" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"5ce261e2e6f23671f6aed2fc" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"69e837eeb62e494a2e6d95da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"dc44f67c5bc66fc79bcb9fdd" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"675d3dfdec9bb05af7d9220a" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"ec240be4f240d6b1f685853f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"13109da9c5f39f4f81898de1" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"d1d91eeb5e485391898fe52b" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"e7de380006ea3938f0a5e3a4" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"8ba5920d97158646543d68d1" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"724ba6d2f238cbc21a387b05" +], +[ +"relationship_scan", +"c0d6997a660484365c6f5537" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"724ba6d2f238cbc21a387b05" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"4d00fbe5bd076e73073a360f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"ff5c10defd431b61508f48a6" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"47946632b9728216cd56b1c4" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"ca27a2b38f4b19dd3d4322d3" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"7982bfc31674d7e1e8b8ce0a" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"13109da9c5f39f4f81898de1" +], +[ +"relationship_scan", +"dc44f67c5bc66fc79bcb9fdd" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"26ec172c59ec2e1c73aeb2f3" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"00769da5cbe0dd726dfeacec" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"10ec4ab1bda9423660df12bb" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"555298220ce6380b9c52ef77" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"f9cdf97aade5823a9831739c" +], +[ +"relationship_scan", +"3ed5b887bd66bc315abbb0d0" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"559a746f5e3da3ab0dda8d0f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"af2642902d40879fb19181d1" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"13109da9c5f39f4f81898de1" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"ff5c10defd431b61508f48a6" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"213d712724f65014f14e9b98" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"a00a6ea595d3733ae6bdecbe" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"7982bfc31674d7e1e8b8ce0a" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"4b024d0e2335530406204f51" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"13109da9c5f39f4f81898de1" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"a00a6ea595d3733ae6bdecbe" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"ce0ee85a93b4296093c1b658" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"13109da9c5f39f4f81898de1" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"832f6e23b1252077129a8394" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"d4bbd58d7ad9570e86406c6c" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"83c936d9211631eb5da3224c" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"69e837eeb62e494a2e6d95da" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"7d8886cd0f2ebb5fbd225317" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"dc44f67c5bc66fc79bcb9fdd" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"13109da9c5f39f4f81898de1" +], +[ +"relationship_scan", +"64cf60943772eda8c4ab4076" +], +[ +"relationship_scan", +"4ac473d5a38f415f6efab2d7" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"5cb1a4e7332b765787ed7d56" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"7a4dc202a4e5e510088b04c6" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"de0dbe3d87a63aed00766035" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"ae91faaf159c10db1dcbbbcb" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"13109da9c5f39f4f81898de1" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"13109da9c5f39f4f81898de1" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"13109da9c5f39f4f81898de1" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"f1a66383215430f9f3c833f0" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"4201f20ecc920461d474506a" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"7d501e0244f982810a12eded" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"4c4f5ae247068467caf252fa" +], +[ +"relationship_scan", +"26ec172c59ec2e1c73aeb2f3" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"83c936d9211631eb5da3224c" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"33026aa7b75cdb1184ce1ace" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"6c1381fd912ee8d61871a3a3" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"7982bfc31674d7e1e8b8ce0a" +], +[ +"relationship_scan", +"c0d6997a660484365c6f5537" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"e7de380006ea3938f0a5e3a4" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"26ec172c59ec2e1c73aeb2f3" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"8bfa6cf7d9f39cd5efb8f5fb" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"83c936d9211631eb5da3224c" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"ce5d972d49c637af98e2b47d" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"5ee866e3ecad7a6c82ae9e19" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"7982bfc31674d7e1e8b8ce0a" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"992b5778bb655a00da7d71e4" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"ef9e51bcdb987473521c94b9" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"26ec172c59ec2e1c73aeb2f3" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"d94da99480df0afb3a746c14" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"13109da9c5f39f4f81898de1" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"17e8c4a71f6c0e623d85825c" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"a3b8d8894423895f21677109" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"26ec172c59ec2e1c73aeb2f3" +], +[ +"relationship_scan", +"c577cd193800695d1504fd71" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"fe4cb0a45939795e3facf67c" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"7982bfc31674d7e1e8b8ce0a" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"870a919b6614442893edc536" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"483455993db3bce81f93e289" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"64cf60943772eda8c4ab4076" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"635db574c6126ed1bbac759c" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"26ec172c59ec2e1c73aeb2f3" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"7982bfc31674d7e1e8b8ce0a" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"f7f0ff1cf2ee32bd97a12f06" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"65356ad7a7360fa11cc6a4e9" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"bf1bef6516960b5981f26b31" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"dc44f67c5bc66fc79bcb9fdd" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"724ba6d2f238cbc21a387b05" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"d8725a415319d88c92b56397" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"555298220ce6380b9c52ef77" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"cf24c2f836084b913bd870ef" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"06ea59a7166830e1d0ec1f76" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"a3b8d8894423895f21677109" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"dc44f67c5bc66fc79bcb9fdd" +], +[ +"relationship_scan", +"26ec172c59ec2e1c73aeb2f3" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"17e8c4a71f6c0e623d85825c" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"519ee66b98dc0c39f410f60b" +], +[ +"relationship_scan", +"1ebfd73c2d8073d2e95ad475" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"36319bcf0996ec5108def30c" +], +[ +"relationship_scan", +"231f497d98edbebd3ddc13f5" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"83c936d9211631eb5da3224c" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"c0d6997a660484365c6f5537" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"dc44f67c5bc66fc79bcb9fdd" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"241f6446dab2ddad96402fb9" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"39e1cb29ea8de6ecbfebcebf" +], +[ +"relationship_scan", +"724ba6d2f238cbc21a387b05" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"549aa256efc9f908b87da677" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"e91139fd35b64d91435ccb66" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"13109da9c5f39f4f81898de1" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"dc44f67c5bc66fc79bcb9fdd" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"bdf8273dcb44c1f3504a7280" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"62c8dc4dab68343e4c90a583" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"dc44f67c5bc66fc79bcb9fdd" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"69e837eeb62e494a2e6d95da" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"5018e2fc27a349e92ad2c514" +], +[ +"relationship_scan", +"8d407fa8d21b870aaa8c11d9" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"c0d6997a660484365c6f5537" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"fe4cb0a45939795e3facf67c" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"e5aae3dfd3ab6cdd92858cf3" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"13109da9c5f39f4f81898de1" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"1d02a84d63fafde4d1bf3c06" +], +[ +"relationship_scan", +"b720226034f24d3bc59cf3aa" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"7a4dc202a4e5e510088b04c6" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"c0d6997a660484365c6f5537" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"5b3198d25393608c9e54a38d" +], +[ +"relationship_scan", +"4ac473d5a38f415f6efab2d7" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"13109da9c5f39f4f81898de1" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"a79adccd4afe1fecf50a966f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"675d3dfdec9bb05af7d9220a" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"1d02a84d63fafde4d1bf3c06" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"1b58998dd9ab153fb131988a" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"64a80c704fddd1138dcede4b" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"213d712724f65014f14e9b98" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"e2deae92e09652b5dddd22ce" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"13109da9c5f39f4f81898de1" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"083ab7ee92be305eb936d0d0" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"7982bfc31674d7e1e8b8ce0a" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"dc44f67c5bc66fc79bcb9fdd" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"e91139fd35b64d91435ccb66" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"13109da9c5f39f4f81898de1" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"c516f3539ca9c5c120d82566" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"724ba6d2f238cbc21a387b05" +], +[ +"relationship_scan", +"c0d6997a660484365c6f5537" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"992b5778bb655a00da7d71e4" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"7982bfc31674d7e1e8b8ce0a" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"add18a1345f8afba2e0198b9" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"213d712724f65014f14e9b98" +], +[ +"relationship_scan", +"83c936d9211631eb5da3224c" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"ca27a2b38f4b19dd3d4322d3" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"bfae9b565e630124c07affb9" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"8fcf5aaa10ea643c56849e1e" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"2adfffa71538a75f932e2fa0" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"26ec172c59ec2e1c73aeb2f3" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"13109da9c5f39f4f81898de1" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"83c936d9211631eb5da3224c" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"992b5778bb655a00da7d71e4" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"7982bfc31674d7e1e8b8ce0a" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"69e837eeb62e494a2e6d95da" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"e89c783b729ed1764e7eb837" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"7d501e0244f982810a12eded" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"d4bbd58d7ad9570e86406c6c" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"3cd7e1c2532296723b94064f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"7982bfc31674d7e1e8b8ce0a" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +] +] diff --git a/tests/goldens/python_oracle/relationship_scan_slash_comments_dialect.json b/tests/goldens/python_oracle/relationship_scan_slash_comments_dialect.json new file mode 100644 index 0000000000..268cdbb4a6 --- /dev/null +++ b/tests/goldens/python_oracle/relationship_scan_slash_comments_dialect.json @@ -0,0 +1,12002 @@ +[ +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"eb2afa6d328dd92be5f304b9" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"b6940b3438bb9ec17ae2f3d9" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"0046853319a96d03316380b4" +], +[ +"relationship_scan", +"83c936d9211631eb5da3224c" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"bf1bef6516960b5981f26b31" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1ebfd73c2d8073d2e95ad475" +], +[ +"relationship_scan", +"7982bfc31674d7e1e8b8ce0a" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"f94586774bff2f36b9438389" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"26ec172c59ec2e1c73aeb2f3" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"be27c3024b27aae2f3e383c6" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"13109da9c5f39f4f81898de1" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"13109da9c5f39f4f81898de1" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"11d5220b939f393a21b19853" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"17e8c4a71f6c0e623d85825c" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"724ba6d2f238cbc21a387b05" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"c0d6997a660484365c6f5537" +], +[ +"relationship_scan", +"13109da9c5f39f4f81898de1" +], +[ +"relationship_scan", +"bd16e6564139df8319d22d95" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"7aad6dc172e5bd929243b60c" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"055fb1791a2117fd1fb88dc9" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"fe30dd97c721722f8743b30e" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"724ba6d2f238cbc21a387b05" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"af2642902d40879fb19181d1" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"f1a66383215430f9f3c833f0" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"bdf8273dcb44c1f3504a7280" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"fe30dd97c721722f8743b30e" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"83c936d9211631eb5da3224c" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"e56ade38b019d4f7a68977c2" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"83c936d9211631eb5da3224c" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"fd86e4596dfe3a833747873e" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"e2deae92e09652b5dddd22ce" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"0c0e0d8d4427f898a9ef1bdc" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"10ec4ab1bda9423660df12bb" +], +[ +"relationship_scan", +"c577cd193800695d1504fd71" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"13109da9c5f39f4f81898de1" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1ebfd73c2d8073d2e95ad475" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"13109da9c5f39f4f81898de1" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"26ec172c59ec2e1c73aeb2f3" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"e30de3d99c2bb744eb273d12" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"eabf84bd5052c1bf02e57810" +], +[ +"relationship_scan", +"62c8dc4dab68343e4c90a583" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"724ba6d2f238cbc21a387b05" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"de9ade866d9892820e6278e4" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"ef9e51bcdb987473521c94b9" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"26ec172c59ec2e1c73aeb2f3" +], +[ +"relationship_scan", +"c0d6997a660484365c6f5537" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"724ba6d2f238cbc21a387b05" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"13109da9c5f39f4f81898de1" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"da455579fb071fbc72f85683" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"69e837eeb62e494a2e6d95da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"7982bfc31674d7e1e8b8ce0a" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"73c0fe393e5b5690d3fca531" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"96c44f9c12663f2cd628ad92" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"13109da9c5f39f4f81898de1" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"d14402daba20662061977f41" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"9ce1efff6889c67a9585050b" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"c0d6997a660484365c6f5537" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"a0557c6134a4443adaa1be7b" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"26ec172c59ec2e1c73aeb2f3" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"281362ff2f4c94700c9a9fb6" +], +[ +"relationship_scan", +"415c76bd8fd09531638663fc" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"992b5778bb655a00da7d71e4" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"b6940b3438bb9ec17ae2f3d9" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"10ec4ab1bda9423660df12bb" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"69e837eeb62e494a2e6d95da" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"d6f82e5d94843b36581be7bf" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"6e4bb09886287b3c8aad775e" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"69e837eeb62e494a2e6d95da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"e7de380006ea3938f0a5e3a4" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"d4bbd58d7ad9570e86406c6c" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"daa42f0a07a717ffad57e3d6" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"4f88513270dce52b601d2f8d" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"7d501e0244f982810a12eded" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"8c610fdd88860558bb28e698" +], +[ +"relationship_scan", +"a26dd4604ca1463be85f240b" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"3cd7e1c2532296723b94064f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"13109da9c5f39f4f81898de1" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"92392e036493fb8448722543" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"f5c6d72e6f10acc72866da36" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"c0d6997a660484365c6f5537" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"13109da9c5f39f4f81898de1" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"724ba6d2f238cbc21a387b05" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"6cf970e486b1151ea07fc787" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"7982bfc31674d7e1e8b8ce0a" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"83c936d9211631eb5da3224c" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"10ec4ab1bda9423660df12bb" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"5432b628257450440b1253b7" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"6ab5406cc7aebb255508e0b7" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"dc44f67c5bc66fc79bcb9fdd" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"dc44f67c5bc66fc79bcb9fdd" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"13109da9c5f39f4f81898de1" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"014780726007cb076fd3abac" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"5d98b8e0e275880a9236dd2e" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"13109da9c5f39f4f81898de1" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"7982bfc31674d7e1e8b8ce0a" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"bf1bef6516960b5981f26b31" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"26ec172c59ec2e1c73aeb2f3" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"7d501e0244f982810a12eded" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"83c936d9211631eb5da3224c" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"7982bfc31674d7e1e8b8ce0a" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"dc44f67c5bc66fc79bcb9fdd" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"13109da9c5f39f4f81898de1" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"33026aa7b75cdb1184ce1ace" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"ea8d47f00d8db1b50237988a" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"fe30dd97c721722f8743b30e" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1ef683520236c27f46b94382" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"7d501e0244f982810a12eded" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"83c936d9211631eb5da3224c" +], +[ +"relationship_scan", +"af2642902d40879fb19181d1" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"675d3dfdec9bb05af7d9220a" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"69c9fad5bd6096008b06dd1d" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"d846a400d539e830953b3f82" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"dc44f67c5bc66fc79bcb9fdd" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"13109da9c5f39f4f81898de1" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"9e3f94fe8fa71cab098c2be0" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"f9a2b5a6900bbb02c1888a76" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"dc44f67c5bc66fc79bcb9fdd" +], +[ +"relationship_scan", +"8bfa6cf7d9f39cd5efb8f5fb" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"13109da9c5f39f4f81898de1" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"fe4cb0a45939795e3facf67c" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"26ec172c59ec2e1c73aeb2f3" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"83c936d9211631eb5da3224c" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"e2deae92e09652b5dddd22ce" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"4c4f5ae247068467caf252fa" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"9e3f94fe8fa71cab098c2be0" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"83c936d9211631eb5da3224c" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"e2deae92e09652b5dddd22ce" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"096a42122bfb3b6bc01acfaa" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1d02a84d63fafde4d1bf3c06" +], +[ +"relationship_scan", +"231f497d98edbebd3ddc13f5" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"13109da9c5f39f4f81898de1" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"9936bb7c38f56c7a1fe4e32d" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"fe30dd97c721722f8743b30e" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"5ee8b43cb49f5fbf3e418a01" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"b1821a7be091282be22f17c3" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"dc44f67c5bc66fc79bcb9fdd" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"580885eecbd90bb1f82597e5" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"c516f3539ca9c5c120d82566" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"ae91faaf159c10db1dcbbbcb" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"33922b397222c101fb9ee721" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"c577cd193800695d1504fd71" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"9e3f94fe8fa71cab098c2be0" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"2f7e9201eb5edc668c12967a" +], +[ +"relationship_scan", +"724ba6d2f238cbc21a387b05" +], +[ +"relationship_scan", +"fb498f81d96450b36c3b1229" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"c0d6997a660484365c6f5537" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"73c0fe393e5b5690d3fca531" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"27c59d3365ae9086cdf151ab" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"f94586774bff2f36b9438389" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"f94586774bff2f36b9438389" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"f5c6d72e6f10acc72866da36" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"7982bfc31674d7e1e8b8ce0a" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"675d3dfdec9bb05af7d9220a" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"c0d6997a660484365c6f5537" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"83c936d9211631eb5da3224c" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"82e2a4654e00ff23660fb891" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"00769da5cbe0dd726dfeacec" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"e2deae92e09652b5dddd22ce" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"f7f0ff1cf2ee32bd97a12f06" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"83c936d9211631eb5da3224c" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"c0d6997a660484365c6f5537" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"cab7bc045f7100af1343c98d" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"7d501e0244f982810a12eded" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"7d501e0244f982810a12eded" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"13109da9c5f39f4f81898de1" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"c0d6997a660484365c6f5537" +], +[ +"relationship_scan", +"3cd7e1c2532296723b94064f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"7d501e0244f982810a12eded" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"f052dd673363259cf025ba48" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"7982bfc31674d7e1e8b8ce0a" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"dc44f67c5bc66fc79bcb9fdd" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"13109da9c5f39f4f81898de1" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"724ba6d2f238cbc21a387b05" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"231f497d98edbebd3ddc13f5" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"8cd9a73d282b2a6324bb9b2d" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"7982bfc31674d7e1e8b8ce0a" +], +[ +"relationship_scan", +"13109da9c5f39f4f81898de1" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"dc44f67c5bc66fc79bcb9fdd" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"d1d91eeb5e485391898fe52b" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"83c936d9211631eb5da3224c" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"69e837eeb62e494a2e6d95da" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"69e837eeb62e494a2e6d95da" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"bdf8273dcb44c1f3504a7280" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"7982bfc31674d7e1e8b8ce0a" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"559a746f5e3da3ab0dda8d0f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"e7de380006ea3938f0a5e3a4" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"83c936d9211631eb5da3224c" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"11d5220b939f393a21b19853" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"dc44f67c5bc66fc79bcb9fdd" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"dc44f67c5bc66fc79bcb9fdd" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"dc44f67c5bc66fc79bcb9fdd" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"ae616509f741ea20a39b6210" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"69e837eeb62e494a2e6d95da" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"b6940b3438bb9ec17ae2f3d9" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"9e3f94fe8fa71cab098c2be0" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"6b67da3a7a1f59ddf6e67779" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"555298220ce6380b9c52ef77" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"69e837eeb62e494a2e6d95da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"580885eecbd90bb1f82597e5" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"724ba6d2f238cbc21a387b05" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"5ee866e3ecad7a6c82ae9e19" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"580885eecbd90bb1f82597e5" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"13109da9c5f39f4f81898de1" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"9488a1d77871488acbebd59f" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"1ebfd73c2d8073d2e95ad475" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"7d501e0244f982810a12eded" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"9e3f94fe8fa71cab098c2be0" +], +[ +"relationship_scan", +"13109da9c5f39f4f81898de1" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"d4bbd58d7ad9570e86406c6c" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"459e21f584cde6390509a840" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"5d98b8e0e275880a9236dd2e" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"c516f3539ca9c5c120d82566" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"64cf60943772eda8c4ab4076" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"33026aa7b75cdb1184ce1ace" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"69e837eeb62e494a2e6d95da" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"7d501e0244f982810a12eded" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"5ee866e3ecad7a6c82ae9e19" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"bdf8273dcb44c1f3504a7280" +], +[ +"relationship_scan", +"5ad9dd6976c2a82ea2916815" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"675d3dfdec9bb05af7d9220a" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"5ee866e3ecad7a6c82ae9e19" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"33026aa7b75cdb1184ce1ace" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"33026aa7b75cdb1184ce1ace" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"8c440652c8c6caf4950fc95d" +], +[ +"relationship_scan", +"8bfa6cf7d9f39cd5efb8f5fb" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"400d95ea3c437722f01b4b34" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"ca27a2b38f4b19dd3d4322d3" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"00769da5cbe0dd726dfeacec" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"42f2d7be88aa1df60e95fe9e" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"fe4cb0a45939795e3facf67c" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"65356ad7a7360fa11cc6a4e9" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"83c936d9211631eb5da3224c" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"233fb28c266f95c42fb32a46" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"555298220ce6380b9c52ef77" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"c516f3539ca9c5c120d82566" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"fb498f81d96450b36c3b1229" +], +[ +"relationship_scan", +"26ec172c59ec2e1c73aeb2f3" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"dc44f67c5bc66fc79bcb9fdd" +], +[ +"relationship_scan", +"c2b0726293b9fb1d1db86c59" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"ff229f4e9827b2241dafbc10" +], +[ +"relationship_scan", +"7d501e0244f982810a12eded" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"13109da9c5f39f4f81898de1" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"f1340cb3c30a32cc60af522e" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"a3b8d8894423895f21677109" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"13109da9c5f39f4f81898de1" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23ba7bbbeafa7e14cd5d168b" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"97e81cd8cd956d6e9b65309f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"dc44f67c5bc66fc79bcb9fdd" +], +[ +"relationship_scan", +"10ec4ab1bda9423660df12bb" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"724ba6d2f238cbc21a387b05" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"13109da9c5f39f4f81898de1" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"13109da9c5f39f4f81898de1" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"c0d6997a660484365c6f5537" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"231f497d98edbebd3ddc13f5" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"c0d6997a660484365c6f5537" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"5ee866e3ecad7a6c82ae9e19" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"dc44f67c5bc66fc79bcb9fdd" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"13109da9c5f39f4f81898de1" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"7d501e0244f982810a12eded" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"13109da9c5f39f4f81898de1" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"83c936d9211631eb5da3224c" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"7d501e0244f982810a12eded" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"559a746f5e3da3ab0dda8d0f" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"efb21d196591eb41f295ae52" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"580885eecbd90bb1f82597e5" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"4f3e015b9f88f3ebd0569cf8" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"c0d6997a660484365c6f5537" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"e94c126c8092ea5668a526be" +], +[ +"relationship_scan", +"26f2fafd8e8686fba727e697" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"d1d91eeb5e485391898fe52b" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"69e837eeb62e494a2e6d95da" +], +[ +"relationship_scan", +"de78bc9086c39bc8c6aadba5" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"00769da5cbe0dd726dfeacec" +], +[ +"relationship_scan", +"c0d6997a660484365c6f5537" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"d846a400d539e830953b3f82" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"74a3816101acdc4912ac700e" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"c55aaf5c93117c92e7a561fb" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"13109da9c5f39f4f81898de1" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"1ebfd73c2d8073d2e95ad475" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"606308e2aa33431d356159c9" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"dc44f67c5bc66fc79bcb9fdd" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"dc44f67c5bc66fc79bcb9fdd" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"90d92cd50766c7e66fbb46f8" +], +[ +"relationship_scan", +"26ec172c59ec2e1c73aeb2f3" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"a5164e335ba70fc57dce10f6" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"13109da9c5f39f4f81898de1" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"724ba6d2f238cbc21a387b05" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"69e837eeb62e494a2e6d95da" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"bdf8273dcb44c1f3504a7280" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"23990d5e82c5bde1e18c01da" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +] +] diff --git a/tests/goldens/python_oracle/relationship_scan_unicode_identifier_and_keyword_edges.json b/tests/goldens/python_oracle/relationship_scan_unicode_identifier_and_keyword_edges.json new file mode 100644 index 0000000000..486bd275c4 --- /dev/null +++ b/tests/goldens/python_oracle/relationship_scan_unicode_identifier_and_keyword_edges.json @@ -0,0 +1,706 @@ +[ +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"e0792de1aeaa20fa494fd6d4" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"2dcc4acb0e2e9f2bac25652b" +], +[ +"relationship_scan", +"49aef06c4b607fa7174a63d0" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"cc5e20b2e6bc8670b6e2568d" +], +[ +"relationship_scan", +"56f4bb5040f04e84faf0a311" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"14fa8747e0122561d98d0058" +], +[ +"relationship_scan", +"e6b985b0ee5fb197e2ed2949" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"ffd27c85b69ef765a7b016dd" +], +[ +"relationship_scan", +"285da5f34353c56078c50b83" +], +[ +"relationship_scan", +"96a8c0392855603d1014c040" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"be1a7ed9401aa8d1fad108e3" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"e0792de1aeaa20fa494fd6d4" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"59687e5abb14c38215161fcb" +], +[ +"relationship_scan", +"05a31371bd85901f5b54fdbc" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"e49d183ef2d425fc32041cd2" +], +[ +"relationship_scan", +"2b7fe845e7053734553719b5" +], +[ +"relationship_scan", +"b384f004dd3afd2d783796eb" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"39b7acc03bee6e653a99edcb" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"56b5ffe7966f617a06ee1b55" +], +[ +"relationship_scan", +"093c1f28bc4bfb4fd6dbc7e6" +], +[ +"relationship_scan", +"c1e2f3f94e5502280de31aba" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"8d61a757a517a358c8d7a903" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"e0792de1aeaa20fa494fd6d4" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"c78d8b79df7373ab9aaa7778" +], +[ +"relationship_scan", +"56499424a43e65f1484bdd8d" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"faaffd2b633c4471c2987321" +], +[ +"relationship_scan", +"10cf149069ec1a5f92ee841b" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"1737aef2fafd640cf710093f" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"4a31d86722a6780753dfd4cf" +], +[ +"relationship_scan", +"19d94ad7d5a7c52ec98a9bb7" +], +[ +"relationship_scan", +"757d65c8bfbeff313bde8fe0" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"d8dbfd1ba87ee2b489f9b713" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"7175b348030ff7b753fe05c4" +], +[ +"relationship_scan", +"1d6a433b70aa9e8a5578b9c6" +], +[ +"relationship_scan", +"74143900a16e0949d7e4afb4" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"51bafb10380b32e748257671" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"c67071f58305b795be4165db" +], +[ +"relationship_scan", +"0496cf5ebe15f05a5b6ccfbf" +], +[ +"relationship_scan", +"670a78a12b68cebe739c1211" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"9c91343f2279b48915d0c132" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"d3e3aa061c19fa680424f623" +], +[ +"relationship_scan", +"299cee81b7e8b12105fa54e2" +], +[ +"relationship_scan", +"5b7950deac36ce4181287be5" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +], +[ +"relationship_scan", +"717b3f8e139f594f9e766616" +], +[ +"relationship_scan", +"0f122872352ce95b09ae311c" +], +[ +"relationship_scan", +"115fb5923729db29a887b522" +], +[ +"relationship_scan", +"199553205d07e4b204fe9c37" +] +] diff --git a/tests/goldens/python_oracle/semantic_formerly_deferred_dialects_added_to_the_native_parser_build.json b/tests/goldens/python_oracle/semantic_formerly_deferred_dialects_added_to_the_native_parser_build.json new file mode 100644 index 0000000000..64b357cbe9 --- /dev/null +++ b/tests/goldens/python_oracle/semantic_formerly_deferred_dialects_added_to_the_native_parser_build.json @@ -0,0 +1,24 @@ +[ +[ +"completion", +{ +"databricks": "25140233ccf8e7760c91ffd6", +"mysql": "25140233ccf8e7760c91ffd6", +"oracle": "25140233ccf8e7760c91ffd6", +"sqlite": "25140233ccf8e7760c91ffd6", +"trino": "25140233ccf8e7760c91ffd6", +"tsql": "25140233ccf8e7760c91ffd6" +} +], +[ +"completion", +{ +"databricks": "edd3b1ec05f9481067078045", +"mysql": "edd3b1ec05f9481067078045", +"oracle": "edd3b1ec05f9481067078045", +"sqlite": "edd3b1ec05f9481067078045", +"trino": "edd3b1ec05f9481067078045", +"tsql": "edd3b1ec05f9481067078045" +} +] +] diff --git a/tests/goldens/python_oracle/semantic_formerly_deferred_no_dialect_and_an_unknown_dialect_raise_the_wheel_s_errors.json b/tests/goldens/python_oracle/semantic_formerly_deferred_no_dialect_and_an_unknown_dialect_raise_the_wheel_s_errors.json new file mode 100644 index 0000000000..8d1adcbf89 --- /dev/null +++ b/tests/goldens/python_oracle/semantic_formerly_deferred_no_dialect_and_an_unknown_dialect_raise_the_wheel_s_errors.json @@ -0,0 +1,16 @@ +[ +[ +"completion", +{ +"None": "8c4cd35551096786ad11558f", +"nonsense": "6f6079f31e12e028922d40f2" +} +], +[ +"completion", +{ +"None": "8c4cd35551096786ad11558f", +"nonsense": "6f6079f31e12e028922d40f2" +} +] +] diff --git a/tests/goldens/python_oracle/semantic_formerly_deferred_non_ascii_names_comments_and_line_separators.json b/tests/goldens/python_oracle/semantic_formerly_deferred_non_ascii_names_comments_and_line_separators.json new file mode 100644 index 0000000000..297a968cbf --- /dev/null +++ b/tests/goldens/python_oracle/semantic_formerly_deferred_non_ascii_names_comments_and_line_separators.json @@ -0,0 +1,38 @@ +[ +[ +"completion", +{ +"bigquery": "72198dc725abd42004ae2f92", +"duckdb": "72198dc725abd42004ae2f92", +"postgres": "72198dc725abd42004ae2f92", +"snowflake": "72198dc725abd42004ae2f92" +} +], +[ +"completion", +{ +"bigquery": "eb3b9bf0df6905ad935dadba", +"duckdb": "2bb0db315a6b4bd580d0f1da", +"postgres": "2bb0db315a6b4bd580d0f1da", +"snowflake": "2bb0db315a6b4bd580d0f1da" +} +], +[ +"completion", +{ +"bigquery": "167cc5c4a5563a44e435d35a", +"duckdb": "167cc5c4a5563a44e435d35a", +"postgres": "167cc5c4a5563a44e435d35a", +"snowflake": "167cc5c4a5563a44e435d35a" +} +], +[ +"completion", +{ +"bigquery": "b64b5864b0dd1efc66efe5c5", +"duckdb": "b64b5864b0dd1efc66efe5c5", +"postgres": "b64b5864b0dd1efc66efe5c5", +"snowflake": "b64b5864b0dd1efc66efe5c5" +} +] +] diff --git a/tests/goldens/python_oracle/semantic_generated_typos_aliases_temporal_comparisons_type_errors_and_opt_outs.json b/tests/goldens/python_oracle/semantic_generated_typos_aliases_temporal_comparisons_type_errors_and_opt_outs.json new file mode 100644 index 0000000000..b09f4e70a7 --- /dev/null +++ b/tests/goldens/python_oracle/semantic_generated_typos_aliases_temporal_comparisons_type_errors_and_opt_outs.json @@ -0,0 +1,74 @@ +[ +[ +"completion", +{ +"bigquery": "386e47117f671dcf1e99ba79", +"duckdb": "f8a96a6ad1b63bd08886df5e", +"postgres": "f8a96a6ad1b63bd08886df5e", +"snowflake": "f8a96a6ad1b63bd08886df5e" +} +], +[ +"completion", +{ +"bigquery": "6b2a976a568aea0841340272", +"duckdb": "6b2a976a568aea0841340272", +"postgres": "6b2a976a568aea0841340272", +"snowflake": "6b2a976a568aea0841340272" +} +], +[ +"completion", +{ +"bigquery": "da1919b4d28cc12b6aeb0d6a", +"duckdb": "da1919b4d28cc12b6aeb0d6a", +"postgres": "da1919b4d28cc12b6aeb0d6a", +"snowflake": "da1919b4d28cc12b6aeb0d6a" +} +], +[ +"completion", +{ +"bigquery": "0f8a7d8a92a2525f96180eab", +"duckdb": "0f8a7d8a92a2525f96180eab", +"postgres": "0f8a7d8a92a2525f96180eab", +"snowflake": "0f8a7d8a92a2525f96180eab" +} +], +[ +"completion", +{ +"bigquery": "a0775e9568c53c1c04d03b9e", +"duckdb": "a0775e9568c53c1c04d03b9e", +"postgres": "a0775e9568c53c1c04d03b9e", +"snowflake": "a0775e9568c53c1c04d03b9e" +} +], +[ +"completion", +{ +"bigquery": "56d1dd61d4d03302a8f2934a", +"duckdb": "ec5f01a5076273dcce4865e9", +"postgres": "ec5f01a5076273dcce4865e9", +"snowflake": "ec5f01a5076273dcce4865e9" +} +], +[ +"completion", +{ +"bigquery": "f9877a22ff91f0e41760f3cc", +"duckdb": "f9877a22ff91f0e41760f3cc", +"postgres": "f9877a22ff91f0e41760f3cc", +"snowflake": "f9877a22ff91f0e41760f3cc" +} +], +[ +"completion", +{ +"bigquery": "89c0ecb9bfa8db140822ca46", +"duckdb": "e8762d8e3f7d18a056f664ad", +"postgres": "e8762d8e3f7d18a056f664ad", +"snowflake": "e8762d8e3f7d18a056f664ad" +} +] +] diff --git a/tests/goldens/python_oracle/semantic_session_analysis_session_corpus_with_pivots_stars_and_set_operations.json b/tests/goldens/python_oracle/semantic_session_analysis_session_corpus_with_pivots_stars_and_set_operations.json new file mode 100644 index 0000000000..9000a6d33b --- /dev/null +++ b/tests/goldens/python_oracle/semantic_session_analysis_session_corpus_with_pivots_stars_and_set_operations.json @@ -0,0 +1,18 @@ +[ +[ +"completion", +"f85970edb78845ff2ce0ea2c" +], +[ +"completion", +"7149dab572362b7f40692734" +], +[ +"completion", +"c72855d94cb69680061f4edd" +], +[ +"completion", +"808ea581e0aab0f08630bc23" +] +] diff --git a/tests/goldens/python_oracle/semantic_session_failing_semantics_corpus.json b/tests/goldens/python_oracle/semantic_session_failing_semantics_corpus.json new file mode 100644 index 0000000000..292cd9e8ea --- /dev/null +++ b/tests/goldens/python_oracle/semantic_session_failing_semantics_corpus.json @@ -0,0 +1,26 @@ +[ +[ +"completion", +"1b1aca58c29b7d2a4885cd24" +], +[ +"completion", +"7d957239333982bbc2a73159" +], +[ +"completion", +"17d9bf58e797f8ac09758305" +], +[ +"completion", +"758b2e20f1f61ae3237cc60b" +], +[ +"completion", +"d76482d15b26655a451ba2bc" +], +[ +"completion", +"28fd253e8477c9fa71e5c357" +] +] diff --git a/tests/goldens/python_oracle/sql_test_assembly_a_decimal_case_parameter_the_default_context_overflows.json b/tests/goldens/python_oracle/sql_test_assembly_a_decimal_case_parameter_the_default_context_overflows.json new file mode 100644 index 0000000000..82e0cdc498 --- /dev/null +++ b/tests/goldens/python_oracle/sql_test_assembly_a_decimal_case_parameter_the_default_context_overflows.json @@ -0,0 +1,10 @@ +[ +[ +"sql_test_assembly", +{ +"diagnostics": "74234e98afe7498fb5daf1f3", +"raised": "eda90da258aa7debe1d39bd6", +"sql_tests": "74234e98afe7498fb5daf1f3" +} +] +] diff --git a/tests/goldens/python_oracle/sql_test_assembly_a_macro_test_over_a_model_with_a_non_ascii_name_after.json b/tests/goldens/python_oracle/sql_test_assembly_a_macro_test_over_a_model_with_a_non_ascii_name_after.json new file mode 100644 index 0000000000..cebfde29f7 --- /dev/null +++ b/tests/goldens/python_oracle/sql_test_assembly_a_macro_test_over_a_model_with_a_non_ascii_name_after.json @@ -0,0 +1,10 @@ +[ +[ +"sql_test_assembly", +{ +"diagnostics": "97401f24e7899c2504f00597", +"raised": "74234e98afe7498fb5daf1f3", +"sql_tests": "e0d1db85219183b51c102852" +} +] +] diff --git a/tests/goldens/python_oracle/sql_test_assembly_a_mock_reading_a_deeply_nested_helper_whose_nested_cte_shadows_another.json b/tests/goldens/python_oracle/sql_test_assembly_a_mock_reading_a_deeply_nested_helper_whose_nested_cte_shadows_another.json new file mode 100644 index 0000000000..efb18880b9 --- /dev/null +++ b/tests/goldens/python_oracle/sql_test_assembly_a_mock_reading_a_deeply_nested_helper_whose_nested_cte_shadows_another.json @@ -0,0 +1,10 @@ +[ +[ +"sql_test_assembly", +{ +"diagnostics": "134b5a980760bc0b6c888571", +"raised": "74234e98afe7498fb5daf1f3", +"sql_tests": "85aa78137e27cd6c6ebae02b" +} +] +] diff --git a/tests/goldens/python_oracle/sql_test_assembly_an_unread_helper_with_an_invalid_reference_call.json b/tests/goldens/python_oracle/sql_test_assembly_an_unread_helper_with_an_invalid_reference_call.json new file mode 100644 index 0000000000..4e73795ae1 --- /dev/null +++ b/tests/goldens/python_oracle/sql_test_assembly_an_unread_helper_with_an_invalid_reference_call.json @@ -0,0 +1,10 @@ +[ +[ +"sql_test_assembly", +{ +"diagnostics": "d66d63d2d739d2ad7c978860", +"raised": "74234e98afe7498fb5daf1f3", +"sql_tests": "04c58ad3582f31de5ebe5178" +} +] +] diff --git a/tests/goldens/python_oracle/sql_test_assembly_decimal_case_parameters_the_default_context_rounds_and_flushes.json b/tests/goldens/python_oracle/sql_test_assembly_decimal_case_parameters_the_default_context_rounds_and_flushes.json new file mode 100644 index 0000000000..8918f01755 --- /dev/null +++ b/tests/goldens/python_oracle/sql_test_assembly_decimal_case_parameters_the_default_context_rounds_and_flushes.json @@ -0,0 +1,10 @@ +[ +[ +"sql_test_assembly", +{ +"diagnostics": "134b5a980760bc0b6c888571", +"raised": "74234e98afe7498fb5daf1f3", +"sql_tests": "c9fdab56e644c9475570663d" +} +] +] diff --git a/tests/goldens/python_oracle/sql_test_assembly_model_direct_parameterized_and_mock_reads_helper_tests.json b/tests/goldens/python_oracle/sql_test_assembly_model_direct_parameterized_and_mock_reads_helper_tests.json new file mode 100644 index 0000000000..26f41f75ed --- /dev/null +++ b/tests/goldens/python_oracle/sql_test_assembly_model_direct_parameterized_and_mock_reads_helper_tests.json @@ -0,0 +1,34 @@ +[ +[ +"sql_test_assembly", +{ +"diagnostics": "4b16299f17e60e58f2790f5d", +"raised": "74234e98afe7498fb5daf1f3", +"sql_tests": "571161f404b1e68fb08c2be8" +} +], +[ +"sql_test_assembly", +{ +"diagnostics": "2f09ddab1196ed38909b55d2", +"raised": "74234e98afe7498fb5daf1f3", +"sql_tests": "b1fde08fd97d16270d71db00" +} +], +[ +"sql_test_assembly", +{ +"diagnostics": "775db3dd642a88a84b585e70", +"raised": "74234e98afe7498fb5daf1f3", +"sql_tests": "eb8781590978f943d4cda3a2" +} +], +[ +"sql_test_assembly", +{ +"diagnostics": "1a90c1b182791e84c6f3df11", +"raised": "74234e98afe7498fb5daf1f3", +"sql_tests": "9a64536c2908bed9e46d362e" +} +] +] diff --git a/tests/goldens/python_oracle/sql_test_assembly_non_ascii_test_contents_case_folded_reads_and_located_diagnostics.json b/tests/goldens/python_oracle/sql_test_assembly_non_ascii_test_contents_case_folded_reads_and_located_diagnostics.json new file mode 100644 index 0000000000..cf49c48317 --- /dev/null +++ b/tests/goldens/python_oracle/sql_test_assembly_non_ascii_test_contents_case_folded_reads_and_located_diagnostics.json @@ -0,0 +1,10 @@ +[ +[ +"sql_test_assembly", +{ +"diagnostics": "841354a5025b7303e999ad10", +"raised": "74234e98afe7498fb5daf1f3", +"sql_tests": "ba1a28153c7e0394be6b4d5e" +} +] +] diff --git a/tests/goldens/python_oracle/types_generated_seeded_scalar_parameterized_nested_padded_and_invalid_types.json b/tests/goldens/python_oracle/types_generated_seeded_scalar_parameterized_nested_padded_and_invalid_types.json new file mode 100644 index 0000000000..a7ccced078 --- /dev/null +++ b/tests/goldens/python_oracle/types_generated_seeded_scalar_parameterized_nested_padded_and_invalid_types.json @@ -0,0 +1,25502 @@ +[ +[ +"type", +{ +"DuckDB": "7e163d1c3f6840b5164def94", +"None": "7e163d1c3f6840b5164def94", +"bigquery": "7e163d1c3f6840b5164def94", +"databricks": "7e163d1c3f6840b5164def94", +"duckdb": "7e163d1c3f6840b5164def94", +"generic": "7e163d1c3f6840b5164def94", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "7e163d1c3f6840b5164def94", +"postgres": "7e163d1c3f6840b5164def94", +"postgresql": "7e163d1c3f6840b5164def94", +"snowflake": "7e163d1c3f6840b5164def94", +"tsql": "7e163d1c3f6840b5164def94" +} +], +[ +"type", +{ +"DuckDB": "1eb7fb4e8cf75773c5573562", +"None": "1eb7fb4e8cf75773c5573562", +"bigquery": "c9b810639795a7bfab91b98d", +"databricks": "1eb7fb4e8cf75773c5573562", +"duckdb": "1eb7fb4e8cf75773c5573562", +"generic": "1eb7fb4e8cf75773c5573562", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "1eb7fb4e8cf75773c5573562", +"postgres": "1eb7fb4e8cf75773c5573562", +"postgresql": "1eb7fb4e8cf75773c5573562", +"snowflake": "97a20344d811fb77c7690863", +"tsql": "1eb7fb4e8cf75773c5573562" +} +], +[ +"type", +{ +"DuckDB": "19a1a80ffc06169f32694de8", +"None": "19a1a80ffc06169f32694de8", +"bigquery": "19a1a80ffc06169f32694de8", +"databricks": "19a1a80ffc06169f32694de8", +"duckdb": "19a1a80ffc06169f32694de8", +"generic": "19a1a80ffc06169f32694de8", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "19a1a80ffc06169f32694de8", +"postgres": "19a1a80ffc06169f32694de8", +"postgresql": "19a1a80ffc06169f32694de8", +"snowflake": "19a1a80ffc06169f32694de8", +"tsql": "19a1a80ffc06169f32694de8" +} +], +[ +"type", +{ +"DuckDB": "e6badc927d1adf4563b4f3a5", +"None": "e6badc927d1adf4563b4f3a5", +"bigquery": "e6badc927d1adf4563b4f3a5", +"databricks": "e6badc927d1adf4563b4f3a5", +"duckdb": "e6badc927d1adf4563b4f3a5", +"generic": "e6badc927d1adf4563b4f3a5", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "e6badc927d1adf4563b4f3a5", +"postgres": "e6badc927d1adf4563b4f3a5", +"postgresql": "e6badc927d1adf4563b4f3a5", +"snowflake": "e6badc927d1adf4563b4f3a5", +"tsql": "e6badc927d1adf4563b4f3a5" +} +], +[ +"type", +{ +"DuckDB": "8a3f094f18fb4047f0febf59", +"None": "bbb2563edda71d0b69ef0855", +"bigquery": "5c28019dce48a74708c90a76", +"databricks": "bbb2563edda71d0b69ef0855", +"duckdb": "8a3f094f18fb4047f0febf59", +"generic": "bbb2563edda71d0b69ef0855", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "51d717b08676179ee1ccefe4", +"postgres": "bbb2563edda71d0b69ef0855", +"postgresql": "bbb2563edda71d0b69ef0855", +"snowflake": "bbb2563edda71d0b69ef0855", +"tsql": "83fd3ed7282be0616dc3037e" +} +], +[ +"type", +{ +"DuckDB": "688179272da645629077e980", +"None": "688179272da645629077e980", +"bigquery": "688179272da645629077e980", +"databricks": "688179272da645629077e980", +"duckdb": "688179272da645629077e980", +"generic": "688179272da645629077e980", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "688179272da645629077e980", +"postgres": "688179272da645629077e980", +"postgresql": "688179272da645629077e980", +"snowflake": "b210f8eb26c37b422f786c6b", +"tsql": "688179272da645629077e980" +} +], +[ +"type", +{ +"DuckDB": "0703bf71a54942bdaa28406e", +"None": "0703bf71a54942bdaa28406e", +"bigquery": "a428302e4848ffe877284c84", +"databricks": "0703bf71a54942bdaa28406e", +"duckdb": "0703bf71a54942bdaa28406e", +"generic": "0703bf71a54942bdaa28406e", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "0703bf71a54942bdaa28406e", +"postgres": "0703bf71a54942bdaa28406e", +"postgresql": "0703bf71a54942bdaa28406e", +"snowflake": "652ff8b21f638eac8fdc46c5", +"tsql": "441f377c46ddc162ec0a5976" +} +], +[ +"type", +{ +"DuckDB": "5c8b98f516cedefc237fa721", +"None": "5c8b98f516cedefc237fa721", +"bigquery": "5c8b98f516cedefc237fa721", +"databricks": "5c8b98f516cedefc237fa721", +"duckdb": "5c8b98f516cedefc237fa721", +"generic": "5c8b98f516cedefc237fa721", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "5c8b98f516cedefc237fa721", +"postgres": "5c8b98f516cedefc237fa721", +"postgresql": "5c8b98f516cedefc237fa721", +"snowflake": "5c8b98f516cedefc237fa721", +"tsql": "5c8b98f516cedefc237fa721" +} +], +[ +"type", +{ +"DuckDB": "d00038134428e2ce04bc8e09", +"None": "ab7940999dc6f4c634249230", +"bigquery": "ab7940999dc6f4c634249230", +"databricks": "ab7940999dc6f4c634249230", +"duckdb": "d00038134428e2ce04bc8e09", +"generic": "ab7940999dc6f4c634249230", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "ab7940999dc6f4c634249230", +"postgres": "ab7940999dc6f4c634249230", +"postgresql": "ab7940999dc6f4c634249230", +"snowflake": "d00038134428e2ce04bc8e09", +"tsql": "ab7940999dc6f4c634249230" +} +], +[ +"type", +{ +"DuckDB": "ee1b4ffc65518c536e3632ee", +"None": "ee1b4ffc65518c536e3632ee", +"bigquery": "a428302e4848ffe877284c84", +"databricks": "ee1b4ffc65518c536e3632ee", +"duckdb": "ee1b4ffc65518c536e3632ee", +"generic": "ee1b4ffc65518c536e3632ee", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "ee1b4ffc65518c536e3632ee", +"postgres": "ee1b4ffc65518c536e3632ee", +"postgresql": "ee1b4ffc65518c536e3632ee", +"snowflake": "652ff8b21f638eac8fdc46c5", +"tsql": "ee1b4ffc65518c536e3632ee" +} +], +[ +"type", +{ +"DuckDB": "ebc821a95b9286e22c2b26d0", +"None": "ebc821a95b9286e22c2b26d0", +"bigquery": "19a1a80ffc06169f32694de8", +"databricks": "ebc821a95b9286e22c2b26d0", +"duckdb": "ebc821a95b9286e22c2b26d0", +"generic": "ebc821a95b9286e22c2b26d0", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "ebc821a95b9286e22c2b26d0", +"postgres": "ebc821a95b9286e22c2b26d0", +"postgresql": "ebc821a95b9286e22c2b26d0", +"snowflake": "ebc821a95b9286e22c2b26d0", +"tsql": "ebc821a95b9286e22c2b26d0" +} +], +[ +"type", +{ +"DuckDB": "0f799a95a4f5ef502897f02c", +"None": "0f799a95a4f5ef502897f02c", +"bigquery": "b1b23029bedaa16e2a6f8516", +"databricks": "0f799a95a4f5ef502897f02c", +"duckdb": "0f799a95a4f5ef502897f02c", +"generic": "0f799a95a4f5ef502897f02c", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "0f799a95a4f5ef502897f02c", +"postgres": "0f799a95a4f5ef502897f02c", +"postgresql": "0f799a95a4f5ef502897f02c", +"snowflake": "0f799a95a4f5ef502897f02c", +"tsql": "0f799a95a4f5ef502897f02c" +} +], +[ +"type", +{ +"DuckDB": "2bfa352725f9d8a91250f75e", +"None": "2bfa352725f9d8a91250f75e", +"bigquery": "2bfa352725f9d8a91250f75e", +"databricks": "2bfa352725f9d8a91250f75e", +"duckdb": "2bfa352725f9d8a91250f75e", +"generic": "2bfa352725f9d8a91250f75e", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "2bfa352725f9d8a91250f75e", +"postgres": "2bfa352725f9d8a91250f75e", +"postgresql": "2bfa352725f9d8a91250f75e", +"snowflake": "2bfa352725f9d8a91250f75e", +"tsql": "2bfa352725f9d8a91250f75e" +} +], +[ +"type", +{ +"DuckDB": "19bdd92ea0cc5fb028657510", +"None": "19bdd92ea0cc5fb028657510", +"bigquery": "1e75e5227bea0ae294ac7af1", +"databricks": "1e75e5227bea0ae294ac7af1", +"duckdb": "19bdd92ea0cc5fb028657510", +"generic": "19bdd92ea0cc5fb028657510", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "19bdd92ea0cc5fb028657510", +"postgres": "19bdd92ea0cc5fb028657510", +"postgresql": "19bdd92ea0cc5fb028657510", +"snowflake": "8ff614b7306c0edbe36ce00b", +"tsql": "901e8c830028411846541f65" +} +], +[ +"type", +{ +"DuckDB": "e1c36a5cdd2427ff2b089ac9", +"None": "e1c36a5cdd2427ff2b089ac9", +"bigquery": "e1c36a5cdd2427ff2b089ac9", +"databricks": "e1c36a5cdd2427ff2b089ac9", +"duckdb": "e1c36a5cdd2427ff2b089ac9", +"generic": "e1c36a5cdd2427ff2b089ac9", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "e1c36a5cdd2427ff2b089ac9", +"postgres": "e1c36a5cdd2427ff2b089ac9", +"postgresql": "e1c36a5cdd2427ff2b089ac9", +"snowflake": "18db5afe2c1e80d1ee652b54", +"tsql": "e1c36a5cdd2427ff2b089ac9" +} +], +[ +"type", +{ +"DuckDB": "73151c1398b30e5c5d18f4ce", +"None": "73151c1398b30e5c5d18f4ce", +"bigquery": "73151c1398b30e5c5d18f4ce", +"databricks": "73151c1398b30e5c5d18f4ce", +"duckdb": "73151c1398b30e5c5d18f4ce", +"generic": "73151c1398b30e5c5d18f4ce", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "73151c1398b30e5c5d18f4ce", +"postgres": "73151c1398b30e5c5d18f4ce", +"postgresql": "73151c1398b30e5c5d18f4ce", +"snowflake": "73151c1398b30e5c5d18f4ce", +"tsql": "73151c1398b30e5c5d18f4ce" +} +], +[ +"type", +{ +"DuckDB": "3147a9e06daa6de4a4df5abc", +"None": "3147a9e06daa6de4a4df5abc", +"bigquery": "f276e907770196606577c932", +"databricks": "3147a9e06daa6de4a4df5abc", +"duckdb": "3147a9e06daa6de4a4df5abc", +"generic": "3147a9e06daa6de4a4df5abc", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "3147a9e06daa6de4a4df5abc", +"postgres": "3147a9e06daa6de4a4df5abc", +"postgresql": "3147a9e06daa6de4a4df5abc", +"snowflake": "67b5874a2c569226c490211f", +"tsql": "3147a9e06daa6de4a4df5abc" +} +], +[ +"type", +{ +"DuckDB": "0703bf71a54942bdaa28406e", +"None": "0703bf71a54942bdaa28406e", +"bigquery": "a428302e4848ffe877284c84", +"databricks": "0703bf71a54942bdaa28406e", +"duckdb": "0703bf71a54942bdaa28406e", +"generic": "0703bf71a54942bdaa28406e", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "0703bf71a54942bdaa28406e", +"postgres": "0703bf71a54942bdaa28406e", +"postgresql": "0703bf71a54942bdaa28406e", +"snowflake": "652ff8b21f638eac8fdc46c5", +"tsql": "441f377c46ddc162ec0a5976" +} +], +[ +"type", +{ +"DuckDB": "78b2cf275c640af54feeca31", +"None": "78b2cf275c640af54feeca31", +"bigquery": "1e75e5227bea0ae294ac7af1", +"databricks": "78b2cf275c640af54feeca31", +"duckdb": "78b2cf275c640af54feeca31", +"generic": "78b2cf275c640af54feeca31", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "78b2cf275c640af54feeca31", +"postgres": "78b2cf275c640af54feeca31", +"postgresql": "78b2cf275c640af54feeca31", +"snowflake": "8ff614b7306c0edbe36ce00b", +"tsql": "78b2cf275c640af54feeca31" +} +], +[ +"type", +{ +"DuckDB": "f15c56475abfc73488abe63b", +"None": "f15c56475abfc73488abe63b", +"bigquery": "a428302e4848ffe877284c84", +"databricks": "f15c56475abfc73488abe63b", +"duckdb": "f15c56475abfc73488abe63b", +"generic": "f15c56475abfc73488abe63b", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "f15c56475abfc73488abe63b", +"postgres": "f15c56475abfc73488abe63b", +"postgresql": "f15c56475abfc73488abe63b", +"snowflake": "652ff8b21f638eac8fdc46c5", +"tsql": "f15c56475abfc73488abe63b" +} +], +[ +"type", +{ +"DuckDB": "717cf79ef777823eb3576deb", +"None": "717cf79ef777823eb3576deb", +"bigquery": "717cf79ef777823eb3576deb", +"databricks": "717cf79ef777823eb3576deb", +"duckdb": "717cf79ef777823eb3576deb", +"generic": "717cf79ef777823eb3576deb", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "717cf79ef777823eb3576deb", +"postgres": "717cf79ef777823eb3576deb", +"postgresql": "717cf79ef777823eb3576deb", +"snowflake": "717cf79ef777823eb3576deb", +"tsql": "717cf79ef777823eb3576deb" +} +], +[ +"type", +{ +"DuckDB": "a6c6f4aa4257d422cbf3f875", +"None": "a6c6f4aa4257d422cbf3f875", +"bigquery": "ea191a784359be345cd9ded6", +"databricks": "ea191a784359be345cd9ded6", +"duckdb": "a6c6f4aa4257d422cbf3f875", +"generic": "a6c6f4aa4257d422cbf3f875", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "ea191a784359be345cd9ded6", +"postgres": "a6c6f4aa4257d422cbf3f875", +"postgresql": "a6c6f4aa4257d422cbf3f875", +"snowflake": "a6c6f4aa4257d422cbf3f875", +"tsql": "a6c6f4aa4257d422cbf3f875" +} +], +[ +"type", +{ +"DuckDB": "19bdd92ea0cc5fb028657510", +"None": "78b2cf275c640af54feeca31", +"bigquery": "78b2cf275c640af54feeca31", +"databricks": "1e75e5227bea0ae294ac7af1", +"duckdb": "19bdd92ea0cc5fb028657510", +"generic": "78b2cf275c640af54feeca31", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "19bdd92ea0cc5fb028657510", +"postgres": "78b2cf275c640af54feeca31", +"postgresql": "78b2cf275c640af54feeca31", +"snowflake": "8ff614b7306c0edbe36ce00b", +"tsql": "78b2cf275c640af54feeca31" +} +], +[ +"type", +{ +"DuckDB": "0f799a95a4f5ef502897f02c", +"None": "0f799a95a4f5ef502897f02c", +"bigquery": "b1b23029bedaa16e2a6f8516", +"databricks": "0f799a95a4f5ef502897f02c", +"duckdb": "0f799a95a4f5ef502897f02c", +"generic": "0f799a95a4f5ef502897f02c", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "0f799a95a4f5ef502897f02c", +"postgres": "0f799a95a4f5ef502897f02c", +"postgresql": "0f799a95a4f5ef502897f02c", +"snowflake": "0f799a95a4f5ef502897f02c", +"tsql": "0f799a95a4f5ef502897f02c" +} +], +[ +"type", +{ +"DuckDB": "e9b32e3b5a5505b32f33e169", +"None": "e9b32e3b5a5505b32f33e169", +"bigquery": "e9b32e3b5a5505b32f33e169", +"databricks": "e9b32e3b5a5505b32f33e169", +"duckdb": "e9b32e3b5a5505b32f33e169", +"generic": "e9b32e3b5a5505b32f33e169", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "e9b32e3b5a5505b32f33e169", +"postgres": "e9b32e3b5a5505b32f33e169", +"postgresql": "e9b32e3b5a5505b32f33e169", +"snowflake": "e9b32e3b5a5505b32f33e169", +"tsql": "e9b32e3b5a5505b32f33e169" +} +], +[ +"type", +{ +"DuckDB": "3f71ab5f3c1c040da96f2cec", +"None": "3f71ab5f3c1c040da96f2cec", +"bigquery": "3f71ab5f3c1c040da96f2cec", +"databricks": "3f71ab5f3c1c040da96f2cec", +"duckdb": "3f71ab5f3c1c040da96f2cec", +"generic": "3f71ab5f3c1c040da96f2cec", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "3f71ab5f3c1c040da96f2cec", +"postgres": "3f71ab5f3c1c040da96f2cec", +"postgresql": "3f71ab5f3c1c040da96f2cec", +"snowflake": "3f71ab5f3c1c040da96f2cec", +"tsql": "3f71ab5f3c1c040da96f2cec" +} +], +[ +"type", +{ +"DuckDB": "a766fea06fc070b352976b0a", +"None": "a766fea06fc070b352976b0a", +"bigquery": "e4f0244beaa01667e80482b6", +"databricks": "e4f0244beaa01667e80482b6", +"duckdb": "a766fea06fc070b352976b0a", +"generic": "a766fea06fc070b352976b0a", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "e4f0244beaa01667e80482b6", +"postgres": "a766fea06fc070b352976b0a", +"postgresql": "a766fea06fc070b352976b0a", +"snowflake": "a766fea06fc070b352976b0a", +"tsql": "a766fea06fc070b352976b0a" +} +], +[ +"type", +{ +"DuckDB": "4114b18e7e26d16613331fa7", +"None": "4114b18e7e26d16613331fa7", +"bigquery": "4114b18e7e26d16613331fa7", +"databricks": "4fb572024031cb7631777be1", +"duckdb": "4114b18e7e26d16613331fa7", +"generic": "4114b18e7e26d16613331fa7", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "4114b18e7e26d16613331fa7", +"postgres": "4114b18e7e26d16613331fa7", +"postgresql": "4114b18e7e26d16613331fa7", +"snowflake": "4114b18e7e26d16613331fa7", +"tsql": "4114b18e7e26d16613331fa7" +} +], +[ +"type", +{ +"DuckDB": "98a80237e4e0a12f35bbf17e", +"None": "98a80237e4e0a12f35bbf17e", +"bigquery": "98a80237e4e0a12f35bbf17e", +"databricks": "98a80237e4e0a12f35bbf17e", +"duckdb": "98a80237e4e0a12f35bbf17e", +"generic": "98a80237e4e0a12f35bbf17e", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "98a80237e4e0a12f35bbf17e", +"postgres": "98a80237e4e0a12f35bbf17e", +"postgresql": "98a80237e4e0a12f35bbf17e", +"snowflake": "98a80237e4e0a12f35bbf17e", +"tsql": "98a80237e4e0a12f35bbf17e" +} +], +[ +"type", +{ +"DuckDB": "d61c83ef8bfdf043fa672cb5", +"None": "d61c83ef8bfdf043fa672cb5", +"bigquery": "c9b810639795a7bfab91b98d", +"databricks": "d61c83ef8bfdf043fa672cb5", +"duckdb": "d61c83ef8bfdf043fa672cb5", +"generic": "d61c83ef8bfdf043fa672cb5", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "d61c83ef8bfdf043fa672cb5", +"postgres": "d61c83ef8bfdf043fa672cb5", +"postgresql": "d61c83ef8bfdf043fa672cb5", +"snowflake": "97a20344d811fb77c7690863", +"tsql": "d61c83ef8bfdf043fa672cb5" +} +], +[ +"type", +{ +"DuckDB": "f7fca17b74cc50ae3de8c826", +"None": "f7fca17b74cc50ae3de8c826", +"bigquery": "f7fca17b74cc50ae3de8c826", +"databricks": "f7fca17b74cc50ae3de8c826", +"duckdb": "f7fca17b74cc50ae3de8c826", +"generic": "f7fca17b74cc50ae3de8c826", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "f7fca17b74cc50ae3de8c826", +"postgres": "f7fca17b74cc50ae3de8c826", +"postgresql": "f7fca17b74cc50ae3de8c826", +"snowflake": "55155766823b6a3a5e882fc2", +"tsql": "f7fca17b74cc50ae3de8c826" +} +], +[ +"type", +{ +"DuckDB": "9a79cb58680bebe49009a72d", +"None": "9a79cb58680bebe49009a72d", +"bigquery": "9a79cb58680bebe49009a72d", +"databricks": "9a79cb58680bebe49009a72d", +"duckdb": "9a79cb58680bebe49009a72d", +"generic": "9a79cb58680bebe49009a72d", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "9a79cb58680bebe49009a72d", +"postgres": "9a79cb58680bebe49009a72d", +"postgresql": "9a79cb58680bebe49009a72d", +"snowflake": "9a79cb58680bebe49009a72d", +"tsql": "9a79cb58680bebe49009a72d" +} +], +[ +"type", +{ +"DuckDB": "9bafb08d41fd1c208b5deca4", +"None": "9bafb08d41fd1c208b5deca4", +"bigquery": "9bafb08d41fd1c208b5deca4", +"databricks": "9bafb08d41fd1c208b5deca4", +"duckdb": "9bafb08d41fd1c208b5deca4", +"generic": "9bafb08d41fd1c208b5deca4", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "9bafb08d41fd1c208b5deca4", +"postgres": "9bafb08d41fd1c208b5deca4", +"postgresql": "9bafb08d41fd1c208b5deca4", +"snowflake": "9bafb08d41fd1c208b5deca4", +"tsql": "9bafb08d41fd1c208b5deca4" +} +], +[ +"type", +{ +"DuckDB": "de89632e277dbc8c97115419", +"None": "de89632e277dbc8c97115419", +"bigquery": "de89632e277dbc8c97115419", +"databricks": "de89632e277dbc8c97115419", +"duckdb": "de89632e277dbc8c97115419", +"generic": "de89632e277dbc8c97115419", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "de89632e277dbc8c97115419", +"postgres": "de89632e277dbc8c97115419", +"postgresql": "de89632e277dbc8c97115419", +"snowflake": "4b356542044f1267fcfc487a", +"tsql": "de89632e277dbc8c97115419" +} +], +[ +"type", +{ +"DuckDB": "2e60720c3255d112fcd0938a", +"None": "2e60720c3255d112fcd0938a", +"bigquery": "2e60720c3255d112fcd0938a", +"databricks": "2e60720c3255d112fcd0938a", +"duckdb": "2e60720c3255d112fcd0938a", +"generic": "2e60720c3255d112fcd0938a", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "2e60720c3255d112fcd0938a", +"postgres": "2e60720c3255d112fcd0938a", +"postgresql": "2e60720c3255d112fcd0938a", +"snowflake": "2e60720c3255d112fcd0938a", +"tsql": "2e60720c3255d112fcd0938a" +} +], +[ +"type", +{ +"DuckDB": "669084d1ea704ae5b8ee05c2", +"None": "669084d1ea704ae5b8ee05c2", +"bigquery": "669084d1ea704ae5b8ee05c2", +"databricks": "669084d1ea704ae5b8ee05c2", +"duckdb": "669084d1ea704ae5b8ee05c2", +"generic": "669084d1ea704ae5b8ee05c2", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "669084d1ea704ae5b8ee05c2", +"postgres": "669084d1ea704ae5b8ee05c2", +"postgresql": "669084d1ea704ae5b8ee05c2", +"snowflake": "669084d1ea704ae5b8ee05c2", +"tsql": "669084d1ea704ae5b8ee05c2" +} +], +[ +"type", +{ +"DuckDB": "c9cc0c1ce817773e19f141b5", +"None": "d7249dcf128bf2bb675aa0d9", +"bigquery": "d7249dcf128bf2bb675aa0d9", +"databricks": "f1640dc6a7437eae3cc39eec", +"duckdb": "c9cc0c1ce817773e19f141b5", +"generic": "d7249dcf128bf2bb675aa0d9", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "d7249dcf128bf2bb675aa0d9", +"postgres": "d7249dcf128bf2bb675aa0d9", +"postgresql": "d7249dcf128bf2bb675aa0d9", +"snowflake": "89091c4ddfa26794a7c15ab6", +"tsql": "d7249dcf128bf2bb675aa0d9" +} +], +[ +"type", +{ +"DuckDB": "e060b5a5a8e9774b580d58d3", +"None": "e060b5a5a8e9774b580d58d3", +"bigquery": "319a9fbb02ed503eb114164b", +"databricks": "319a9fbb02ed503eb114164b", +"duckdb": "e060b5a5a8e9774b580d58d3", +"generic": "e060b5a5a8e9774b580d58d3", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "319a9fbb02ed503eb114164b", +"postgres": "e060b5a5a8e9774b580d58d3", +"postgresql": "e060b5a5a8e9774b580d58d3", +"snowflake": "e060b5a5a8e9774b580d58d3", +"tsql": "e060b5a5a8e9774b580d58d3" +} +], +[ +"type", +{ +"DuckDB": "3dbbe73ee4310c73030e8110", +"None": "3dbbe73ee4310c73030e8110", +"bigquery": "3dbbe73ee4310c73030e8110", +"databricks": "3dbbe73ee4310c73030e8110", +"duckdb": "3dbbe73ee4310c73030e8110", +"generic": "3dbbe73ee4310c73030e8110", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "3dbbe73ee4310c73030e8110", +"postgres": "3dbbe73ee4310c73030e8110", +"postgresql": "3dbbe73ee4310c73030e8110", +"snowflake": "f43dac38f34a1c0618a3f812", +"tsql": "3dbbe73ee4310c73030e8110" +} +], +[ +"type", +{ +"DuckDB": "8111d803c9182d0189c728e9", +"None": "8111d803c9182d0189c728e9", +"bigquery": "8111d803c9182d0189c728e9", +"databricks": "8111d803c9182d0189c728e9", +"duckdb": "8111d803c9182d0189c728e9", +"generic": "8111d803c9182d0189c728e9", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "8111d803c9182d0189c728e9", +"postgres": "8111d803c9182d0189c728e9", +"postgresql": "8111d803c9182d0189c728e9", +"snowflake": "8111d803c9182d0189c728e9", +"tsql": "8111d803c9182d0189c728e9" +} +], +[ +"type", +{ +"DuckDB": "f7fca17b74cc50ae3de8c826", +"None": "f7fca17b74cc50ae3de8c826", +"bigquery": "f7fca17b74cc50ae3de8c826", +"databricks": "f7fca17b74cc50ae3de8c826", +"duckdb": "f7fca17b74cc50ae3de8c826", +"generic": "f7fca17b74cc50ae3de8c826", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "f7fca17b74cc50ae3de8c826", +"postgres": "f7fca17b74cc50ae3de8c826", +"postgresql": "f7fca17b74cc50ae3de8c826", +"snowflake": "55155766823b6a3a5e882fc2", +"tsql": "f7fca17b74cc50ae3de8c826" +} +], +[ +"type", +{ +"DuckDB": "d79c3ac70093cb4cb531e71c", +"None": "d79c3ac70093cb4cb531e71c", +"bigquery": "b0477b36767a62145aa9158c", +"databricks": "d79c3ac70093cb4cb531e71c", +"duckdb": "d79c3ac70093cb4cb531e71c", +"generic": "d79c3ac70093cb4cb531e71c", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "d79c3ac70093cb4cb531e71c", +"postgres": "d79c3ac70093cb4cb531e71c", +"postgresql": "d79c3ac70093cb4cb531e71c", +"snowflake": "652ff8b21f638eac8fdc46c5", +"tsql": "d79c3ac70093cb4cb531e71c" +} +], +[ +"type", +{ +"DuckDB": "4b356542044f1267fcfc487a", +"None": "4b356542044f1267fcfc487a", +"bigquery": "4b356542044f1267fcfc487a", +"databricks": "4b356542044f1267fcfc487a", +"duckdb": "4b356542044f1267fcfc487a", +"generic": "4b356542044f1267fcfc487a", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "4b356542044f1267fcfc487a", +"postgres": "4b356542044f1267fcfc487a", +"postgresql": "4b356542044f1267fcfc487a", +"snowflake": "4b356542044f1267fcfc487a", +"tsql": "4b356542044f1267fcfc487a" +} +], +[ +"type", +{ +"DuckDB": "f0ec29663977eb66dca07a0e", +"None": "f0ec29663977eb66dca07a0e", +"bigquery": "b0477b36767a62145aa9158c", +"databricks": "f0ec29663977eb66dca07a0e", +"duckdb": "f0ec29663977eb66dca07a0e", +"generic": "f0ec29663977eb66dca07a0e", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "f0ec29663977eb66dca07a0e", +"postgres": "f0ec29663977eb66dca07a0e", +"postgresql": "f0ec29663977eb66dca07a0e", +"snowflake": "652ff8b21f638eac8fdc46c5", +"tsql": "f0ec29663977eb66dca07a0e" +} +], +[ +"type", +{ +"DuckDB": "08736485547ba339930697e9", +"None": "08736485547ba339930697e9", +"bigquery": "08736485547ba339930697e9", +"databricks": "08736485547ba339930697e9", +"duckdb": "08736485547ba339930697e9", +"generic": "08736485547ba339930697e9", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "08736485547ba339930697e9", +"postgres": "08736485547ba339930697e9", +"postgresql": "08736485547ba339930697e9", +"snowflake": "08736485547ba339930697e9", +"tsql": "08736485547ba339930697e9" +} +], +[ +"type", +{ +"DuckDB": "8a3f094f18fb4047f0febf59", +"None": "8a3f094f18fb4047f0febf59", +"bigquery": "5c28019dce48a74708c90a76", +"databricks": "8a3f094f18fb4047f0febf59", +"duckdb": "8a3f094f18fb4047f0febf59", +"generic": "8a3f094f18fb4047f0febf59", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "5c28019dce48a74708c90a76", +"postgres": "8a3f094f18fb4047f0febf59", +"postgresql": "8a3f094f18fb4047f0febf59", +"snowflake": "850deea990b52b82b36a9848", +"tsql": "cc8534b198fe0c225bbffd8d" +} +], +[ +"type", +{ +"DuckDB": "64fc778308b798a730b1d5c9", +"None": "64fc778308b798a730b1d5c9", +"bigquery": "64fc778308b798a730b1d5c9", +"databricks": "64fc778308b798a730b1d5c9", +"duckdb": "64fc778308b798a730b1d5c9", +"generic": "64fc778308b798a730b1d5c9", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "64fc778308b798a730b1d5c9", +"postgres": "64fc778308b798a730b1d5c9", +"postgresql": "64fc778308b798a730b1d5c9", +"snowflake": "64fc778308b798a730b1d5c9", +"tsql": "64fc778308b798a730b1d5c9" +} +], +[ +"type", +{ +"DuckDB": "b46dfa976d5ba04f95bea32b", +"None": "b46dfa976d5ba04f95bea32b", +"bigquery": "68d2179839f17f0eb289d1aa", +"databricks": "b46dfa976d5ba04f95bea32b", +"duckdb": "b46dfa976d5ba04f95bea32b", +"generic": "b46dfa976d5ba04f95bea32b", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "b46dfa976d5ba04f95bea32b", +"postgres": "34dcdfe3e3afe6140e1353e0", +"postgresql": "34dcdfe3e3afe6140e1353e0", +"snowflake": "b46dfa976d5ba04f95bea32b", +"tsql": "1d8b945fd793ecdcacb90c21" +} +], +[ +"type", +{ +"DuckDB": "20c9f38cf0da7cc6079a3a47", +"None": "20c9f38cf0da7cc6079a3a47", +"bigquery": "20c9f38cf0da7cc6079a3a47", +"databricks": "20c9f38cf0da7cc6079a3a47", +"duckdb": "20c9f38cf0da7cc6079a3a47", +"generic": "20c9f38cf0da7cc6079a3a47", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "20c9f38cf0da7cc6079a3a47", +"postgres": "20c9f38cf0da7cc6079a3a47", +"postgresql": "20c9f38cf0da7cc6079a3a47", +"snowflake": "20c9f38cf0da7cc6079a3a47", +"tsql": "20c9f38cf0da7cc6079a3a47" +} +], +[ +"type", +{ +"DuckDB": "1eb7fb4e8cf75773c5573562", +"None": "1eb7fb4e8cf75773c5573562", +"bigquery": "c9b810639795a7bfab91b98d", +"databricks": "1eb7fb4e8cf75773c5573562", +"duckdb": "1eb7fb4e8cf75773c5573562", +"generic": "1eb7fb4e8cf75773c5573562", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "1eb7fb4e8cf75773c5573562", +"postgres": "1eb7fb4e8cf75773c5573562", +"postgresql": "1eb7fb4e8cf75773c5573562", +"snowflake": "97a20344d811fb77c7690863", +"tsql": "1eb7fb4e8cf75773c5573562" +} +], +[ +"type", +{ +"DuckDB": "c50a316d091c821866e4bfba", +"None": "c50a316d091c821866e4bfba", +"bigquery": "c50a316d091c821866e4bfba", +"databricks": "c50a316d091c821866e4bfba", +"duckdb": "c50a316d091c821866e4bfba", +"generic": "c50a316d091c821866e4bfba", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "c50a316d091c821866e4bfba", +"postgres": "c50a316d091c821866e4bfba", +"postgresql": "c50a316d091c821866e4bfba", +"snowflake": "c50a316d091c821866e4bfba", +"tsql": "c50a316d091c821866e4bfba" +} +], +[ +"type", +{ +"DuckDB": "38b2ec94bf02be40007ce525", +"None": "38b2ec94bf02be40007ce525", +"bigquery": "38b2ec94bf02be40007ce525", +"databricks": "38b2ec94bf02be40007ce525", +"duckdb": "38b2ec94bf02be40007ce525", +"generic": "38b2ec94bf02be40007ce525", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "38b2ec94bf02be40007ce525", +"postgres": "38b2ec94bf02be40007ce525", +"postgresql": "38b2ec94bf02be40007ce525", +"snowflake": "38b2ec94bf02be40007ce525", +"tsql": "38b2ec94bf02be40007ce525" +} +], +[ +"type", +{ +"DuckDB": "19a1a80ffc06169f32694de8", +"None": "19a1a80ffc06169f32694de8", +"bigquery": "19a1a80ffc06169f32694de8", +"databricks": "19a1a80ffc06169f32694de8", +"duckdb": "19a1a80ffc06169f32694de8", +"generic": "19a1a80ffc06169f32694de8", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "19a1a80ffc06169f32694de8", +"postgres": "19a1a80ffc06169f32694de8", +"postgresql": "19a1a80ffc06169f32694de8", +"snowflake": "19a1a80ffc06169f32694de8", +"tsql": "19a1a80ffc06169f32694de8" +} +], +[ +"type", +{ +"DuckDB": "09a5861e271d932cd3a9a264", +"None": "6ef74921b43664a98de3f7e4", +"bigquery": "47e0816fecdd9e015d7aeb79", +"databricks": "6ef74921b43664a98de3f7e4", +"duckdb": "09a5861e271d932cd3a9a264", +"generic": "6ef74921b43664a98de3f7e4", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "6c03a3450ea4742ee7396e3c", +"postgres": "cc685e113aac64bd76fbc3cb", +"postgresql": "cc685e113aac64bd76fbc3cb", +"snowflake": "6fe4c4c52324360189048430", +"tsql": "d1dc9a140dbe2eb1874c6ad7" +} +], +[ +"type", +{ +"DuckDB": "35e216b6921bf843994f2eea", +"None": "46ec3e19e05a6cb29854ccac", +"bigquery": "46ec3e19e05a6cb29854ccac", +"databricks": "46ec3e19e05a6cb29854ccac", +"duckdb": "35e216b6921bf843994f2eea", +"generic": "46ec3e19e05a6cb29854ccac", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "46ec3e19e05a6cb29854ccac", +"postgres": "46ec3e19e05a6cb29854ccac", +"postgresql": "46ec3e19e05a6cb29854ccac", +"snowflake": "46ec3e19e05a6cb29854ccac", +"tsql": "46ec3e19e05a6cb29854ccac" +} +], +[ +"type", +{ +"DuckDB": "5abf4ec799a2ec32fb10da7e", +"None": "de89632e277dbc8c97115419", +"bigquery": "de89632e277dbc8c97115419", +"databricks": "de89632e277dbc8c97115419", +"duckdb": "5abf4ec799a2ec32fb10da7e", +"generic": "de89632e277dbc8c97115419", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "de89632e277dbc8c97115419", +"postgres": "de89632e277dbc8c97115419", +"postgresql": "de89632e277dbc8c97115419", +"snowflake": "4b356542044f1267fcfc487a", +"tsql": "de89632e277dbc8c97115419" +} +], +[ +"type", +{ +"DuckDB": "1950e32420d1d40d41ffae64", +"None": "1950e32420d1d40d41ffae64", +"bigquery": "1950e32420d1d40d41ffae64", +"databricks": "1950e32420d1d40d41ffae64", +"duckdb": "1950e32420d1d40d41ffae64", +"generic": "1950e32420d1d40d41ffae64", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "1950e32420d1d40d41ffae64", +"postgres": "1950e32420d1d40d41ffae64", +"postgresql": "1950e32420d1d40d41ffae64", +"snowflake": "1950e32420d1d40d41ffae64", +"tsql": "1950e32420d1d40d41ffae64" +} +], +[ +"type", +{ +"DuckDB": "3f71ab5f3c1c040da96f2cec", +"None": "3f71ab5f3c1c040da96f2cec", +"bigquery": "3f71ab5f3c1c040da96f2cec", +"databricks": "3f71ab5f3c1c040da96f2cec", +"duckdb": "3f71ab5f3c1c040da96f2cec", +"generic": "3f71ab5f3c1c040da96f2cec", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "3f71ab5f3c1c040da96f2cec", +"postgres": "3f71ab5f3c1c040da96f2cec", +"postgresql": "3f71ab5f3c1c040da96f2cec", +"snowflake": "3f71ab5f3c1c040da96f2cec", +"tsql": "3f71ab5f3c1c040da96f2cec" +} +], +[ +"type", +{ +"DuckDB": "9e4a50a8aab648a9737f7d0c", +"None": "9e4a50a8aab648a9737f7d0c", +"bigquery": "d9a4e245156e760303573500", +"databricks": "9e4a50a8aab648a9737f7d0c", +"duckdb": "9e4a50a8aab648a9737f7d0c", +"generic": "9e4a50a8aab648a9737f7d0c", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "9e4a50a8aab648a9737f7d0c", +"postgres": "36d29258901a4d8c296baa68", +"postgresql": "36d29258901a4d8c296baa68", +"snowflake": "9e4a50a8aab648a9737f7d0c", +"tsql": "355e032cc5c0f24695836b3d" +} +], +[ +"type", +{ +"DuckDB": "461923a0d34defd0c726d6e5", +"None": "461923a0d34defd0c726d6e5", +"bigquery": "b5c4d5044b2a6e70633f0d0a", +"databricks": "461923a0d34defd0c726d6e5", +"duckdb": "461923a0d34defd0c726d6e5", +"generic": "461923a0d34defd0c726d6e5", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "461923a0d34defd0c726d6e5", +"postgres": "461923a0d34defd0c726d6e5", +"postgresql": "461923a0d34defd0c726d6e5", +"snowflake": "461923a0d34defd0c726d6e5", +"tsql": "461923a0d34defd0c726d6e5" +} +], +[ +"type", +{ +"DuckDB": "2bfa352725f9d8a91250f75e", +"None": "2bfa352725f9d8a91250f75e", +"bigquery": "2bfa352725f9d8a91250f75e", +"databricks": "2bfa352725f9d8a91250f75e", +"duckdb": "2bfa352725f9d8a91250f75e", +"generic": "2bfa352725f9d8a91250f75e", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "2bfa352725f9d8a91250f75e", +"postgres": "2bfa352725f9d8a91250f75e", +"postgresql": "2bfa352725f9d8a91250f75e", +"snowflake": "2bfa352725f9d8a91250f75e", +"tsql": "2bfa352725f9d8a91250f75e" +} +], +[ +"type", +{ +"DuckDB": "8441d00030df06ad6a5534d3", +"None": "8441d00030df06ad6a5534d3", +"bigquery": "c9b810639795a7bfab91b98d", +"databricks": "8441d00030df06ad6a5534d3", +"duckdb": "8441d00030df06ad6a5534d3", +"generic": "8441d00030df06ad6a5534d3", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "8441d00030df06ad6a5534d3", +"postgres": "8441d00030df06ad6a5534d3", +"postgresql": "8441d00030df06ad6a5534d3", +"snowflake": "97a20344d811fb77c7690863", +"tsql": "8441d00030df06ad6a5534d3" +} +], +[ +"type", +{ +"DuckDB": "e46d4be44ab9e500e9190d26", +"None": "e46d4be44ab9e500e9190d26", +"bigquery": "e6ffdece2977be55da73b59a", +"databricks": "e46d4be44ab9e500e9190d26", +"duckdb": "e46d4be44ab9e500e9190d26", +"generic": "e46d4be44ab9e500e9190d26", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "e46d4be44ab9e500e9190d26", +"postgres": "e46d4be44ab9e500e9190d26", +"postgresql": "e46d4be44ab9e500e9190d26", +"snowflake": "e46d4be44ab9e500e9190d26", +"tsql": "e46d4be44ab9e500e9190d26" +} +], +[ +"type", +{ +"DuckDB": "a7120d1b1abcb844c87a968a", +"None": "a7120d1b1abcb844c87a968a", +"bigquery": "a7120d1b1abcb844c87a968a", +"databricks": "a7120d1b1abcb844c87a968a", +"duckdb": "a7120d1b1abcb844c87a968a", +"generic": "a7120d1b1abcb844c87a968a", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "a7120d1b1abcb844c87a968a", +"postgres": "a7120d1b1abcb844c87a968a", +"postgresql": "a7120d1b1abcb844c87a968a", +"snowflake": "a7120d1b1abcb844c87a968a", +"tsql": "a7120d1b1abcb844c87a968a" +} +], +[ +"type", +{ +"DuckDB": "cc2a8dbf7a9806988a7b5067", +"None": "cc2a8dbf7a9806988a7b5067", +"bigquery": "cc2a8dbf7a9806988a7b5067", +"databricks": "cc2a8dbf7a9806988a7b5067", +"duckdb": "cc2a8dbf7a9806988a7b5067", +"generic": "cc2a8dbf7a9806988a7b5067", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "cc2a8dbf7a9806988a7b5067", +"postgres": "cc2a8dbf7a9806988a7b5067", +"postgresql": "cc2a8dbf7a9806988a7b5067", +"snowflake": "cc2a8dbf7a9806988a7b5067", +"tsql": "cc2a8dbf7a9806988a7b5067" +} +], +[ +"type", +{ +"DuckDB": "5d4d5145235f17764810d03f", +"None": "5d4d5145235f17764810d03f", +"bigquery": "5d4d5145235f17764810d03f", +"databricks": "5d4d5145235f17764810d03f", +"duckdb": "5d4d5145235f17764810d03f", +"generic": "5d4d5145235f17764810d03f", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "5d4d5145235f17764810d03f", +"postgres": "5d4d5145235f17764810d03f", +"postgresql": "5d4d5145235f17764810d03f", +"snowflake": "5d4d5145235f17764810d03f", +"tsql": "5d4d5145235f17764810d03f" +} +], +[ +"type", +{ +"DuckDB": "2427f5522575cdc3d6a74e4c", +"None": "2427f5522575cdc3d6a74e4c", +"bigquery": "2427f5522575cdc3d6a74e4c", +"databricks": "2427f5522575cdc3d6a74e4c", +"duckdb": "2427f5522575cdc3d6a74e4c", +"generic": "2427f5522575cdc3d6a74e4c", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "2427f5522575cdc3d6a74e4c", +"postgres": "2427f5522575cdc3d6a74e4c", +"postgresql": "2427f5522575cdc3d6a74e4c", +"snowflake": "2427f5522575cdc3d6a74e4c", +"tsql": "2427f5522575cdc3d6a74e4c" +} +], +[ +"type", +{ +"DuckDB": "2bfa352725f9d8a91250f75e", +"None": "2bfa352725f9d8a91250f75e", +"bigquery": "2bfa352725f9d8a91250f75e", +"databricks": "2bfa352725f9d8a91250f75e", +"duckdb": "2bfa352725f9d8a91250f75e", +"generic": "2bfa352725f9d8a91250f75e", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "2bfa352725f9d8a91250f75e", +"postgres": "2bfa352725f9d8a91250f75e", +"postgresql": "2bfa352725f9d8a91250f75e", +"snowflake": "2bfa352725f9d8a91250f75e", +"tsql": "2bfa352725f9d8a91250f75e" +} +], +[ +"type", +{ +"DuckDB": "97d3bfe2b726a642c0011696", +"None": "5a48ec343f2513c62588cb55", +"bigquery": "5a48ec343f2513c62588cb55", +"databricks": "12b8a08a67c6c5ca887183e3", +"duckdb": "97d3bfe2b726a642c0011696", +"generic": "5a48ec343f2513c62588cb55", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "5a48ec343f2513c62588cb55", +"postgres": "5a48ec343f2513c62588cb55", +"postgresql": "5a48ec343f2513c62588cb55", +"snowflake": "582c76388cd6468a1e793692", +"tsql": "5a48ec343f2513c62588cb55" +} +], +[ +"type", +{ +"DuckDB": "8441d00030df06ad6a5534d3", +"None": "8441d00030df06ad6a5534d3", +"bigquery": "c9b810639795a7bfab91b98d", +"databricks": "8441d00030df06ad6a5534d3", +"duckdb": "8441d00030df06ad6a5534d3", +"generic": "8441d00030df06ad6a5534d3", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "8441d00030df06ad6a5534d3", +"postgres": "8441d00030df06ad6a5534d3", +"postgresql": "8441d00030df06ad6a5534d3", +"snowflake": "97a20344d811fb77c7690863", +"tsql": "8441d00030df06ad6a5534d3" +} +], +[ +"type", +{ +"DuckDB": "b5c4d5044b2a6e70633f0d0a", +"None": "b5c4d5044b2a6e70633f0d0a", +"bigquery": "b5c4d5044b2a6e70633f0d0a", +"databricks": "b5c4d5044b2a6e70633f0d0a", +"duckdb": "b5c4d5044b2a6e70633f0d0a", +"generic": "b5c4d5044b2a6e70633f0d0a", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "b5c4d5044b2a6e70633f0d0a", +"postgres": "b5c4d5044b2a6e70633f0d0a", +"postgresql": "b5c4d5044b2a6e70633f0d0a", +"snowflake": "4e24a80b20b9dee0cbbfac17", +"tsql": "b5c4d5044b2a6e70633f0d0a" +} +], +[ +"type", +{ +"DuckDB": "7a8df655ee308ea4f929b9fd", +"None": "7a8df655ee308ea4f929b9fd", +"bigquery": "ac984ee30077ed3bb3c7c9d5", +"databricks": "ac984ee30077ed3bb3c7c9d5", +"duckdb": "7a8df655ee308ea4f929b9fd", +"generic": "7a8df655ee308ea4f929b9fd", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "ac984ee30077ed3bb3c7c9d5", +"postgres": "7a8df655ee308ea4f929b9fd", +"postgresql": "7a8df655ee308ea4f929b9fd", +"snowflake": "7a8df655ee308ea4f929b9fd", +"tsql": "7a8df655ee308ea4f929b9fd" +} +], +[ +"type", +{ +"DuckDB": "804fec6876d0b43935790142", +"None": "804fec6876d0b43935790142", +"bigquery": "804fec6876d0b43935790142", +"databricks": "804fec6876d0b43935790142", +"duckdb": "804fec6876d0b43935790142", +"generic": "804fec6876d0b43935790142", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "804fec6876d0b43935790142", +"postgres": "804fec6876d0b43935790142", +"postgresql": "804fec6876d0b43935790142", +"snowflake": "804fec6876d0b43935790142", +"tsql": "804fec6876d0b43935790142" +} +], +[ +"type", +{ +"DuckDB": "8a4c61c12f9eaa564d1c19a1", +"None": "8a4c61c12f9eaa564d1c19a1", +"bigquery": "8a4c61c12f9eaa564d1c19a1", +"databricks": "8a4c61c12f9eaa564d1c19a1", +"duckdb": "8a4c61c12f9eaa564d1c19a1", +"generic": "8a4c61c12f9eaa564d1c19a1", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "8a4c61c12f9eaa564d1c19a1", +"postgres": "8a4c61c12f9eaa564d1c19a1", +"postgresql": "8a4c61c12f9eaa564d1c19a1", +"snowflake": "8a4c61c12f9eaa564d1c19a1", +"tsql": "8a4c61c12f9eaa564d1c19a1" +} +], +[ +"type", +{ +"DuckDB": "fcb2bd160300a30539bd5398", +"None": "fcb2bd160300a30539bd5398", +"bigquery": "fcb2bd160300a30539bd5398", +"databricks": "fcb2bd160300a30539bd5398", +"duckdb": "fcb2bd160300a30539bd5398", +"generic": "fcb2bd160300a30539bd5398", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "fcb2bd160300a30539bd5398", +"postgres": "fcb2bd160300a30539bd5398", +"postgresql": "fcb2bd160300a30539bd5398", +"snowflake": "fcb2bd160300a30539bd5398", +"tsql": "fcb2bd160300a30539bd5398" +} +], +[ +"type", +{ +"DuckDB": "fe23594c781e79cbb0c8927a", +"None": "fe23594c781e79cbb0c8927a", +"bigquery": "fe23594c781e79cbb0c8927a", +"databricks": "fe23594c781e79cbb0c8927a", +"duckdb": "fe23594c781e79cbb0c8927a", +"generic": "fe23594c781e79cbb0c8927a", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "fe23594c781e79cbb0c8927a", +"postgres": "fe23594c781e79cbb0c8927a", +"postgresql": "fe23594c781e79cbb0c8927a", +"snowflake": "38b2ec94bf02be40007ce525", +"tsql": "fe23594c781e79cbb0c8927a" +} +], +[ +"type", +{ +"DuckDB": "c0eec31620dfc2ac0028173d", +"None": "d3bcf10e00645b12a802c7d0", +"bigquery": "02e0b2ed25f32a8d09350a23", +"databricks": "d3bcf10e00645b12a802c7d0", +"duckdb": "c0eec31620dfc2ac0028173d", +"generic": "d3bcf10e00645b12a802c7d0", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "6c03a3450ea4742ee7396e3c", +"postgres": "c0eec31620dfc2ac0028173d", +"postgresql": "c0eec31620dfc2ac0028173d", +"snowflake": "d379c0ee4dad89e570b7329e", +"tsql": "d1dc9a140dbe2eb1874c6ad7" +} +], +[ +"type", +{ +"DuckDB": "06aec7cca4b30489405665e2", +"None": "06aec7cca4b30489405665e2", +"bigquery": "06aec7cca4b30489405665e2", +"databricks": "06aec7cca4b30489405665e2", +"duckdb": "06aec7cca4b30489405665e2", +"generic": "06aec7cca4b30489405665e2", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "06aec7cca4b30489405665e2", +"postgres": "06aec7cca4b30489405665e2", +"postgresql": "06aec7cca4b30489405665e2", +"snowflake": "06aec7cca4b30489405665e2", +"tsql": "06aec7cca4b30489405665e2" +} +], +[ +"type", +{ +"DuckDB": "76b7de42fb46036e5c9279bf", +"None": "76b7de42fb46036e5c9279bf", +"bigquery": "76b7de42fb46036e5c9279bf", +"databricks": "76b7de42fb46036e5c9279bf", +"duckdb": "76b7de42fb46036e5c9279bf", +"generic": "76b7de42fb46036e5c9279bf", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "76b7de42fb46036e5c9279bf", +"postgres": "76b7de42fb46036e5c9279bf", +"postgresql": "76b7de42fb46036e5c9279bf", +"snowflake": "76b7de42fb46036e5c9279bf", +"tsql": "76b7de42fb46036e5c9279bf" +} +], +[ +"type", +{ +"DuckDB": "93c1b5b5960e26479baf88d0", +"None": "93c1b5b5960e26479baf88d0", +"bigquery": "93c1b5b5960e26479baf88d0", +"databricks": "93c1b5b5960e26479baf88d0", +"duckdb": "93c1b5b5960e26479baf88d0", +"generic": "93c1b5b5960e26479baf88d0", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "93c1b5b5960e26479baf88d0", +"postgres": "93c1b5b5960e26479baf88d0", +"postgresql": "93c1b5b5960e26479baf88d0", +"snowflake": "93c1b5b5960e26479baf88d0", +"tsql": "93c1b5b5960e26479baf88d0" +} +], +[ +"type", +{ +"DuckDB": "3b3de43279bf3f0706595e4a", +"None": "9db9d9c0f19fb71af06e1044", +"bigquery": "a4d165ed06d0b1b815192ef4", +"databricks": "9db9d9c0f19fb71af06e1044", +"duckdb": "3b3de43279bf3f0706595e4a", +"generic": "9db9d9c0f19fb71af06e1044", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "6c03a3450ea4742ee7396e3c", +"postgres": "3b3de43279bf3f0706595e4a", +"postgresql": "3b3de43279bf3f0706595e4a", +"snowflake": "0b6d401f07331fac8353bbd3", +"tsql": "b9c379a586b78ced66993a52" +} +], +[ +"type", +{ +"DuckDB": "6965b3d5426a0af9750f9a03", +"None": "6965b3d5426a0af9750f9a03", +"bigquery": "6965b3d5426a0af9750f9a03", +"databricks": "6965b3d5426a0af9750f9a03", +"duckdb": "6965b3d5426a0af9750f9a03", +"generic": "6965b3d5426a0af9750f9a03", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "6965b3d5426a0af9750f9a03", +"postgres": "6965b3d5426a0af9750f9a03", +"postgresql": "6965b3d5426a0af9750f9a03", +"snowflake": "6965b3d5426a0af9750f9a03", +"tsql": "6965b3d5426a0af9750f9a03" +} +], +[ +"type", +{ +"DuckDB": "7aa59eed1bba74a9dee48e59", +"None": "7aa59eed1bba74a9dee48e59", +"bigquery": "7aa59eed1bba74a9dee48e59", +"databricks": "7aa59eed1bba74a9dee48e59", +"duckdb": "7aa59eed1bba74a9dee48e59", +"generic": "7aa59eed1bba74a9dee48e59", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "7aa59eed1bba74a9dee48e59", +"postgres": "7aa59eed1bba74a9dee48e59", +"postgresql": "7aa59eed1bba74a9dee48e59", +"snowflake": "7aa59eed1bba74a9dee48e59", +"tsql": "7aa59eed1bba74a9dee48e59" +} +], +[ +"type", +{ +"DuckDB": "66e7166890ccedeaad6c241a", +"None": "66e7166890ccedeaad6c241a", +"bigquery": "66e7166890ccedeaad6c241a", +"databricks": "66e7166890ccedeaad6c241a", +"duckdb": "66e7166890ccedeaad6c241a", +"generic": "66e7166890ccedeaad6c241a", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "66e7166890ccedeaad6c241a", +"postgres": "66e7166890ccedeaad6c241a", +"postgresql": "66e7166890ccedeaad6c241a", +"snowflake": "66e7166890ccedeaad6c241a", +"tsql": "66e7166890ccedeaad6c241a" +} +], +[ +"type", +{ +"DuckDB": "9aff7fcc7d550e1a8d105471", +"None": "9aff7fcc7d550e1a8d105471", +"bigquery": "f9bb9d0c419201aea072940b", +"databricks": "9aff7fcc7d550e1a8d105471", +"duckdb": "9aff7fcc7d550e1a8d105471", +"generic": "9aff7fcc7d550e1a8d105471", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "9aff7fcc7d550e1a8d105471", +"postgres": "9aff7fcc7d550e1a8d105471", +"postgresql": "9aff7fcc7d550e1a8d105471", +"snowflake": "9aff7fcc7d550e1a8d105471", +"tsql": "9aff7fcc7d550e1a8d105471" +} +], +[ +"type", +{ +"DuckDB": "b561884132dbe7e42b719110", +"None": "b561884132dbe7e42b719110", +"bigquery": "b1b23029bedaa16e2a6f8516", +"databricks": "b561884132dbe7e42b719110", +"duckdb": "b561884132dbe7e42b719110", +"generic": "b561884132dbe7e42b719110", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "b561884132dbe7e42b719110", +"postgres": "b561884132dbe7e42b719110", +"postgresql": "b561884132dbe7e42b719110", +"snowflake": "b561884132dbe7e42b719110", +"tsql": "b561884132dbe7e42b719110" +} +], +[ +"type", +{ +"DuckDB": "fb6eefdc9bed918e3ac82197", +"None": "fb6eefdc9bed918e3ac82197", +"bigquery": "fb6eefdc9bed918e3ac82197", +"databricks": "fb6eefdc9bed918e3ac82197", +"duckdb": "fb6eefdc9bed918e3ac82197", +"generic": "fb6eefdc9bed918e3ac82197", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "fb6eefdc9bed918e3ac82197", +"postgres": "fb6eefdc9bed918e3ac82197", +"postgresql": "fb6eefdc9bed918e3ac82197", +"snowflake": "fb6eefdc9bed918e3ac82197", +"tsql": "fb6eefdc9bed918e3ac82197" +} +], +[ +"type", +{ +"DuckDB": "8698d724534891869075175e", +"None": "0017a88bb60ec3403c786ed8", +"bigquery": "47e0816fecdd9e015d7aeb79", +"databricks": "0017a88bb60ec3403c786ed8", +"duckdb": "8698d724534891869075175e", +"generic": "0017a88bb60ec3403c786ed8", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "6c03a3450ea4742ee7396e3c", +"postgres": "8698d724534891869075175e", +"postgresql": "8698d724534891869075175e", +"snowflake": "e6f36041b1d9fb8fe3a18cbb", +"tsql": "d1dc9a140dbe2eb1874c6ad7" +} +], +[ +"type", +{ +"DuckDB": "ee07062f9d57cfdfb20f327b", +"None": "ee07062f9d57cfdfb20f327b", +"bigquery": "1b5f2388e58e5d99180f6450", +"databricks": "0a22fc4bfa30bc1953d41de6", +"duckdb": "ee07062f9d57cfdfb20f327b", +"generic": "ee07062f9d57cfdfb20f327b", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "ee07062f9d57cfdfb20f327b", +"postgres": "0a9a262e0d175ab0eb0865e2", +"postgresql": "0a9a262e0d175ab0eb0865e2", +"snowflake": "0f4d95882eb1debabb5a887b", +"tsql": "ee374268d4ffdfcf4f1eec33" +} +], +[ +"type", +{ +"DuckDB": "0c43dc837a50933667588ef1", +"None": "0c43dc837a50933667588ef1", +"bigquery": "0c43dc837a50933667588ef1", +"databricks": "0c43dc837a50933667588ef1", +"duckdb": "0c43dc837a50933667588ef1", +"generic": "0c43dc837a50933667588ef1", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "0c43dc837a50933667588ef1", +"postgres": "0c43dc837a50933667588ef1", +"postgresql": "0c43dc837a50933667588ef1", +"snowflake": "0c43dc837a50933667588ef1", +"tsql": "0c43dc837a50933667588ef1" +} +], +[ +"type", +{ +"DuckDB": "d2c97d221599d038d9875873", +"None": "d2c97d221599d038d9875873", +"bigquery": "d2c97d221599d038d9875873", +"databricks": "d2c97d221599d038d9875873", +"duckdb": "d2c97d221599d038d9875873", +"generic": "d2c97d221599d038d9875873", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "d2c97d221599d038d9875873", +"postgres": "d2c97d221599d038d9875873", +"postgresql": "d2c97d221599d038d9875873", +"snowflake": "d2c97d221599d038d9875873", +"tsql": "d2c97d221599d038d9875873" +} +], +[ +"type", +{ +"DuckDB": "e2879cf4770e7f48d2dd704a", +"None": "e2879cf4770e7f48d2dd704a", +"bigquery": "c9b810639795a7bfab91b98d", +"databricks": "e2879cf4770e7f48d2dd704a", +"duckdb": "e2879cf4770e7f48d2dd704a", +"generic": "e2879cf4770e7f48d2dd704a", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "e2879cf4770e7f48d2dd704a", +"postgres": "e2879cf4770e7f48d2dd704a", +"postgresql": "e2879cf4770e7f48d2dd704a", +"snowflake": "97a20344d811fb77c7690863", +"tsql": "e2879cf4770e7f48d2dd704a" +} +], +[ +"type", +{ +"DuckDB": "1eb7fb4e8cf75773c5573562", +"None": "1eb7fb4e8cf75773c5573562", +"bigquery": "c9b810639795a7bfab91b98d", +"databricks": "1eb7fb4e8cf75773c5573562", +"duckdb": "1eb7fb4e8cf75773c5573562", +"generic": "1eb7fb4e8cf75773c5573562", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "1eb7fb4e8cf75773c5573562", +"postgres": "1eb7fb4e8cf75773c5573562", +"postgresql": "1eb7fb4e8cf75773c5573562", +"snowflake": "97a20344d811fb77c7690863", +"tsql": "1eb7fb4e8cf75773c5573562" +} +], +[ +"type", +{ +"DuckDB": "aab0389e2b5470136660bf8a", +"None": "aab0389e2b5470136660bf8a", +"bigquery": "c9b810639795a7bfab91b98d", +"databricks": "aab0389e2b5470136660bf8a", +"duckdb": "aab0389e2b5470136660bf8a", +"generic": "aab0389e2b5470136660bf8a", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "aab0389e2b5470136660bf8a", +"postgres": "aab0389e2b5470136660bf8a", +"postgresql": "aab0389e2b5470136660bf8a", +"snowflake": "97a20344d811fb77c7690863", +"tsql": "aab0389e2b5470136660bf8a" +} +], +[ +"type", +{ +"DuckDB": "3f71ab5f3c1c040da96f2cec", +"None": "3f71ab5f3c1c040da96f2cec", +"bigquery": "3f71ab5f3c1c040da96f2cec", +"databricks": "3f71ab5f3c1c040da96f2cec", +"duckdb": "3f71ab5f3c1c040da96f2cec", +"generic": "3f71ab5f3c1c040da96f2cec", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "3f71ab5f3c1c040da96f2cec", +"postgres": "3f71ab5f3c1c040da96f2cec", +"postgresql": "3f71ab5f3c1c040da96f2cec", +"snowflake": "3f71ab5f3c1c040da96f2cec", +"tsql": "3f71ab5f3c1c040da96f2cec" +} +], +[ +"type", +{ +"DuckDB": "0c4610f182f18bf41d306e01", +"None": "0c4610f182f18bf41d306e01", +"bigquery": "0c4610f182f18bf41d306e01", +"databricks": "0c4610f182f18bf41d306e01", +"duckdb": "0c4610f182f18bf41d306e01", +"generic": "0c4610f182f18bf41d306e01", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "0c4610f182f18bf41d306e01", +"postgres": "0c4610f182f18bf41d306e01", +"postgresql": "0c4610f182f18bf41d306e01", +"snowflake": "0c4610f182f18bf41d306e01", +"tsql": "0c4610f182f18bf41d306e01" +} +], +[ +"type", +{ +"DuckDB": "ab5ad6180652b3b00d1f5b01", +"None": "ab5ad6180652b3b00d1f5b01", +"bigquery": "946d5ee30ab7469c57d850df", +"databricks": "ab5ad6180652b3b00d1f5b01", +"duckdb": "ab5ad6180652b3b00d1f5b01", +"generic": "ab5ad6180652b3b00d1f5b01", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "ab5ad6180652b3b00d1f5b01", +"postgres": "ab5ad6180652b3b00d1f5b01", +"postgresql": "ab5ad6180652b3b00d1f5b01", +"snowflake": "f43dac38f34a1c0618a3f812", +"tsql": "ab5ad6180652b3b00d1f5b01" +} +], +[ +"type", +{ +"DuckDB": "1d8b945fd793ecdcacb90c21", +"None": "1d8b945fd793ecdcacb90c21", +"bigquery": "68d2179839f17f0eb289d1aa", +"databricks": "e3bc1b8bad22d8104417b00f", +"duckdb": "1d8b945fd793ecdcacb90c21", +"generic": "1d8b945fd793ecdcacb90c21", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "1d8b945fd793ecdcacb90c21", +"postgres": "3efe8bb57c98fcbe74096b3c", +"postgresql": "3efe8bb57c98fcbe74096b3c", +"snowflake": "1d8b945fd793ecdcacb90c21", +"tsql": "1d8b945fd793ecdcacb90c21" +} +], +[ +"type", +{ +"DuckDB": "4c4563a9f306a1bb11e116d9", +"None": "4c4563a9f306a1bb11e116d9", +"bigquery": "23ee196b7bd6039855a1460f", +"databricks": "4c4563a9f306a1bb11e116d9", +"duckdb": "4c4563a9f306a1bb11e116d9", +"generic": "4c4563a9f306a1bb11e116d9", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "4c4563a9f306a1bb11e116d9", +"postgres": "4c4563a9f306a1bb11e116d9", +"postgresql": "4c4563a9f306a1bb11e116d9", +"snowflake": "5d25d5e13f81700741695ed4", +"tsql": "4c4563a9f306a1bb11e116d9" +} +], +[ +"type", +{ +"DuckDB": "29739921db4d47abc1ac18c7", +"None": "29739921db4d47abc1ac18c7", +"bigquery": "01d1b160c1768fa1cd4b2e45", +"databricks": "adbb06204fd66d8071c3dbc6", +"duckdb": "29739921db4d47abc1ac18c7", +"generic": "29739921db4d47abc1ac18c7", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "29739921db4d47abc1ac18c7", +"postgres": "29739921db4d47abc1ac18c7", +"postgresql": "29739921db4d47abc1ac18c7", +"snowflake": "216a7f0ead009a087eea4e1c", +"tsql": "561143bc26e834af800f173b" +} +], +[ +"type", +{ +"DuckDB": "e2879cf4770e7f48d2dd704a", +"None": "e2879cf4770e7f48d2dd704a", +"bigquery": "c9b810639795a7bfab91b98d", +"databricks": "e2879cf4770e7f48d2dd704a", +"duckdb": "e2879cf4770e7f48d2dd704a", +"generic": "e2879cf4770e7f48d2dd704a", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "e2879cf4770e7f48d2dd704a", +"postgres": "e2879cf4770e7f48d2dd704a", +"postgresql": "e2879cf4770e7f48d2dd704a", +"snowflake": "97a20344d811fb77c7690863", +"tsql": "e2879cf4770e7f48d2dd704a" +} +], +[ +"type", +{ +"DuckDB": "ee47e1424cb01deb0cf51760", +"None": "ee47e1424cb01deb0cf51760", +"bigquery": "ee47e1424cb01deb0cf51760", +"databricks": "ee47e1424cb01deb0cf51760", +"duckdb": "ee47e1424cb01deb0cf51760", +"generic": "ee47e1424cb01deb0cf51760", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "ee47e1424cb01deb0cf51760", +"postgres": "ee47e1424cb01deb0cf51760", +"postgresql": "ee47e1424cb01deb0cf51760", +"snowflake": "ee47e1424cb01deb0cf51760", +"tsql": "ee47e1424cb01deb0cf51760" +} +], +[ +"type", +{ +"DuckDB": "1655128a72b1db9af6a89df3", +"None": "1655128a72b1db9af6a89df3", +"bigquery": "b4c316e81db1cb6a277b5d27", +"databricks": "b4c316e81db1cb6a277b5d27", +"duckdb": "1655128a72b1db9af6a89df3", +"generic": "1655128a72b1db9af6a89df3", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "b4c316e81db1cb6a277b5d27", +"postgres": "1655128a72b1db9af6a89df3", +"postgresql": "1655128a72b1db9af6a89df3", +"snowflake": "1655128a72b1db9af6a89df3", +"tsql": "1655128a72b1db9af6a89df3" +} +], +[ +"type", +{ +"DuckDB": "768fc4c8dd514e3bc66f6184", +"None": "768fc4c8dd514e3bc66f6184", +"bigquery": "1b5e4ba111b3a98453dd1b5c", +"databricks": "28beac12e88e437078a0c62a", +"duckdb": "768fc4c8dd514e3bc66f6184", +"generic": "768fc4c8dd514e3bc66f6184", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "768fc4c8dd514e3bc66f6184", +"postgres": "768fc4c8dd514e3bc66f6184", +"postgresql": "768fc4c8dd514e3bc66f6184", +"snowflake": "28beac12e88e437078a0c62a", +"tsql": "28beac12e88e437078a0c62a" +} +], +[ +"type", +{ +"DuckDB": "b46dfa976d5ba04f95bea32b", +"None": "b46dfa976d5ba04f95bea32b", +"bigquery": "68d2179839f17f0eb289d1aa", +"databricks": "b46dfa976d5ba04f95bea32b", +"duckdb": "b46dfa976d5ba04f95bea32b", +"generic": "b46dfa976d5ba04f95bea32b", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "b46dfa976d5ba04f95bea32b", +"postgres": "34dcdfe3e3afe6140e1353e0", +"postgresql": "34dcdfe3e3afe6140e1353e0", +"snowflake": "b46dfa976d5ba04f95bea32b", +"tsql": "1d8b945fd793ecdcacb90c21" +} +], +[ +"type", +{ +"DuckDB": "c50a316d091c821866e4bfba", +"None": "c50a316d091c821866e4bfba", +"bigquery": "c50a316d091c821866e4bfba", +"databricks": "c50a316d091c821866e4bfba", +"duckdb": "c50a316d091c821866e4bfba", +"generic": "c50a316d091c821866e4bfba", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "c50a316d091c821866e4bfba", +"postgres": "c50a316d091c821866e4bfba", +"postgresql": "c50a316d091c821866e4bfba", +"snowflake": "c50a316d091c821866e4bfba", +"tsql": "c50a316d091c821866e4bfba" +} +], +[ +"type", +{ +"DuckDB": "2a0918be53051fe629d9ff8f", +"None": "2a0918be53051fe629d9ff8f", +"bigquery": "2a0918be53051fe629d9ff8f", +"databricks": "2a0918be53051fe629d9ff8f", +"duckdb": "2a0918be53051fe629d9ff8f", +"generic": "2a0918be53051fe629d9ff8f", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "2a0918be53051fe629d9ff8f", +"postgres": "2a0918be53051fe629d9ff8f", +"postgresql": "2a0918be53051fe629d9ff8f", +"snowflake": "3e611643f0beab4953c4e09b", +"tsql": "2a0918be53051fe629d9ff8f" +} +], +[ +"type", +{ +"DuckDB": "e2879cf4770e7f48d2dd704a", +"None": "e2879cf4770e7f48d2dd704a", +"bigquery": "c9b810639795a7bfab91b98d", +"databricks": "e2879cf4770e7f48d2dd704a", +"duckdb": "e2879cf4770e7f48d2dd704a", +"generic": "e2879cf4770e7f48d2dd704a", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "e2879cf4770e7f48d2dd704a", +"postgres": "e2879cf4770e7f48d2dd704a", +"postgresql": "e2879cf4770e7f48d2dd704a", +"snowflake": "97a20344d811fb77c7690863", +"tsql": "e2879cf4770e7f48d2dd704a" +} +], +[ +"type", +{ +"DuckDB": "62368fc15cefd5807807b209", +"None": "62368fc15cefd5807807b209", +"bigquery": "e6ffdece2977be55da73b59a", +"databricks": "62368fc15cefd5807807b209", +"duckdb": "62368fc15cefd5807807b209", +"generic": "62368fc15cefd5807807b209", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "62368fc15cefd5807807b209", +"postgres": "62368fc15cefd5807807b209", +"postgresql": "62368fc15cefd5807807b209", +"snowflake": "62368fc15cefd5807807b209", +"tsql": "62368fc15cefd5807807b209" +} +], +[ +"type", +{ +"DuckDB": "755657fbcced1de4551fb370", +"None": "17a6d1702d6997aa4e447f46", +"bigquery": "17a6d1702d6997aa4e447f46", +"databricks": "17a6d1702d6997aa4e447f46", +"duckdb": "755657fbcced1de4551fb370", +"generic": "17a6d1702d6997aa4e447f46", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "17a6d1702d6997aa4e447f46", +"postgres": "17a6d1702d6997aa4e447f46", +"postgresql": "17a6d1702d6997aa4e447f46", +"snowflake": "17a6d1702d6997aa4e447f46", +"tsql": "17a6d1702d6997aa4e447f46" +} +], +[ +"type", +{ +"DuckDB": "8d66732c326e570c1efcd995", +"None": "8d66732c326e570c1efcd995", +"bigquery": "8d66732c326e570c1efcd995", +"databricks": "8d66732c326e570c1efcd995", +"duckdb": "8d66732c326e570c1efcd995", +"generic": "8d66732c326e570c1efcd995", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "8d66732c326e570c1efcd995", +"postgres": "8d66732c326e570c1efcd995", +"postgresql": "8d66732c326e570c1efcd995", +"snowflake": "8d66732c326e570c1efcd995", +"tsql": "8d66732c326e570c1efcd995" +} +], +[ +"type", +{ +"DuckDB": "caf173733defe796376d4efe", +"None": "caf173733defe796376d4efe", +"bigquery": "caf173733defe796376d4efe", +"databricks": "caf173733defe796376d4efe", +"duckdb": "caf173733defe796376d4efe", +"generic": "caf173733defe796376d4efe", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "caf173733defe796376d4efe", +"postgres": "caf173733defe796376d4efe", +"postgresql": "caf173733defe796376d4efe", +"snowflake": "caf173733defe796376d4efe", +"tsql": "caf173733defe796376d4efe" +} +], +[ +"type", +{ +"DuckDB": "de89632e277dbc8c97115419", +"None": "de89632e277dbc8c97115419", +"bigquery": "de89632e277dbc8c97115419", +"databricks": "de89632e277dbc8c97115419", +"duckdb": "de89632e277dbc8c97115419", +"generic": "de89632e277dbc8c97115419", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "de89632e277dbc8c97115419", +"postgres": "de89632e277dbc8c97115419", +"postgresql": "de89632e277dbc8c97115419", +"snowflake": "4b356542044f1267fcfc487a", +"tsql": "de89632e277dbc8c97115419" +} +], +[ +"type", +{ +"DuckDB": "14cd6e78d75f61b2bd1bbd71", +"None": "14cd6e78d75f61b2bd1bbd71", +"bigquery": "14cd6e78d75f61b2bd1bbd71", +"databricks": "73504f31156e8e661c1fb26c", +"duckdb": "14cd6e78d75f61b2bd1bbd71", +"generic": "14cd6e78d75f61b2bd1bbd71", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "73504f31156e8e661c1fb26c", +"postgres": "14cd6e78d75f61b2bd1bbd71", +"postgresql": "14cd6e78d75f61b2bd1bbd71", +"snowflake": "14cd6e78d75f61b2bd1bbd71", +"tsql": "14cd6e78d75f61b2bd1bbd71" +} +], +[ +"type", +{ +"DuckDB": "79278352c17c9de0f5a28af5", +"None": "79278352c17c9de0f5a28af5", +"bigquery": "c9b810639795a7bfab91b98d", +"databricks": "79278352c17c9de0f5a28af5", +"duckdb": "79278352c17c9de0f5a28af5", +"generic": "79278352c17c9de0f5a28af5", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "79278352c17c9de0f5a28af5", +"postgres": "79278352c17c9de0f5a28af5", +"postgresql": "79278352c17c9de0f5a28af5", +"snowflake": "97a20344d811fb77c7690863", +"tsql": "79278352c17c9de0f5a28af5" +} +], +[ +"type", +{ +"DuckDB": "cf5e019d9de8b46b75fdfdb6", +"None": "cf5e019d9de8b46b75fdfdb6", +"bigquery": "cf5e019d9de8b46b75fdfdb6", +"databricks": "cf5e019d9de8b46b75fdfdb6", +"duckdb": "cf5e019d9de8b46b75fdfdb6", +"generic": "cf5e019d9de8b46b75fdfdb6", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "cf5e019d9de8b46b75fdfdb6", +"postgres": "cf5e019d9de8b46b75fdfdb6", +"postgresql": "cf5e019d9de8b46b75fdfdb6", +"snowflake": "cf5e019d9de8b46b75fdfdb6", +"tsql": "cf5e019d9de8b46b75fdfdb6" +} +], +[ +"type", +{ +"DuckDB": "4f8af4650ce9c18ed0cb0bca", +"None": "4f8af4650ce9c18ed0cb0bca", +"bigquery": "4f8af4650ce9c18ed0cb0bca", +"databricks": "4f8af4650ce9c18ed0cb0bca", +"duckdb": "4f8af4650ce9c18ed0cb0bca", +"generic": "4f8af4650ce9c18ed0cb0bca", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "4f8af4650ce9c18ed0cb0bca", +"postgres": "4f8af4650ce9c18ed0cb0bca", +"postgresql": "4f8af4650ce9c18ed0cb0bca", +"snowflake": "4f8af4650ce9c18ed0cb0bca", +"tsql": "4f8af4650ce9c18ed0cb0bca" +} +], +[ +"type", +{ +"DuckDB": "cbd04e906c540e91d7c8ea88", +"None": "cbd04e906c540e91d7c8ea88", +"bigquery": "b5c4d5044b2a6e70633f0d0a", +"databricks": "cbd04e906c540e91d7c8ea88", +"duckdb": "cbd04e906c540e91d7c8ea88", +"generic": "cbd04e906c540e91d7c8ea88", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "cbd04e906c540e91d7c8ea88", +"postgres": "cbd04e906c540e91d7c8ea88", +"postgresql": "cbd04e906c540e91d7c8ea88", +"snowflake": "cbd04e906c540e91d7c8ea88", +"tsql": "cbd04e906c540e91d7c8ea88" +} +], +[ +"type", +{ +"DuckDB": "70fb4728c3adcf6dbe4975d5", +"None": "70fb4728c3adcf6dbe4975d5", +"bigquery": "70fb4728c3adcf6dbe4975d5", +"databricks": "70fb4728c3adcf6dbe4975d5", +"duckdb": "70fb4728c3adcf6dbe4975d5", +"generic": "70fb4728c3adcf6dbe4975d5", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "70fb4728c3adcf6dbe4975d5", +"postgres": "70fb4728c3adcf6dbe4975d5", +"postgresql": "70fb4728c3adcf6dbe4975d5", +"snowflake": "70fb4728c3adcf6dbe4975d5", +"tsql": "70fb4728c3adcf6dbe4975d5" +} +], +[ +"type", +{ +"DuckDB": "8b8d5f75ba6dec68b4cebc6b", +"None": "8b8d5f75ba6dec68b4cebc6b", +"bigquery": "8b8d5f75ba6dec68b4cebc6b", +"databricks": "8b8d5f75ba6dec68b4cebc6b", +"duckdb": "8b8d5f75ba6dec68b4cebc6b", +"generic": "8b8d5f75ba6dec68b4cebc6b", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "8b8d5f75ba6dec68b4cebc6b", +"postgres": "8b8d5f75ba6dec68b4cebc6b", +"postgresql": "8b8d5f75ba6dec68b4cebc6b", +"snowflake": "8b8d5f75ba6dec68b4cebc6b", +"tsql": "8b8d5f75ba6dec68b4cebc6b" +} +], +[ +"type", +{ +"DuckDB": "aae2b1fe6f2d9807ecde412b", +"None": "aae2b1fe6f2d9807ecde412b", +"bigquery": "e1c36a5cdd2427ff2b089ac9", +"databricks": "aae2b1fe6f2d9807ecde412b", +"duckdb": "aae2b1fe6f2d9807ecde412b", +"generic": "aae2b1fe6f2d9807ecde412b", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "aae2b1fe6f2d9807ecde412b", +"postgres": "aae2b1fe6f2d9807ecde412b", +"postgresql": "aae2b1fe6f2d9807ecde412b", +"snowflake": "aae2b1fe6f2d9807ecde412b", +"tsql": "aae2b1fe6f2d9807ecde412b" +} +], +[ +"type", +{ +"DuckDB": "8a3f094f18fb4047f0febf59", +"None": "38b2ec94bf02be40007ce525", +"bigquery": "38b2ec94bf02be40007ce525", +"databricks": "38b2ec94bf02be40007ce525", +"duckdb": "8a3f094f18fb4047f0febf59", +"generic": "38b2ec94bf02be40007ce525", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "38b2ec94bf02be40007ce525", +"postgres": "38b2ec94bf02be40007ce525", +"postgresql": "38b2ec94bf02be40007ce525", +"snowflake": "38b2ec94bf02be40007ce525", +"tsql": "38b2ec94bf02be40007ce525" +} +], +[ +"type", +{ +"DuckDB": "f30e987a1e4e17305f6863ad", +"None": "036dd6864cf4939023240245", +"bigquery": "036dd6864cf4939023240245", +"databricks": "036dd6864cf4939023240245", +"duckdb": "f30e987a1e4e17305f6863ad", +"generic": "036dd6864cf4939023240245", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "6c03a3450ea4742ee7396e3c", +"postgres": "f30e987a1e4e17305f6863ad", +"postgresql": "f30e987a1e4e17305f6863ad", +"snowflake": "ff9e7821f3892ba4ddf70a84", +"tsql": "d1dc9a140dbe2eb1874c6ad7" +} +], +[ +"type", +{ +"DuckDB": "bce60580ef3a1dc4ce569fff", +"None": "bce60580ef3a1dc4ce569fff", +"bigquery": "bce60580ef3a1dc4ce569fff", +"databricks": "bce60580ef3a1dc4ce569fff", +"duckdb": "bce60580ef3a1dc4ce569fff", +"generic": "bce60580ef3a1dc4ce569fff", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "bce60580ef3a1dc4ce569fff", +"postgres": "bce60580ef3a1dc4ce569fff", +"postgresql": "bce60580ef3a1dc4ce569fff", +"snowflake": "bce60580ef3a1dc4ce569fff", +"tsql": "bce60580ef3a1dc4ce569fff" +} +], +[ +"type", +{ +"DuckDB": "19e127c23b4598727a2d8ceb", +"None": "19e127c23b4598727a2d8ceb", +"bigquery": "6f6198e2d2c8a8d6444ef5af", +"databricks": "e3bc1b8bad22d8104417b00f", +"duckdb": "19e127c23b4598727a2d8ceb", +"generic": "19e127c23b4598727a2d8ceb", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "aed0419e7f2ce7c0a8892248", +"postgres": "19e127c23b4598727a2d8ceb", +"postgresql": "19e127c23b4598727a2d8ceb", +"snowflake": "aed0419e7f2ce7c0a8892248", +"tsql": "19e127c23b4598727a2d8ceb" +} +], +[ +"type", +{ +"DuckDB": "558da38ec4d9d5d6c72f60cf", +"None": "558da38ec4d9d5d6c72f60cf", +"bigquery": "e6ffdece2977be55da73b59a", +"databricks": "558da38ec4d9d5d6c72f60cf", +"duckdb": "558da38ec4d9d5d6c72f60cf", +"generic": "558da38ec4d9d5d6c72f60cf", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "558da38ec4d9d5d6c72f60cf", +"postgres": "558da38ec4d9d5d6c72f60cf", +"postgresql": "558da38ec4d9d5d6c72f60cf", +"snowflake": "558da38ec4d9d5d6c72f60cf", +"tsql": "558da38ec4d9d5d6c72f60cf" +} +], +[ +"type", +{ +"DuckDB": "f43dac38f34a1c0618a3f812", +"None": "f43dac38f34a1c0618a3f812", +"bigquery": "946d5ee30ab7469c57d850df", +"databricks": "f43dac38f34a1c0618a3f812", +"duckdb": "f43dac38f34a1c0618a3f812", +"generic": "f43dac38f34a1c0618a3f812", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "f43dac38f34a1c0618a3f812", +"postgres": "f43dac38f34a1c0618a3f812", +"postgresql": "f43dac38f34a1c0618a3f812", +"snowflake": "f43dac38f34a1c0618a3f812", +"tsql": "f43dac38f34a1c0618a3f812" +} +], +[ +"type", +{ +"DuckDB": "3dbbe73ee4310c73030e8110", +"None": "3dbbe73ee4310c73030e8110", +"bigquery": "3dbbe73ee4310c73030e8110", +"databricks": "3dbbe73ee4310c73030e8110", +"duckdb": "3dbbe73ee4310c73030e8110", +"generic": "3dbbe73ee4310c73030e8110", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "3dbbe73ee4310c73030e8110", +"postgres": "3dbbe73ee4310c73030e8110", +"postgresql": "3dbbe73ee4310c73030e8110", +"snowflake": "f43dac38f34a1c0618a3f812", +"tsql": "3dbbe73ee4310c73030e8110" +} +], +[ +"type", +{ +"DuckDB": "c6106f30f23f392e17eadef4", +"None": "c6106f30f23f392e17eadef4", +"bigquery": "c6106f30f23f392e17eadef4", +"databricks": "c6106f30f23f392e17eadef4", +"duckdb": "c6106f30f23f392e17eadef4", +"generic": "c6106f30f23f392e17eadef4", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "c6106f30f23f392e17eadef4", +"postgres": "c6106f30f23f392e17eadef4", +"postgresql": "c6106f30f23f392e17eadef4", +"snowflake": "c6106f30f23f392e17eadef4", +"tsql": "c6106f30f23f392e17eadef4" +} +], +[ +"type", +{ +"DuckDB": "cfb4a49a57197b0df1b2e905", +"None": "cfb4a49a57197b0df1b2e905", +"bigquery": "cfb4a49a57197b0df1b2e905", +"databricks": "cfb4a49a57197b0df1b2e905", +"duckdb": "cfb4a49a57197b0df1b2e905", +"generic": "cfb4a49a57197b0df1b2e905", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "cfb4a49a57197b0df1b2e905", +"postgres": "cfb4a49a57197b0df1b2e905", +"postgresql": "cfb4a49a57197b0df1b2e905", +"snowflake": "cfb4a49a57197b0df1b2e905", +"tsql": "cfb4a49a57197b0df1b2e905" +} +], +[ +"type", +{ +"DuckDB": "8790273499dae4e6cbd2d034", +"None": "8790273499dae4e6cbd2d034", +"bigquery": "f9bb9d0c419201aea072940b", +"databricks": "8790273499dae4e6cbd2d034", +"duckdb": "8790273499dae4e6cbd2d034", +"generic": "8790273499dae4e6cbd2d034", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "8790273499dae4e6cbd2d034", +"postgres": "8790273499dae4e6cbd2d034", +"postgresql": "8790273499dae4e6cbd2d034", +"snowflake": "9aff7fcc7d550e1a8d105471", +"tsql": "8790273499dae4e6cbd2d034" +} +], +[ +"type", +{ +"DuckDB": "e8605878c6fffc044556a858", +"None": "e8605878c6fffc044556a858", +"bigquery": "e8605878c6fffc044556a858", +"databricks": "e8605878c6fffc044556a858", +"duckdb": "e8605878c6fffc044556a858", +"generic": "e8605878c6fffc044556a858", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "e8605878c6fffc044556a858", +"postgres": "e8605878c6fffc044556a858", +"postgresql": "e8605878c6fffc044556a858", +"snowflake": "e8605878c6fffc044556a858", +"tsql": "e8605878c6fffc044556a858" +} +], +[ +"type", +{ +"DuckDB": "355fafbc65133795e6c5e43b", +"None": "355fafbc65133795e6c5e43b", +"bigquery": "355fafbc65133795e6c5e43b", +"databricks": "355fafbc65133795e6c5e43b", +"duckdb": "355fafbc65133795e6c5e43b", +"generic": "355fafbc65133795e6c5e43b", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "355fafbc65133795e6c5e43b", +"postgres": "355fafbc65133795e6c5e43b", +"postgresql": "355fafbc65133795e6c5e43b", +"snowflake": "355fafbc65133795e6c5e43b", +"tsql": "355fafbc65133795e6c5e43b" +} +], +[ +"type", +{ +"DuckDB": "0dd2a0d5610068e51e271b9f", +"None": "0dd2a0d5610068e51e271b9f", +"bigquery": "0dd2a0d5610068e51e271b9f", +"databricks": "0dd2a0d5610068e51e271b9f", +"duckdb": "0dd2a0d5610068e51e271b9f", +"generic": "0dd2a0d5610068e51e271b9f", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "0dd2a0d5610068e51e271b9f", +"postgres": "0dd2a0d5610068e51e271b9f", +"postgresql": "0dd2a0d5610068e51e271b9f", +"snowflake": "0dd2a0d5610068e51e271b9f", +"tsql": "0dd2a0d5610068e51e271b9f" +} +], +[ +"type", +{ +"DuckDB": "0703bf71a54942bdaa28406e", +"None": "0703bf71a54942bdaa28406e", +"bigquery": "a428302e4848ffe877284c84", +"databricks": "0703bf71a54942bdaa28406e", +"duckdb": "0703bf71a54942bdaa28406e", +"generic": "0703bf71a54942bdaa28406e", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "0703bf71a54942bdaa28406e", +"postgres": "0703bf71a54942bdaa28406e", +"postgresql": "0703bf71a54942bdaa28406e", +"snowflake": "652ff8b21f638eac8fdc46c5", +"tsql": "441f377c46ddc162ec0a5976" +} +], +[ +"type", +{ +"DuckDB": "6212562845efbc753cb47471", +"None": "6212562845efbc753cb47471", +"bigquery": "6212562845efbc753cb47471", +"databricks": "6212562845efbc753cb47471", +"duckdb": "6212562845efbc753cb47471", +"generic": "6212562845efbc753cb47471", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "6212562845efbc753cb47471", +"postgres": "6212562845efbc753cb47471", +"postgresql": "6212562845efbc753cb47471", +"snowflake": "6212562845efbc753cb47471", +"tsql": "6212562845efbc753cb47471" +} +], +[ +"type", +{ +"DuckDB": "e998cd8f0f74af0526b75ff0", +"None": "e998cd8f0f74af0526b75ff0", +"bigquery": "a428302e4848ffe877284c84", +"databricks": "e998cd8f0f74af0526b75ff0", +"duckdb": "e998cd8f0f74af0526b75ff0", +"generic": "e998cd8f0f74af0526b75ff0", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "e998cd8f0f74af0526b75ff0", +"postgres": "e998cd8f0f74af0526b75ff0", +"postgresql": "e998cd8f0f74af0526b75ff0", +"snowflake": "652ff8b21f638eac8fdc46c5", +"tsql": "e998cd8f0f74af0526b75ff0" +} +], +[ +"type", +{ +"DuckDB": "de89632e277dbc8c97115419", +"None": "de89632e277dbc8c97115419", +"bigquery": "de89632e277dbc8c97115419", +"databricks": "de89632e277dbc8c97115419", +"duckdb": "de89632e277dbc8c97115419", +"generic": "de89632e277dbc8c97115419", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "de89632e277dbc8c97115419", +"postgres": "de89632e277dbc8c97115419", +"postgresql": "de89632e277dbc8c97115419", +"snowflake": "4b356542044f1267fcfc487a", +"tsql": "de89632e277dbc8c97115419" +} +], +[ +"type", +{ +"DuckDB": "c50a316d091c821866e4bfba", +"None": "c50a316d091c821866e4bfba", +"bigquery": "c50a316d091c821866e4bfba", +"databricks": "c50a316d091c821866e4bfba", +"duckdb": "c50a316d091c821866e4bfba", +"generic": "c50a316d091c821866e4bfba", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "c50a316d091c821866e4bfba", +"postgres": "c50a316d091c821866e4bfba", +"postgresql": "c50a316d091c821866e4bfba", +"snowflake": "c50a316d091c821866e4bfba", +"tsql": "c50a316d091c821866e4bfba" +} +], +[ +"type", +{ +"DuckDB": "285056becb5d467811be7cd6", +"None": "285056becb5d467811be7cd6", +"bigquery": "0712c33a016f7dd6a37ee011", +"databricks": "285056becb5d467811be7cd6", +"duckdb": "285056becb5d467811be7cd6", +"generic": "285056becb5d467811be7cd6", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "fc10fc558d906a80a6404b7f", +"postgres": "285056becb5d467811be7cd6", +"postgresql": "285056becb5d467811be7cd6", +"snowflake": "0712c33a016f7dd6a37ee011", +"tsql": "285056becb5d467811be7cd6" +} +], +[ +"type", +{ +"DuckDB": "1655128a72b1db9af6a89df3", +"None": "1655128a72b1db9af6a89df3", +"bigquery": "b4c316e81db1cb6a277b5d27", +"databricks": "b4c316e81db1cb6a277b5d27", +"duckdb": "1655128a72b1db9af6a89df3", +"generic": "1655128a72b1db9af6a89df3", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "b4c316e81db1cb6a277b5d27", +"postgres": "1655128a72b1db9af6a89df3", +"postgresql": "1655128a72b1db9af6a89df3", +"snowflake": "1655128a72b1db9af6a89df3", +"tsql": "1655128a72b1db9af6a89df3" +} +], +[ +"type", +{ +"DuckDB": "1d8b945fd793ecdcacb90c21", +"None": "1d8b945fd793ecdcacb90c21", +"bigquery": "68d2179839f17f0eb289d1aa", +"databricks": "e3bc1b8bad22d8104417b00f", +"duckdb": "1d8b945fd793ecdcacb90c21", +"generic": "1d8b945fd793ecdcacb90c21", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "1d8b945fd793ecdcacb90c21", +"postgres": "3efe8bb57c98fcbe74096b3c", +"postgresql": "3efe8bb57c98fcbe74096b3c", +"snowflake": "1d8b945fd793ecdcacb90c21", +"tsql": "1d8b945fd793ecdcacb90c21" +} +], +[ +"type", +{ +"DuckDB": "3cf4b9eaf303451db16b56f0", +"None": "3cf4b9eaf303451db16b56f0", +"bigquery": "3cf4b9eaf303451db16b56f0", +"databricks": "3cf4b9eaf303451db16b56f0", +"duckdb": "3cf4b9eaf303451db16b56f0", +"generic": "3cf4b9eaf303451db16b56f0", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "3cf4b9eaf303451db16b56f0", +"postgres": "3cf4b9eaf303451db16b56f0", +"postgresql": "3cf4b9eaf303451db16b56f0", +"snowflake": "3cf4b9eaf303451db16b56f0", +"tsql": "3cf4b9eaf303451db16b56f0" +} +], +[ +"type", +{ +"DuckDB": "e57ac1541fb51b362cd5b470", +"None": "e57ac1541fb51b362cd5b470", +"bigquery": "e57ac1541fb51b362cd5b470", +"databricks": "e57ac1541fb51b362cd5b470", +"duckdb": "e57ac1541fb51b362cd5b470", +"generic": "e57ac1541fb51b362cd5b470", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "e57ac1541fb51b362cd5b470", +"postgres": "e57ac1541fb51b362cd5b470", +"postgresql": "e57ac1541fb51b362cd5b470", +"snowflake": "4b356542044f1267fcfc487a", +"tsql": "e57ac1541fb51b362cd5b470" +} +], +[ +"type", +{ +"DuckDB": "19bdd92ea0cc5fb028657510", +"None": "1e75e5227bea0ae294ac7af1", +"bigquery": "1e75e5227bea0ae294ac7af1", +"databricks": "1e75e5227bea0ae294ac7af1", +"duckdb": "19bdd92ea0cc5fb028657510", +"generic": "1e75e5227bea0ae294ac7af1", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "19bdd92ea0cc5fb028657510", +"postgres": "19bdd92ea0cc5fb028657510", +"postgresql": "19bdd92ea0cc5fb028657510", +"snowflake": "8ff614b7306c0edbe36ce00b", +"tsql": "901e8c830028411846541f65" +} +], +[ +"type", +{ +"DuckDB": "638ca9212b62ada31a448c62", +"None": "1fec266134381c760a254d16", +"bigquery": "1fec266134381c760a254d16", +"databricks": "1fec266134381c760a254d16", +"duckdb": "638ca9212b62ada31a448c62", +"generic": "1fec266134381c760a254d16", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "1fec266134381c760a254d16", +"postgres": "1fec266134381c760a254d16", +"postgresql": "1fec266134381c760a254d16", +"snowflake": "1fec266134381c760a254d16", +"tsql": "1fec266134381c760a254d16" +} +], +[ +"type", +{ +"DuckDB": "3d23f811a03db519b598c815", +"None": "3d23f811a03db519b598c815", +"bigquery": "3d23f811a03db519b598c815", +"databricks": "3d23f811a03db519b598c815", +"duckdb": "3d23f811a03db519b598c815", +"generic": "3d23f811a03db519b598c815", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "3d23f811a03db519b598c815", +"postgres": "3d23f811a03db519b598c815", +"postgresql": "3d23f811a03db519b598c815", +"snowflake": "3d23f811a03db519b598c815", +"tsql": "3d23f811a03db519b598c815" +} +], +[ +"type", +{ +"DuckDB": "4928771fd9e503a30457d160", +"None": "4928771fd9e503a30457d160", +"bigquery": "4928771fd9e503a30457d160", +"databricks": "4928771fd9e503a30457d160", +"duckdb": "4928771fd9e503a30457d160", +"generic": "4928771fd9e503a30457d160", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "4928771fd9e503a30457d160", +"postgres": "4928771fd9e503a30457d160", +"postgresql": "4928771fd9e503a30457d160", +"snowflake": "4928771fd9e503a30457d160", +"tsql": "4928771fd9e503a30457d160" +} +], +[ +"type", +{ +"DuckDB": "e280c4da8e0aefee0745af65", +"None": "e280c4da8e0aefee0745af65", +"bigquery": "e280c4da8e0aefee0745af65", +"databricks": "e280c4da8e0aefee0745af65", +"duckdb": "e280c4da8e0aefee0745af65", +"generic": "e280c4da8e0aefee0745af65", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "e280c4da8e0aefee0745af65", +"postgres": "e280c4da8e0aefee0745af65", +"postgresql": "e280c4da8e0aefee0745af65", +"snowflake": "e280c4da8e0aefee0745af65", +"tsql": "e280c4da8e0aefee0745af65" +} +], +[ +"type", +{ +"DuckDB": "6226bc03436ecf8fccd39252", +"None": "5aa51d84ac5e6c7a9306f348", +"bigquery": "5aa51d84ac5e6c7a9306f348", +"databricks": "5aa51d84ac5e6c7a9306f348", +"duckdb": "6226bc03436ecf8fccd39252", +"generic": "5aa51d84ac5e6c7a9306f348", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "5aa51d84ac5e6c7a9306f348", +"postgres": "5aa51d84ac5e6c7a9306f348", +"postgresql": "5aa51d84ac5e6c7a9306f348", +"snowflake": "5aa51d84ac5e6c7a9306f348", +"tsql": "5aa51d84ac5e6c7a9306f348" +} +], +[ +"type", +{ +"DuckDB": "533aa8bbcadbe01c5e7a5ba7", +"None": "533aa8bbcadbe01c5e7a5ba7", +"bigquery": "533aa8bbcadbe01c5e7a5ba7", +"databricks": "e8a1e0270aa8ec0f1dc6e35e", +"duckdb": "533aa8bbcadbe01c5e7a5ba7", +"generic": "533aa8bbcadbe01c5e7a5ba7", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "c619dae9f0c9870858ec6530", +"postgres": "533aa8bbcadbe01c5e7a5ba7", +"postgresql": "533aa8bbcadbe01c5e7a5ba7", +"snowflake": "533aa8bbcadbe01c5e7a5ba7", +"tsql": "533aa8bbcadbe01c5e7a5ba7" +} +], +[ +"type", +{ +"DuckDB": "e2879cf4770e7f48d2dd704a", +"None": "e2879cf4770e7f48d2dd704a", +"bigquery": "c9b810639795a7bfab91b98d", +"databricks": "e2879cf4770e7f48d2dd704a", +"duckdb": "e2879cf4770e7f48d2dd704a", +"generic": "e2879cf4770e7f48d2dd704a", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "e2879cf4770e7f48d2dd704a", +"postgres": "e2879cf4770e7f48d2dd704a", +"postgresql": "e2879cf4770e7f48d2dd704a", +"snowflake": "97a20344d811fb77c7690863", +"tsql": "e2879cf4770e7f48d2dd704a" +} +], +[ +"type", +{ +"DuckDB": "207acc46dcc150502155f4a3", +"None": "d638c2852078bf3facb9dc9e", +"bigquery": "285a15e7c9efb8c0d32d6070", +"databricks": "d638c2852078bf3facb9dc9e", +"duckdb": "207acc46dcc150502155f4a3", +"generic": "d638c2852078bf3facb9dc9e", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "6c03a3450ea4742ee7396e3c", +"postgres": "6c49aec265f259dd95b5310e", +"postgresql": "6c49aec265f259dd95b5310e", +"snowflake": "ef2c05747b795f92c0b523ee", +"tsql": "2954e90d1d02f8a24fb095ea" +} +], +[ +"type", +{ +"DuckDB": "ad35c4a2523ce8c2f57acf51", +"None": "ad35c4a2523ce8c2f57acf51", +"bigquery": "ad35c4a2523ce8c2f57acf51", +"databricks": "ad35c4a2523ce8c2f57acf51", +"duckdb": "ad35c4a2523ce8c2f57acf51", +"generic": "ad35c4a2523ce8c2f57acf51", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "ad35c4a2523ce8c2f57acf51", +"postgres": "ad35c4a2523ce8c2f57acf51", +"postgresql": "ad35c4a2523ce8c2f57acf51", +"snowflake": "ad35c4a2523ce8c2f57acf51", +"tsql": "ad35c4a2523ce8c2f57acf51" +} +], +[ +"type", +{ +"DuckDB": "8203bd5901a8ec71ff7c103e", +"None": "8203bd5901a8ec71ff7c103e", +"bigquery": "2a0918be53051fe629d9ff8f", +"databricks": "8203bd5901a8ec71ff7c103e", +"duckdb": "8203bd5901a8ec71ff7c103e", +"generic": "8203bd5901a8ec71ff7c103e", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "8203bd5901a8ec71ff7c103e", +"postgres": "8203bd5901a8ec71ff7c103e", +"postgresql": "8203bd5901a8ec71ff7c103e", +"snowflake": "8203bd5901a8ec71ff7c103e", +"tsql": "8203bd5901a8ec71ff7c103e" +} +], +[ +"type", +{ +"DuckDB": "f38ef32a483f1c4f89ae309e", +"None": "f38ef32a483f1c4f89ae309e", +"bigquery": "a428302e4848ffe877284c84", +"databricks": "f38ef32a483f1c4f89ae309e", +"duckdb": "f38ef32a483f1c4f89ae309e", +"generic": "f38ef32a483f1c4f89ae309e", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "f38ef32a483f1c4f89ae309e", +"postgres": "f38ef32a483f1c4f89ae309e", +"postgresql": "f38ef32a483f1c4f89ae309e", +"snowflake": "652ff8b21f638eac8fdc46c5", +"tsql": "f38ef32a483f1c4f89ae309e" +} +], +[ +"type", +{ +"DuckDB": "cd932c5de0731b5ff7bddd24", +"None": "cd932c5de0731b5ff7bddd24", +"bigquery": "cd932c5de0731b5ff7bddd24", +"databricks": "cd932c5de0731b5ff7bddd24", +"duckdb": "cd932c5de0731b5ff7bddd24", +"generic": "cd932c5de0731b5ff7bddd24", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "cd932c5de0731b5ff7bddd24", +"postgres": "cd932c5de0731b5ff7bddd24", +"postgresql": "cd932c5de0731b5ff7bddd24", +"snowflake": "cd932c5de0731b5ff7bddd24", +"tsql": "cd932c5de0731b5ff7bddd24" +} +], +[ +"type", +{ +"DuckDB": "70fb4728c3adcf6dbe4975d5", +"None": "70fb4728c3adcf6dbe4975d5", +"bigquery": "70fb4728c3adcf6dbe4975d5", +"databricks": "70fb4728c3adcf6dbe4975d5", +"duckdb": "70fb4728c3adcf6dbe4975d5", +"generic": "70fb4728c3adcf6dbe4975d5", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "70fb4728c3adcf6dbe4975d5", +"postgres": "70fb4728c3adcf6dbe4975d5", +"postgresql": "70fb4728c3adcf6dbe4975d5", +"snowflake": "70fb4728c3adcf6dbe4975d5", +"tsql": "70fb4728c3adcf6dbe4975d5" +} +], +[ +"type", +{ +"DuckDB": "19a1a80ffc06169f32694de8", +"None": "19a1a80ffc06169f32694de8", +"bigquery": "19a1a80ffc06169f32694de8", +"databricks": "19a1a80ffc06169f32694de8", +"duckdb": "19a1a80ffc06169f32694de8", +"generic": "19a1a80ffc06169f32694de8", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "19a1a80ffc06169f32694de8", +"postgres": "19a1a80ffc06169f32694de8", +"postgresql": "19a1a80ffc06169f32694de8", +"snowflake": "19a1a80ffc06169f32694de8", +"tsql": "19a1a80ffc06169f32694de8" +} +], +[ +"type", +{ +"DuckDB": "f38ef32a483f1c4f89ae309e", +"None": "f38ef32a483f1c4f89ae309e", +"bigquery": "a428302e4848ffe877284c84", +"databricks": "f38ef32a483f1c4f89ae309e", +"duckdb": "f38ef32a483f1c4f89ae309e", +"generic": "f38ef32a483f1c4f89ae309e", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "f38ef32a483f1c4f89ae309e", +"postgres": "f38ef32a483f1c4f89ae309e", +"postgresql": "f38ef32a483f1c4f89ae309e", +"snowflake": "652ff8b21f638eac8fdc46c5", +"tsql": "f38ef32a483f1c4f89ae309e" +} +], +[ +"type", +{ +"DuckDB": "2e28de65a4b680fb5f4ebda9", +"None": "2e28de65a4b680fb5f4ebda9", +"bigquery": "2e28de65a4b680fb5f4ebda9", +"databricks": "2e28de65a4b680fb5f4ebda9", +"duckdb": "2e28de65a4b680fb5f4ebda9", +"generic": "2e28de65a4b680fb5f4ebda9", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "2e28de65a4b680fb5f4ebda9", +"postgres": "2e28de65a4b680fb5f4ebda9", +"postgresql": "2e28de65a4b680fb5f4ebda9", +"snowflake": "2e28de65a4b680fb5f4ebda9", +"tsql": "2e28de65a4b680fb5f4ebda9" +} +], +[ +"type", +{ +"DuckDB": "ebc821a95b9286e22c2b26d0", +"None": "ebc821a95b9286e22c2b26d0", +"bigquery": "19a1a80ffc06169f32694de8", +"databricks": "ebc821a95b9286e22c2b26d0", +"duckdb": "ebc821a95b9286e22c2b26d0", +"generic": "ebc821a95b9286e22c2b26d0", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "ebc821a95b9286e22c2b26d0", +"postgres": "ebc821a95b9286e22c2b26d0", +"postgresql": "ebc821a95b9286e22c2b26d0", +"snowflake": "ebc821a95b9286e22c2b26d0", +"tsql": "ebc821a95b9286e22c2b26d0" +} +], +[ +"type", +{ +"DuckDB": "ace891b6844cb59efad42031", +"None": "79278352c17c9de0f5a28af5", +"bigquery": "c9b810639795a7bfab91b98d", +"databricks": "79278352c17c9de0f5a28af5", +"duckdb": "ace891b6844cb59efad42031", +"generic": "79278352c17c9de0f5a28af5", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "79278352c17c9de0f5a28af5", +"postgres": "79278352c17c9de0f5a28af5", +"postgresql": "79278352c17c9de0f5a28af5", +"snowflake": "97a20344d811fb77c7690863", +"tsql": "79278352c17c9de0f5a28af5" +} +], +[ +"type", +{ +"DuckDB": "57922064a7dc546cbb50e42b", +"None": "57922064a7dc546cbb50e42b", +"bigquery": "57922064a7dc546cbb50e42b", +"databricks": "57922064a7dc546cbb50e42b", +"duckdb": "57922064a7dc546cbb50e42b", +"generic": "57922064a7dc546cbb50e42b", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "57922064a7dc546cbb50e42b", +"postgres": "57922064a7dc546cbb50e42b", +"postgresql": "57922064a7dc546cbb50e42b", +"snowflake": "57922064a7dc546cbb50e42b", +"tsql": "57922064a7dc546cbb50e42b" +} +], +[ +"type", +{ +"DuckDB": "e08a957777bd278f921ca0ee", +"None": "e08a957777bd278f921ca0ee", +"bigquery": "b1b23029bedaa16e2a6f8516", +"databricks": "e08a957777bd278f921ca0ee", +"duckdb": "e08a957777bd278f921ca0ee", +"generic": "e08a957777bd278f921ca0ee", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "e08a957777bd278f921ca0ee", +"postgres": "e08a957777bd278f921ca0ee", +"postgresql": "e08a957777bd278f921ca0ee", +"snowflake": "e08a957777bd278f921ca0ee", +"tsql": "e08a957777bd278f921ca0ee" +} +], +[ +"type", +{ +"DuckDB": "5980124ff4dad5573f810a21", +"None": "2785bf366213936ce93d91f2", +"bigquery": "2785bf366213936ce93d91f2", +"databricks": "2785bf366213936ce93d91f2", +"duckdb": "5980124ff4dad5573f810a21", +"generic": "2785bf366213936ce93d91f2", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "6c03a3450ea4742ee7396e3c", +"postgres": "5980124ff4dad5573f810a21", +"postgresql": "5980124ff4dad5573f810a21", +"snowflake": "b53e32783b8b9274e350988b", +"tsql": "6c658d2325cc2559c4253e41" +} +], +[ +"type", +{ +"DuckDB": "055c9340448c8378561480dd", +"None": "055c9340448c8378561480dd", +"bigquery": "055c9340448c8378561480dd", +"databricks": "055c9340448c8378561480dd", +"duckdb": "055c9340448c8378561480dd", +"generic": "055c9340448c8378561480dd", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "055c9340448c8378561480dd", +"postgres": "055c9340448c8378561480dd", +"postgresql": "055c9340448c8378561480dd", +"snowflake": "055c9340448c8378561480dd", +"tsql": "055c9340448c8378561480dd" +} +], +[ +"type", +{ +"DuckDB": "ab8c248625776c7ac340119c", +"None": "ab8c248625776c7ac340119c", +"bigquery": "ab8c248625776c7ac340119c", +"databricks": "ab8c248625776c7ac340119c", +"duckdb": "ab8c248625776c7ac340119c", +"generic": "ab8c248625776c7ac340119c", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "ab8c248625776c7ac340119c", +"postgres": "ab8c248625776c7ac340119c", +"postgresql": "ab8c248625776c7ac340119c", +"snowflake": "ab8c248625776c7ac340119c", +"tsql": "ab8c248625776c7ac340119c" +} +], +[ +"type", +{ +"DuckDB": "d23bf939a7eb8e49c7e6867a", +"None": "d23bf939a7eb8e49c7e6867a", +"bigquery": "d23bf939a7eb8e49c7e6867a", +"databricks": "d23bf939a7eb8e49c7e6867a", +"duckdb": "d23bf939a7eb8e49c7e6867a", +"generic": "d23bf939a7eb8e49c7e6867a", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "d23bf939a7eb8e49c7e6867a", +"postgres": "d23bf939a7eb8e49c7e6867a", +"postgresql": "d23bf939a7eb8e49c7e6867a", +"snowflake": "d23bf939a7eb8e49c7e6867a", +"tsql": "d23bf939a7eb8e49c7e6867a" +} +], +[ +"type", +{ +"DuckDB": "d79c3ac70093cb4cb531e71c", +"None": "d79c3ac70093cb4cb531e71c", +"bigquery": "b0477b36767a62145aa9158c", +"databricks": "d79c3ac70093cb4cb531e71c", +"duckdb": "d79c3ac70093cb4cb531e71c", +"generic": "d79c3ac70093cb4cb531e71c", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "d79c3ac70093cb4cb531e71c", +"postgres": "d79c3ac70093cb4cb531e71c", +"postgresql": "d79c3ac70093cb4cb531e71c", +"snowflake": "652ff8b21f638eac8fdc46c5", +"tsql": "d79c3ac70093cb4cb531e71c" +} +], +[ +"type", +{ +"DuckDB": "3f71ab5f3c1c040da96f2cec", +"None": "3f71ab5f3c1c040da96f2cec", +"bigquery": "3f71ab5f3c1c040da96f2cec", +"databricks": "3f71ab5f3c1c040da96f2cec", +"duckdb": "3f71ab5f3c1c040da96f2cec", +"generic": "3f71ab5f3c1c040da96f2cec", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "3f71ab5f3c1c040da96f2cec", +"postgres": "3f71ab5f3c1c040da96f2cec", +"postgresql": "3f71ab5f3c1c040da96f2cec", +"snowflake": "3f71ab5f3c1c040da96f2cec", +"tsql": "3f71ab5f3c1c040da96f2cec" +} +], +[ +"type", +{ +"DuckDB": "782ae75a1700e1a48355b077", +"None": "782ae75a1700e1a48355b077", +"bigquery": "782ae75a1700e1a48355b077", +"databricks": "782ae75a1700e1a48355b077", +"duckdb": "782ae75a1700e1a48355b077", +"generic": "782ae75a1700e1a48355b077", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "782ae75a1700e1a48355b077", +"postgres": "782ae75a1700e1a48355b077", +"postgresql": "782ae75a1700e1a48355b077", +"snowflake": "782ae75a1700e1a48355b077", +"tsql": "782ae75a1700e1a48355b077" +} +], +[ +"type", +{ +"DuckDB": "28eb0d6de9724959ce5ba43e", +"None": "28eb0d6de9724959ce5ba43e", +"bigquery": "f28a96f0eb38ad8874f6ec5d", +"databricks": "28eb0d6de9724959ce5ba43e", +"duckdb": "28eb0d6de9724959ce5ba43e", +"generic": "28eb0d6de9724959ce5ba43e", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "28eb0d6de9724959ce5ba43e", +"postgres": "28eb0d6de9724959ce5ba43e", +"postgresql": "28eb0d6de9724959ce5ba43e", +"snowflake": "28eb0d6de9724959ce5ba43e", +"tsql": "49cbf3d201d5d03a3e0154a0" +} +], +[ +"type", +{ +"DuckDB": "dcd1c844f2d13f3b6788d1a6", +"None": "dcd1c844f2d13f3b6788d1a6", +"bigquery": "dcd1c844f2d13f3b6788d1a6", +"databricks": "dcd1c844f2d13f3b6788d1a6", +"duckdb": "dcd1c844f2d13f3b6788d1a6", +"generic": "dcd1c844f2d13f3b6788d1a6", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "dcd1c844f2d13f3b6788d1a6", +"postgres": "dcd1c844f2d13f3b6788d1a6", +"postgresql": "dcd1c844f2d13f3b6788d1a6", +"snowflake": "dcd1c844f2d13f3b6788d1a6", +"tsql": "dcd1c844f2d13f3b6788d1a6" +} +], +[ +"type", +{ +"DuckDB": "304be1d51ad99bfab3750f57", +"None": "304be1d51ad99bfab3750f57", +"bigquery": "304be1d51ad99bfab3750f57", +"databricks": "304be1d51ad99bfab3750f57", +"duckdb": "304be1d51ad99bfab3750f57", +"generic": "304be1d51ad99bfab3750f57", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "304be1d51ad99bfab3750f57", +"postgres": "304be1d51ad99bfab3750f57", +"postgresql": "304be1d51ad99bfab3750f57", +"snowflake": "304be1d51ad99bfab3750f57", +"tsql": "304be1d51ad99bfab3750f57" +} +], +[ +"type", +{ +"DuckDB": "7466f0581624f38e4d1e972d", +"None": "f25507ff493aa410f2d2a6d6", +"bigquery": "7aa62aca0969d2a178982985", +"databricks": "3e42d732ee33bbd1424911a7", +"duckdb": "7466f0581624f38e4d1e972d", +"generic": "f25507ff493aa410f2d2a6d6", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "f25507ff493aa410f2d2a6d6", +"postgres": "f25507ff493aa410f2d2a6d6", +"postgresql": "f25507ff493aa410f2d2a6d6", +"snowflake": "60ad8b0a5cb3592bd3b0fc8f", +"tsql": "f25507ff493aa410f2d2a6d6" +} +], +[ +"type", +{ +"DuckDB": "f4c43a87a78970bca1f88b09", +"None": "f4c43a87a78970bca1f88b09", +"bigquery": "f4c43a87a78970bca1f88b09", +"databricks": "f4c43a87a78970bca1f88b09", +"duckdb": "f4c43a87a78970bca1f88b09", +"generic": "f4c43a87a78970bca1f88b09", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "f4c43a87a78970bca1f88b09", +"postgres": "f4c43a87a78970bca1f88b09", +"postgresql": "f4c43a87a78970bca1f88b09", +"snowflake": "652ff8b21f638eac8fdc46c5", +"tsql": "f4c43a87a78970bca1f88b09" +} +], +[ +"type", +{ +"DuckDB": "2427f5522575cdc3d6a74e4c", +"None": "2427f5522575cdc3d6a74e4c", +"bigquery": "2427f5522575cdc3d6a74e4c", +"databricks": "2427f5522575cdc3d6a74e4c", +"duckdb": "2427f5522575cdc3d6a74e4c", +"generic": "2427f5522575cdc3d6a74e4c", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "2427f5522575cdc3d6a74e4c", +"postgres": "2427f5522575cdc3d6a74e4c", +"postgresql": "2427f5522575cdc3d6a74e4c", +"snowflake": "2427f5522575cdc3d6a74e4c", +"tsql": "2427f5522575cdc3d6a74e4c" +} +], +[ +"type", +{ +"DuckDB": "70fb4728c3adcf6dbe4975d5", +"None": "70fb4728c3adcf6dbe4975d5", +"bigquery": "70fb4728c3adcf6dbe4975d5", +"databricks": "70fb4728c3adcf6dbe4975d5", +"duckdb": "70fb4728c3adcf6dbe4975d5", +"generic": "70fb4728c3adcf6dbe4975d5", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "70fb4728c3adcf6dbe4975d5", +"postgres": "70fb4728c3adcf6dbe4975d5", +"postgresql": "70fb4728c3adcf6dbe4975d5", +"snowflake": "70fb4728c3adcf6dbe4975d5", +"tsql": "70fb4728c3adcf6dbe4975d5" +} +], +[ +"type", +{ +"DuckDB": "3af3f9124a8649e4f72030c1", +"None": "3af3f9124a8649e4f72030c1", +"bigquery": "8191fff105ab0743bf9ffd39", +"databricks": "8191fff105ab0743bf9ffd39", +"duckdb": "3af3f9124a8649e4f72030c1", +"generic": "3af3f9124a8649e4f72030c1", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "8191fff105ab0743bf9ffd39", +"postgres": "3af3f9124a8649e4f72030c1", +"postgresql": "3af3f9124a8649e4f72030c1", +"snowflake": "3af3f9124a8649e4f72030c1", +"tsql": "3af3f9124a8649e4f72030c1" +} +], +[ +"type", +{ +"DuckDB": "e46d4be44ab9e500e9190d26", +"None": "e46d4be44ab9e500e9190d26", +"bigquery": "e6ffdece2977be55da73b59a", +"databricks": "e46d4be44ab9e500e9190d26", +"duckdb": "e46d4be44ab9e500e9190d26", +"generic": "e46d4be44ab9e500e9190d26", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "e46d4be44ab9e500e9190d26", +"postgres": "e46d4be44ab9e500e9190d26", +"postgresql": "e46d4be44ab9e500e9190d26", +"snowflake": "e46d4be44ab9e500e9190d26", +"tsql": "e46d4be44ab9e500e9190d26" +} +], +[ +"type", +{ +"DuckDB": "5c28019dce48a74708c90a76", +"None": "5c28019dce48a74708c90a76", +"bigquery": "f28a96f0eb38ad8874f6ec5d", +"databricks": "5c28019dce48a74708c90a76", +"duckdb": "5c28019dce48a74708c90a76", +"generic": "5c28019dce48a74708c90a76", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "5c28019dce48a74708c90a76", +"postgres": "5c28019dce48a74708c90a76", +"postgresql": "5c28019dce48a74708c90a76", +"snowflake": "a5656d70e208254d1d3e9b4f", +"tsql": "2a7a7132adc795ca2bc39c37" +} +], +[ +"type", +{ +"DuckDB": "0dcd6a19b7dc6f6b6d4a5006", +"None": "0dcd6a19b7dc6f6b6d4a5006", +"bigquery": "0dcd6a19b7dc6f6b6d4a5006", +"databricks": "0dcd6a19b7dc6f6b6d4a5006", +"duckdb": "0dcd6a19b7dc6f6b6d4a5006", +"generic": "0dcd6a19b7dc6f6b6d4a5006", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "0dcd6a19b7dc6f6b6d4a5006", +"postgres": "0dcd6a19b7dc6f6b6d4a5006", +"postgresql": "0dcd6a19b7dc6f6b6d4a5006", +"snowflake": "0dcd6a19b7dc6f6b6d4a5006", +"tsql": "0dcd6a19b7dc6f6b6d4a5006" +} +], +[ +"type", +{ +"DuckDB": "c2700ca3573352821e09af03", +"None": "c2700ca3573352821e09af03", +"bigquery": "a428302e4848ffe877284c84", +"databricks": "c2700ca3573352821e09af03", +"duckdb": "c2700ca3573352821e09af03", +"generic": "c2700ca3573352821e09af03", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "c2700ca3573352821e09af03", +"postgres": "c2700ca3573352821e09af03", +"postgresql": "c2700ca3573352821e09af03", +"snowflake": "652ff8b21f638eac8fdc46c5", +"tsql": "e80839f7b11a9775b7596b50" +} +], +[ +"type", +{ +"DuckDB": "787213ce6b6e210ded1d752c", +"None": "787213ce6b6e210ded1d752c", +"bigquery": "b1b23029bedaa16e2a6f8516", +"databricks": "787213ce6b6e210ded1d752c", +"duckdb": "787213ce6b6e210ded1d752c", +"generic": "787213ce6b6e210ded1d752c", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "787213ce6b6e210ded1d752c", +"postgres": "787213ce6b6e210ded1d752c", +"postgresql": "787213ce6b6e210ded1d752c", +"snowflake": "b561884132dbe7e42b719110", +"tsql": "787213ce6b6e210ded1d752c" +} +], +[ +"type", +{ +"DuckDB": "d7b74701deb8b87c32deb7a6", +"None": "d7b74701deb8b87c32deb7a6", +"bigquery": "d7b74701deb8b87c32deb7a6", +"databricks": "d7b74701deb8b87c32deb7a6", +"duckdb": "d7b74701deb8b87c32deb7a6", +"generic": "d7b74701deb8b87c32deb7a6", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "d7b74701deb8b87c32deb7a6", +"postgres": "d7b74701deb8b87c32deb7a6", +"postgresql": "d7b74701deb8b87c32deb7a6", +"snowflake": "d7b74701deb8b87c32deb7a6", +"tsql": "d7b74701deb8b87c32deb7a6" +} +], +[ +"type", +{ +"DuckDB": "a6b64a929834c52f65384447", +"None": "a6b64a929834c52f65384447", +"bigquery": "a6b64a929834c52f65384447", +"databricks": "a6b64a929834c52f65384447", +"duckdb": "a6b64a929834c52f65384447", +"generic": "a6b64a929834c52f65384447", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "a6b64a929834c52f65384447", +"postgres": "a6b64a929834c52f65384447", +"postgresql": "a6b64a929834c52f65384447", +"snowflake": "a6b64a929834c52f65384447", +"tsql": "a6b64a929834c52f65384447" +} +], +[ +"type", +{ +"DuckDB": "638ca9212b62ada31a448c62", +"None": "1fec266134381c760a254d16", +"bigquery": "1fec266134381c760a254d16", +"databricks": "1fec266134381c760a254d16", +"duckdb": "638ca9212b62ada31a448c62", +"generic": "1fec266134381c760a254d16", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "1fec266134381c760a254d16", +"postgres": "1fec266134381c760a254d16", +"postgresql": "1fec266134381c760a254d16", +"snowflake": "1fec266134381c760a254d16", +"tsql": "1fec266134381c760a254d16" +} +], +[ +"type", +{ +"DuckDB": "62368fc15cefd5807807b209", +"None": "62368fc15cefd5807807b209", +"bigquery": "e6ffdece2977be55da73b59a", +"databricks": "62368fc15cefd5807807b209", +"duckdb": "62368fc15cefd5807807b209", +"generic": "62368fc15cefd5807807b209", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "62368fc15cefd5807807b209", +"postgres": "62368fc15cefd5807807b209", +"postgresql": "62368fc15cefd5807807b209", +"snowflake": "62368fc15cefd5807807b209", +"tsql": "62368fc15cefd5807807b209" +} +], +[ +"type", +{ +"DuckDB": "fbbf6dbffd81c1b899b2f41b", +"None": "fbbf6dbffd81c1b899b2f41b", +"bigquery": "fbbf6dbffd81c1b899b2f41b", +"databricks": "fbbf6dbffd81c1b899b2f41b", +"duckdb": "fbbf6dbffd81c1b899b2f41b", +"generic": "fbbf6dbffd81c1b899b2f41b", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "fbbf6dbffd81c1b899b2f41b", +"postgres": "fbbf6dbffd81c1b899b2f41b", +"postgresql": "fbbf6dbffd81c1b899b2f41b", +"snowflake": "fbbf6dbffd81c1b899b2f41b", +"tsql": "fbbf6dbffd81c1b899b2f41b" +} +], +[ +"type", +{ +"DuckDB": "e57ac1541fb51b362cd5b470", +"None": "e57ac1541fb51b362cd5b470", +"bigquery": "e57ac1541fb51b362cd5b470", +"databricks": "e57ac1541fb51b362cd5b470", +"duckdb": "e57ac1541fb51b362cd5b470", +"generic": "e57ac1541fb51b362cd5b470", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "e57ac1541fb51b362cd5b470", +"postgres": "e57ac1541fb51b362cd5b470", +"postgresql": "e57ac1541fb51b362cd5b470", +"snowflake": "4b356542044f1267fcfc487a", +"tsql": "e57ac1541fb51b362cd5b470" +} +], +[ +"type", +{ +"DuckDB": "a2c63b7e92b578944818d750", +"None": "a2c63b7e92b578944818d750", +"bigquery": "a2c63b7e92b578944818d750", +"databricks": "a2c63b7e92b578944818d750", +"duckdb": "a2c63b7e92b578944818d750", +"generic": "a2c63b7e92b578944818d750", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "a2c63b7e92b578944818d750", +"postgres": "a2c63b7e92b578944818d750", +"postgresql": "a2c63b7e92b578944818d750", +"snowflake": "a2c63b7e92b578944818d750", +"tsql": "a2c63b7e92b578944818d750" +} +], +[ +"type", +{ +"DuckDB": "a3d6f52ec64a728636793faa", +"None": "a3d6f52ec64a728636793faa", +"bigquery": "a3d6f52ec64a728636793faa", +"databricks": "a3d6f52ec64a728636793faa", +"duckdb": "a3d6f52ec64a728636793faa", +"generic": "a3d6f52ec64a728636793faa", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "a3d6f52ec64a728636793faa", +"postgres": "a3d6f52ec64a728636793faa", +"postgresql": "a3d6f52ec64a728636793faa", +"snowflake": "a3d6f52ec64a728636793faa", +"tsql": "a3d6f52ec64a728636793faa" +} +], +[ +"type", +{ +"DuckDB": "c7b697bbfa82dd2821ad64e9", +"None": "c7b697bbfa82dd2821ad64e9", +"bigquery": "dcb00b7053ffe69fe3ce99cd", +"databricks": "dcb00b7053ffe69fe3ce99cd", +"duckdb": "c7b697bbfa82dd2821ad64e9", +"generic": "c7b697bbfa82dd2821ad64e9", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "dcb00b7053ffe69fe3ce99cd", +"postgres": "c7b697bbfa82dd2821ad64e9", +"postgresql": "c7b697bbfa82dd2821ad64e9", +"snowflake": "c7b697bbfa82dd2821ad64e9", +"tsql": "c7b697bbfa82dd2821ad64e9" +} +], +[ +"type", +{ +"DuckDB": "717cf79ef777823eb3576deb", +"None": "717cf79ef777823eb3576deb", +"bigquery": "717cf79ef777823eb3576deb", +"databricks": "717cf79ef777823eb3576deb", +"duckdb": "717cf79ef777823eb3576deb", +"generic": "717cf79ef777823eb3576deb", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "717cf79ef777823eb3576deb", +"postgres": "717cf79ef777823eb3576deb", +"postgresql": "717cf79ef777823eb3576deb", +"snowflake": "717cf79ef777823eb3576deb", +"tsql": "717cf79ef777823eb3576deb" +} +], +[ +"type", +{ +"DuckDB": "c1dad3a1ff61e56cb10b9cdf", +"None": "c1dad3a1ff61e56cb10b9cdf", +"bigquery": "c1dad3a1ff61e56cb10b9cdf", +"databricks": "c1dad3a1ff61e56cb10b9cdf", +"duckdb": "c1dad3a1ff61e56cb10b9cdf", +"generic": "c1dad3a1ff61e56cb10b9cdf", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "c1dad3a1ff61e56cb10b9cdf", +"postgres": "c1dad3a1ff61e56cb10b9cdf", +"postgresql": "c1dad3a1ff61e56cb10b9cdf", +"snowflake": "c1dad3a1ff61e56cb10b9cdf", +"tsql": "c1dad3a1ff61e56cb10b9cdf" +} +], +[ +"type", +{ +"DuckDB": "79278352c17c9de0f5a28af5", +"None": "79278352c17c9de0f5a28af5", +"bigquery": "c9b810639795a7bfab91b98d", +"databricks": "79278352c17c9de0f5a28af5", +"duckdb": "79278352c17c9de0f5a28af5", +"generic": "79278352c17c9de0f5a28af5", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "79278352c17c9de0f5a28af5", +"postgres": "79278352c17c9de0f5a28af5", +"postgresql": "79278352c17c9de0f5a28af5", +"snowflake": "97a20344d811fb77c7690863", +"tsql": "79278352c17c9de0f5a28af5" +} +], +[ +"type", +{ +"DuckDB": "755657fbcced1de4551fb370", +"None": "17a6d1702d6997aa4e447f46", +"bigquery": "17a6d1702d6997aa4e447f46", +"databricks": "17a6d1702d6997aa4e447f46", +"duckdb": "755657fbcced1de4551fb370", +"generic": "17a6d1702d6997aa4e447f46", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "17a6d1702d6997aa4e447f46", +"postgres": "17a6d1702d6997aa4e447f46", +"postgresql": "17a6d1702d6997aa4e447f46", +"snowflake": "17a6d1702d6997aa4e447f46", +"tsql": "17a6d1702d6997aa4e447f46" +} +], +[ +"type", +{ +"DuckDB": "c05190b1f2b5d7003e7076da", +"None": "c05190b1f2b5d7003e7076da", +"bigquery": "c05190b1f2b5d7003e7076da", +"databricks": "c05190b1f2b5d7003e7076da", +"duckdb": "c05190b1f2b5d7003e7076da", +"generic": "c05190b1f2b5d7003e7076da", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "c05190b1f2b5d7003e7076da", +"postgres": "c05190b1f2b5d7003e7076da", +"postgresql": "c05190b1f2b5d7003e7076da", +"snowflake": "c05190b1f2b5d7003e7076da", +"tsql": "c05190b1f2b5d7003e7076da" +} +], +[ +"type", +{ +"DuckDB": "fa45b7e4a9ef3b5a9c5781af", +"None": "fa45b7e4a9ef3b5a9c5781af", +"bigquery": "fa45b7e4a9ef3b5a9c5781af", +"databricks": "fa45b7e4a9ef3b5a9c5781af", +"duckdb": "fa45b7e4a9ef3b5a9c5781af", +"generic": "fa45b7e4a9ef3b5a9c5781af", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "fa45b7e4a9ef3b5a9c5781af", +"postgres": "fa45b7e4a9ef3b5a9c5781af", +"postgresql": "fa45b7e4a9ef3b5a9c5781af", +"snowflake": "fa45b7e4a9ef3b5a9c5781af", +"tsql": "fa45b7e4a9ef3b5a9c5781af" +} +], +[ +"type", +{ +"DuckDB": "72bd5e38b32893397eb51579", +"None": "1bdf5908ca249b2331a0427c", +"bigquery": "1bdf5908ca249b2331a0427c", +"databricks": "1bdf5908ca249b2331a0427c", +"duckdb": "72bd5e38b32893397eb51579", +"generic": "1bdf5908ca249b2331a0427c", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "1bdf5908ca249b2331a0427c", +"postgres": "1bdf5908ca249b2331a0427c", +"postgresql": "1bdf5908ca249b2331a0427c", +"snowflake": "8ff614b7306c0edbe36ce00b", +"tsql": "1bdf5908ca249b2331a0427c" +} +], +[ +"type", +{ +"DuckDB": "bb7975dcb1f2ac7cdd149b0b", +"None": "bb7975dcb1f2ac7cdd149b0b", +"bigquery": "bb7975dcb1f2ac7cdd149b0b", +"databricks": "bb7975dcb1f2ac7cdd149b0b", +"duckdb": "bb7975dcb1f2ac7cdd149b0b", +"generic": "bb7975dcb1f2ac7cdd149b0b", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "bb7975dcb1f2ac7cdd149b0b", +"postgres": "bb7975dcb1f2ac7cdd149b0b", +"postgresql": "bb7975dcb1f2ac7cdd149b0b", +"snowflake": "bb7975dcb1f2ac7cdd149b0b", +"tsql": "bb7975dcb1f2ac7cdd149b0b" +} +], +[ +"type", +{ +"DuckDB": "1eb7fb4e8cf75773c5573562", +"None": "1eb7fb4e8cf75773c5573562", +"bigquery": "c9b810639795a7bfab91b98d", +"databricks": "1eb7fb4e8cf75773c5573562", +"duckdb": "1eb7fb4e8cf75773c5573562", +"generic": "1eb7fb4e8cf75773c5573562", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "1eb7fb4e8cf75773c5573562", +"postgres": "1eb7fb4e8cf75773c5573562", +"postgresql": "1eb7fb4e8cf75773c5573562", +"snowflake": "97a20344d811fb77c7690863", +"tsql": "1eb7fb4e8cf75773c5573562" +} +], +[ +"type", +{ +"DuckDB": "74ed18299daa6faf5c9533e2", +"None": "74ed18299daa6faf5c9533e2", +"bigquery": "74ed18299daa6faf5c9533e2", +"databricks": "74ed18299daa6faf5c9533e2", +"duckdb": "74ed18299daa6faf5c9533e2", +"generic": "74ed18299daa6faf5c9533e2", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "74ed18299daa6faf5c9533e2", +"postgres": "74ed18299daa6faf5c9533e2", +"postgresql": "74ed18299daa6faf5c9533e2", +"snowflake": "74ed18299daa6faf5c9533e2", +"tsql": "74ed18299daa6faf5c9533e2" +} +], +[ +"type", +{ +"DuckDB": "60a23b7dcae6c79f4de83068", +"None": "60a23b7dcae6c79f4de83068", +"bigquery": "60a23b7dcae6c79f4de83068", +"databricks": "60a23b7dcae6c79f4de83068", +"duckdb": "60a23b7dcae6c79f4de83068", +"generic": "60a23b7dcae6c79f4de83068", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "60a23b7dcae6c79f4de83068", +"postgres": "60a23b7dcae6c79f4de83068", +"postgresql": "60a23b7dcae6c79f4de83068", +"snowflake": "60a23b7dcae6c79f4de83068", +"tsql": "60a23b7dcae6c79f4de83068" +} +], +[ +"type", +{ +"DuckDB": "0f799a95a4f5ef502897f02c", +"None": "0f799a95a4f5ef502897f02c", +"bigquery": "b1b23029bedaa16e2a6f8516", +"databricks": "0f799a95a4f5ef502897f02c", +"duckdb": "0f799a95a4f5ef502897f02c", +"generic": "0f799a95a4f5ef502897f02c", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "0f799a95a4f5ef502897f02c", +"postgres": "0f799a95a4f5ef502897f02c", +"postgresql": "0f799a95a4f5ef502897f02c", +"snowflake": "0f799a95a4f5ef502897f02c", +"tsql": "0f799a95a4f5ef502897f02c" +} +], +[ +"type", +{ +"DuckDB": "5d0a19a893dbf0c1e6e9f15c", +"None": "5d0a19a893dbf0c1e6e9f15c", +"bigquery": "5d0a19a893dbf0c1e6e9f15c", +"databricks": "5d0a19a893dbf0c1e6e9f15c", +"duckdb": "5d0a19a893dbf0c1e6e9f15c", +"generic": "5d0a19a893dbf0c1e6e9f15c", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "5d0a19a893dbf0c1e6e9f15c", +"postgres": "5d0a19a893dbf0c1e6e9f15c", +"postgresql": "5d0a19a893dbf0c1e6e9f15c", +"snowflake": "5d0a19a893dbf0c1e6e9f15c", +"tsql": "5d0a19a893dbf0c1e6e9f15c" +} +], +[ +"type", +{ +"DuckDB": "fe23594c781e79cbb0c8927a", +"None": "fe23594c781e79cbb0c8927a", +"bigquery": "fe23594c781e79cbb0c8927a", +"databricks": "fe23594c781e79cbb0c8927a", +"duckdb": "fe23594c781e79cbb0c8927a", +"generic": "fe23594c781e79cbb0c8927a", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "fe23594c781e79cbb0c8927a", +"postgres": "fe23594c781e79cbb0c8927a", +"postgresql": "fe23594c781e79cbb0c8927a", +"snowflake": "38b2ec94bf02be40007ce525", +"tsql": "fe23594c781e79cbb0c8927a" +} +], +[ +"type", +{ +"DuckDB": "855e2727b4a8cb5d2711f102", +"None": "855e2727b4a8cb5d2711f102", +"bigquery": "855e2727b4a8cb5d2711f102", +"databricks": "855e2727b4a8cb5d2711f102", +"duckdb": "855e2727b4a8cb5d2711f102", +"generic": "855e2727b4a8cb5d2711f102", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "855e2727b4a8cb5d2711f102", +"postgres": "855e2727b4a8cb5d2711f102", +"postgresql": "855e2727b4a8cb5d2711f102", +"snowflake": "855e2727b4a8cb5d2711f102", +"tsql": "855e2727b4a8cb5d2711f102" +} +], +[ +"type", +{ +"DuckDB": "1ebac487198b6c90b027faab", +"None": "1ebac487198b6c90b027faab", +"bigquery": "a428302e4848ffe877284c84", +"databricks": "1ebac487198b6c90b027faab", +"duckdb": "1ebac487198b6c90b027faab", +"generic": "1ebac487198b6c90b027faab", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "1ebac487198b6c90b027faab", +"postgres": "1ebac487198b6c90b027faab", +"postgresql": "1ebac487198b6c90b027faab", +"snowflake": "652ff8b21f638eac8fdc46c5", +"tsql": "c692d974ee3f362ecb38f27c" +} +], +[ +"type", +{ +"DuckDB": "9c2cff8be7225cf79883ca65", +"None": "9c2cff8be7225cf79883ca65", +"bigquery": "9c2cff8be7225cf79883ca65", +"databricks": "901ac89f8d9ec18bd3a61e4b", +"duckdb": "9c2cff8be7225cf79883ca65", +"generic": "9c2cff8be7225cf79883ca65", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "901ac89f8d9ec18bd3a61e4b", +"postgres": "9c2cff8be7225cf79883ca65", +"postgresql": "9c2cff8be7225cf79883ca65", +"snowflake": "9c2cff8be7225cf79883ca65", +"tsql": "9c2cff8be7225cf79883ca65" +} +], +[ +"type", +{ +"DuckDB": "74f50f8ec759a3cc65ac027d", +"None": "74f50f8ec759a3cc65ac027d", +"bigquery": "74f50f8ec759a3cc65ac027d", +"databricks": "74f50f8ec759a3cc65ac027d", +"duckdb": "74f50f8ec759a3cc65ac027d", +"generic": "74f50f8ec759a3cc65ac027d", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "74f50f8ec759a3cc65ac027d", +"postgres": "74f50f8ec759a3cc65ac027d", +"postgresql": "74f50f8ec759a3cc65ac027d", +"snowflake": "74f50f8ec759a3cc65ac027d", +"tsql": "74f50f8ec759a3cc65ac027d" +} +], +[ +"type", +{ +"DuckDB": "3dbbe73ee4310c73030e8110", +"None": "3dbbe73ee4310c73030e8110", +"bigquery": "3dbbe73ee4310c73030e8110", +"databricks": "3dbbe73ee4310c73030e8110", +"duckdb": "3dbbe73ee4310c73030e8110", +"generic": "3dbbe73ee4310c73030e8110", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "3dbbe73ee4310c73030e8110", +"postgres": "3dbbe73ee4310c73030e8110", +"postgresql": "3dbbe73ee4310c73030e8110", +"snowflake": "f43dac38f34a1c0618a3f812", +"tsql": "3dbbe73ee4310c73030e8110" +} +], +[ +"type", +{ +"DuckDB": "0dcd6a19b7dc6f6b6d4a5006", +"None": "0dcd6a19b7dc6f6b6d4a5006", +"bigquery": "0dcd6a19b7dc6f6b6d4a5006", +"databricks": "0dcd6a19b7dc6f6b6d4a5006", +"duckdb": "0dcd6a19b7dc6f6b6d4a5006", +"generic": "0dcd6a19b7dc6f6b6d4a5006", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "0dcd6a19b7dc6f6b6d4a5006", +"postgres": "0dcd6a19b7dc6f6b6d4a5006", +"postgresql": "0dcd6a19b7dc6f6b6d4a5006", +"snowflake": "0dcd6a19b7dc6f6b6d4a5006", +"tsql": "0dcd6a19b7dc6f6b6d4a5006" +} +], +[ +"type", +{ +"DuckDB": "7ffb4db35f5f9871e8c9a084", +"None": "7ffb4db35f5f9871e8c9a084", +"bigquery": "7ffb4db35f5f9871e8c9a084", +"databricks": "7ffb4db35f5f9871e8c9a084", +"duckdb": "7ffb4db35f5f9871e8c9a084", +"generic": "7ffb4db35f5f9871e8c9a084", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "7ffb4db35f5f9871e8c9a084", +"postgres": "7ffb4db35f5f9871e8c9a084", +"postgresql": "7ffb4db35f5f9871e8c9a084", +"snowflake": "7ffb4db35f5f9871e8c9a084", +"tsql": "7ffb4db35f5f9871e8c9a084" +} +], +[ +"type", +{ +"DuckDB": "d79c3ac70093cb4cb531e71c", +"None": "d79c3ac70093cb4cb531e71c", +"bigquery": "b0477b36767a62145aa9158c", +"databricks": "d79c3ac70093cb4cb531e71c", +"duckdb": "d79c3ac70093cb4cb531e71c", +"generic": "d79c3ac70093cb4cb531e71c", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "d79c3ac70093cb4cb531e71c", +"postgres": "d79c3ac70093cb4cb531e71c", +"postgresql": "d79c3ac70093cb4cb531e71c", +"snowflake": "652ff8b21f638eac8fdc46c5", +"tsql": "d79c3ac70093cb4cb531e71c" +} +], +[ +"type", +{ +"DuckDB": "3147a9e06daa6de4a4df5abc", +"None": "3147a9e06daa6de4a4df5abc", +"bigquery": "f276e907770196606577c932", +"databricks": "3147a9e06daa6de4a4df5abc", +"duckdb": "3147a9e06daa6de4a4df5abc", +"generic": "3147a9e06daa6de4a4df5abc", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "3147a9e06daa6de4a4df5abc", +"postgres": "3147a9e06daa6de4a4df5abc", +"postgresql": "3147a9e06daa6de4a4df5abc", +"snowflake": "67b5874a2c569226c490211f", +"tsql": "3147a9e06daa6de4a4df5abc" +} +], +[ +"type", +{ +"DuckDB": "7afe04283391fb5bd9bd1f6e", +"None": "6fad076e9d13c0d09c490402", +"bigquery": "6fad076e9d13c0d09c490402", +"databricks": "02e0b2ed25f32a8d09350a23", +"duckdb": "7afe04283391fb5bd9bd1f6e", +"generic": "6fad076e9d13c0d09c490402", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "6c03a3450ea4742ee7396e3c", +"postgres": "7afe04283391fb5bd9bd1f6e", +"postgresql": "7afe04283391fb5bd9bd1f6e", +"snowflake": "dddc37362726cca4f2353a8d", +"tsql": "25469e79d5519fb84076e220" +} +], +[ +"type", +{ +"DuckDB": "802f1c1fcb97ddd5679172d2", +"None": "802f1c1fcb97ddd5679172d2", +"bigquery": "a428302e4848ffe877284c84", +"databricks": "802f1c1fcb97ddd5679172d2", +"duckdb": "802f1c1fcb97ddd5679172d2", +"generic": "802f1c1fcb97ddd5679172d2", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "802f1c1fcb97ddd5679172d2", +"postgres": "802f1c1fcb97ddd5679172d2", +"postgresql": "802f1c1fcb97ddd5679172d2", +"snowflake": "652ff8b21f638eac8fdc46c5", +"tsql": "08784560ad78e14a02cc066f" +} +], +[ +"type", +{ +"DuckDB": "71cce31a35d7039dcd2aa86d", +"None": "71cce31a35d7039dcd2aa86d", +"bigquery": "04f1dc31c6fcdb2b73b4e4f3", +"databricks": "7552f1f36764fa5333dc3b01", +"duckdb": "71cce31a35d7039dcd2aa86d", +"generic": "71cce31a35d7039dcd2aa86d", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "71cce31a35d7039dcd2aa86d", +"postgres": "71cce31a35d7039dcd2aa86d", +"postgresql": "71cce31a35d7039dcd2aa86d", +"snowflake": "aa1ac5b2c999b497d54fa520", +"tsql": "71cce31a35d7039dcd2aa86d" +} +], +[ +"type", +{ +"DuckDB": "aae2b1fe6f2d9807ecde412b", +"None": "aae2b1fe6f2d9807ecde412b", +"bigquery": "e1c36a5cdd2427ff2b089ac9", +"databricks": "aae2b1fe6f2d9807ecde412b", +"duckdb": "aae2b1fe6f2d9807ecde412b", +"generic": "aae2b1fe6f2d9807ecde412b", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "aae2b1fe6f2d9807ecde412b", +"postgres": "aae2b1fe6f2d9807ecde412b", +"postgresql": "aae2b1fe6f2d9807ecde412b", +"snowflake": "aae2b1fe6f2d9807ecde412b", +"tsql": "aae2b1fe6f2d9807ecde412b" +} +], +[ +"type", +{ +"DuckDB": "4169d9651c2a3667fc561f32", +"None": "4169d9651c2a3667fc561f32", +"bigquery": "88f7cced71c11944260bb54a", +"databricks": "4169d9651c2a3667fc561f32", +"duckdb": "4169d9651c2a3667fc561f32", +"generic": "4169d9651c2a3667fc561f32", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "4169d9651c2a3667fc561f32", +"postgres": "4169d9651c2a3667fc561f32", +"postgresql": "4169d9651c2a3667fc561f32", +"snowflake": "b210f8eb26c37b422f786c6b", +"tsql": "4169d9651c2a3667fc561f32" +} +], +[ +"type", +{ +"DuckDB": "8441d00030df06ad6a5534d3", +"None": "8441d00030df06ad6a5534d3", +"bigquery": "c9b810639795a7bfab91b98d", +"databricks": "8441d00030df06ad6a5534d3", +"duckdb": "8441d00030df06ad6a5534d3", +"generic": "8441d00030df06ad6a5534d3", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "8441d00030df06ad6a5534d3", +"postgres": "8441d00030df06ad6a5534d3", +"postgresql": "8441d00030df06ad6a5534d3", +"snowflake": "97a20344d811fb77c7690863", +"tsql": "8441d00030df06ad6a5534d3" +} +], +[ +"type", +{ +"DuckDB": "6533f23a0660791970dbbbc8", +"None": "6533f23a0660791970dbbbc8", +"bigquery": "a428302e4848ffe877284c84", +"databricks": "6533f23a0660791970dbbbc8", +"duckdb": "6533f23a0660791970dbbbc8", +"generic": "6533f23a0660791970dbbbc8", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "6533f23a0660791970dbbbc8", +"postgres": "6533f23a0660791970dbbbc8", +"postgresql": "6533f23a0660791970dbbbc8", +"snowflake": "652ff8b21f638eac8fdc46c5", +"tsql": "6533f23a0660791970dbbbc8" +} +], +[ +"type", +{ +"DuckDB": "9d0ae138704cb97e3fe4d105", +"None": "9d0ae138704cb97e3fe4d105", +"bigquery": "6d07fc2f489d414e7eb90262", +"databricks": "6d07fc2f489d414e7eb90262", +"duckdb": "9d0ae138704cb97e3fe4d105", +"generic": "9d0ae138704cb97e3fe4d105", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "6d07fc2f489d414e7eb90262", +"postgres": "9d0ae138704cb97e3fe4d105", +"postgresql": "9d0ae138704cb97e3fe4d105", +"snowflake": "9d0ae138704cb97e3fe4d105", +"tsql": "9d0ae138704cb97e3fe4d105" +} +], +[ +"type", +{ +"DuckDB": "de89632e277dbc8c97115419", +"None": "de89632e277dbc8c97115419", +"bigquery": "de89632e277dbc8c97115419", +"databricks": "de89632e277dbc8c97115419", +"duckdb": "de89632e277dbc8c97115419", +"generic": "de89632e277dbc8c97115419", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "de89632e277dbc8c97115419", +"postgres": "de89632e277dbc8c97115419", +"postgresql": "de89632e277dbc8c97115419", +"snowflake": "4b356542044f1267fcfc487a", +"tsql": "de89632e277dbc8c97115419" +} +], +[ +"type", +{ +"DuckDB": "70fb4728c3adcf6dbe4975d5", +"None": "70fb4728c3adcf6dbe4975d5", +"bigquery": "70fb4728c3adcf6dbe4975d5", +"databricks": "70fb4728c3adcf6dbe4975d5", +"duckdb": "70fb4728c3adcf6dbe4975d5", +"generic": "70fb4728c3adcf6dbe4975d5", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "70fb4728c3adcf6dbe4975d5", +"postgres": "70fb4728c3adcf6dbe4975d5", +"postgresql": "70fb4728c3adcf6dbe4975d5", +"snowflake": "70fb4728c3adcf6dbe4975d5", +"tsql": "70fb4728c3adcf6dbe4975d5" +} +], +[ +"type", +{ +"DuckDB": "2c44dc35fd1ef8701101802e", +"None": "2c44dc35fd1ef8701101802e", +"bigquery": "a428302e4848ffe877284c84", +"databricks": "2c44dc35fd1ef8701101802e", +"duckdb": "2c44dc35fd1ef8701101802e", +"generic": "2c44dc35fd1ef8701101802e", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "2c44dc35fd1ef8701101802e", +"postgres": "2c44dc35fd1ef8701101802e", +"postgresql": "2c44dc35fd1ef8701101802e", +"snowflake": "652ff8b21f638eac8fdc46c5", +"tsql": "2c44dc35fd1ef8701101802e" +} +], +[ +"type", +{ +"DuckDB": "9917d6c8c04307304904313b", +"None": "9917d6c8c04307304904313b", +"bigquery": "9917d6c8c04307304904313b", +"databricks": "9917d6c8c04307304904313b", +"duckdb": "9917d6c8c04307304904313b", +"generic": "9917d6c8c04307304904313b", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "9917d6c8c04307304904313b", +"postgres": "9917d6c8c04307304904313b", +"postgresql": "9917d6c8c04307304904313b", +"snowflake": "9917d6c8c04307304904313b", +"tsql": "9917d6c8c04307304904313b" +} +], +[ +"type", +{ +"DuckDB": "8a3f094f18fb4047f0febf59", +"None": "e51e1eecca3e36c76e34498f", +"bigquery": "5c28019dce48a74708c90a76", +"databricks": "e51e1eecca3e36c76e34498f", +"duckdb": "8a3f094f18fb4047f0febf59", +"generic": "e51e1eecca3e36c76e34498f", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "84fca9ac893777959cfd715c", +"postgres": "e51e1eecca3e36c76e34498f", +"postgresql": "e51e1eecca3e36c76e34498f", +"snowflake": "e51e1eecca3e36c76e34498f", +"tsql": "8adf69b4c11191257f2953cc" +} +], +[ +"type", +{ +"DuckDB": "4b356542044f1267fcfc487a", +"None": "4b356542044f1267fcfc487a", +"bigquery": "4b356542044f1267fcfc487a", +"databricks": "4b356542044f1267fcfc487a", +"duckdb": "4b356542044f1267fcfc487a", +"generic": "4b356542044f1267fcfc487a", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "4b356542044f1267fcfc487a", +"postgres": "4b356542044f1267fcfc487a", +"postgresql": "4b356542044f1267fcfc487a", +"snowflake": "4b356542044f1267fcfc487a", +"tsql": "4b356542044f1267fcfc487a" +} +], +[ +"type", +{ +"DuckDB": "ebc821a95b9286e22c2b26d0", +"None": "ebc821a95b9286e22c2b26d0", +"bigquery": "19a1a80ffc06169f32694de8", +"databricks": "ebc821a95b9286e22c2b26d0", +"duckdb": "ebc821a95b9286e22c2b26d0", +"generic": "ebc821a95b9286e22c2b26d0", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "ebc821a95b9286e22c2b26d0", +"postgres": "ebc821a95b9286e22c2b26d0", +"postgresql": "ebc821a95b9286e22c2b26d0", +"snowflake": "ebc821a95b9286e22c2b26d0", +"tsql": "ebc821a95b9286e22c2b26d0" +} +], +[ +"type", +{ +"DuckDB": "afc451102e0ebe7f507119b9", +"None": "afc451102e0ebe7f507119b9", +"bigquery": "afc451102e0ebe7f507119b9", +"databricks": "afc451102e0ebe7f507119b9", +"duckdb": "afc451102e0ebe7f507119b9", +"generic": "afc451102e0ebe7f507119b9", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "afc451102e0ebe7f507119b9", +"postgres": "afc451102e0ebe7f507119b9", +"postgresql": "afc451102e0ebe7f507119b9", +"snowflake": "afc451102e0ebe7f507119b9", +"tsql": "afc451102e0ebe7f507119b9" +} +], +[ +"type", +{ +"DuckDB": "74ed18299daa6faf5c9533e2", +"None": "74ed18299daa6faf5c9533e2", +"bigquery": "74ed18299daa6faf5c9533e2", +"databricks": "74ed18299daa6faf5c9533e2", +"duckdb": "74ed18299daa6faf5c9533e2", +"generic": "74ed18299daa6faf5c9533e2", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "74ed18299daa6faf5c9533e2", +"postgres": "74ed18299daa6faf5c9533e2", +"postgresql": "74ed18299daa6faf5c9533e2", +"snowflake": "74ed18299daa6faf5c9533e2", +"tsql": "74ed18299daa6faf5c9533e2" +} +], +[ +"type", +{ +"DuckDB": "f43dac38f34a1c0618a3f812", +"None": "f43dac38f34a1c0618a3f812", +"bigquery": "946d5ee30ab7469c57d850df", +"databricks": "f43dac38f34a1c0618a3f812", +"duckdb": "f43dac38f34a1c0618a3f812", +"generic": "f43dac38f34a1c0618a3f812", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "f43dac38f34a1c0618a3f812", +"postgres": "f43dac38f34a1c0618a3f812", +"postgresql": "f43dac38f34a1c0618a3f812", +"snowflake": "f43dac38f34a1c0618a3f812", +"tsql": "f43dac38f34a1c0618a3f812" +} +], +[ +"type", +{ +"DuckDB": "2bfa352725f9d8a91250f75e", +"None": "2bfa352725f9d8a91250f75e", +"bigquery": "2bfa352725f9d8a91250f75e", +"databricks": "2bfa352725f9d8a91250f75e", +"duckdb": "2bfa352725f9d8a91250f75e", +"generic": "2bfa352725f9d8a91250f75e", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "2bfa352725f9d8a91250f75e", +"postgres": "2bfa352725f9d8a91250f75e", +"postgresql": "2bfa352725f9d8a91250f75e", +"snowflake": "2bfa352725f9d8a91250f75e", +"tsql": "2bfa352725f9d8a91250f75e" +} +], +[ +"type", +{ +"DuckDB": "60b39a68a18438603dd5496d", +"None": "60b39a68a18438603dd5496d", +"bigquery": "60b39a68a18438603dd5496d", +"databricks": "60b39a68a18438603dd5496d", +"duckdb": "60b39a68a18438603dd5496d", +"generic": "60b39a68a18438603dd5496d", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "60b39a68a18438603dd5496d", +"postgres": "60b39a68a18438603dd5496d", +"postgresql": "60b39a68a18438603dd5496d", +"snowflake": "60b39a68a18438603dd5496d", +"tsql": "60b39a68a18438603dd5496d" +} +], +[ +"type", +{ +"DuckDB": "b1b23029bedaa16e2a6f8516", +"None": "b1b23029bedaa16e2a6f8516", +"bigquery": "b1b23029bedaa16e2a6f8516", +"databricks": "b1b23029bedaa16e2a6f8516", +"duckdb": "b1b23029bedaa16e2a6f8516", +"generic": "b1b23029bedaa16e2a6f8516", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "b1b23029bedaa16e2a6f8516", +"postgres": "b1b23029bedaa16e2a6f8516", +"postgresql": "b1b23029bedaa16e2a6f8516", +"snowflake": "b561884132dbe7e42b719110", +"tsql": "b1b23029bedaa16e2a6f8516" +} +], +[ +"type", +{ +"DuckDB": "0b9d9879e289ea9a6a3e3e70", +"None": "0b9d9879e289ea9a6a3e3e70", +"bigquery": "0b9d9879e289ea9a6a3e3e70", +"databricks": "0b9d9879e289ea9a6a3e3e70", +"duckdb": "0b9d9879e289ea9a6a3e3e70", +"generic": "0b9d9879e289ea9a6a3e3e70", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "0b9d9879e289ea9a6a3e3e70", +"postgres": "0b9d9879e289ea9a6a3e3e70", +"postgresql": "0b9d9879e289ea9a6a3e3e70", +"snowflake": "0b9d9879e289ea9a6a3e3e70", +"tsql": "0b9d9879e289ea9a6a3e3e70" +} +], +[ +"type", +{ +"DuckDB": "3f71ab5f3c1c040da96f2cec", +"None": "3f71ab5f3c1c040da96f2cec", +"bigquery": "3f71ab5f3c1c040da96f2cec", +"databricks": "3f71ab5f3c1c040da96f2cec", +"duckdb": "3f71ab5f3c1c040da96f2cec", +"generic": "3f71ab5f3c1c040da96f2cec", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "3f71ab5f3c1c040da96f2cec", +"postgres": "3f71ab5f3c1c040da96f2cec", +"postgresql": "3f71ab5f3c1c040da96f2cec", +"snowflake": "3f71ab5f3c1c040da96f2cec", +"tsql": "3f71ab5f3c1c040da96f2cec" +} +], +[ +"type", +{ +"DuckDB": "c6197f1da8168ac56d61807b", +"None": "c6197f1da8168ac56d61807b", +"bigquery": "c6197f1da8168ac56d61807b", +"databricks": "c6197f1da8168ac56d61807b", +"duckdb": "c6197f1da8168ac56d61807b", +"generic": "c6197f1da8168ac56d61807b", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "c6197f1da8168ac56d61807b", +"postgres": "c6197f1da8168ac56d61807b", +"postgresql": "c6197f1da8168ac56d61807b", +"snowflake": "c6197f1da8168ac56d61807b", +"tsql": "c6197f1da8168ac56d61807b" +} +], +[ +"type", +{ +"DuckDB": "38b2ec94bf02be40007ce525", +"None": "38b2ec94bf02be40007ce525", +"bigquery": "38b2ec94bf02be40007ce525", +"databricks": "38b2ec94bf02be40007ce525", +"duckdb": "38b2ec94bf02be40007ce525", +"generic": "38b2ec94bf02be40007ce525", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "38b2ec94bf02be40007ce525", +"postgres": "38b2ec94bf02be40007ce525", +"postgresql": "38b2ec94bf02be40007ce525", +"snowflake": "38b2ec94bf02be40007ce525", +"tsql": "38b2ec94bf02be40007ce525" +} +], +[ +"type", +{ +"DuckDB": "e998cd8f0f74af0526b75ff0", +"None": "e998cd8f0f74af0526b75ff0", +"bigquery": "a428302e4848ffe877284c84", +"databricks": "e998cd8f0f74af0526b75ff0", +"duckdb": "e998cd8f0f74af0526b75ff0", +"generic": "e998cd8f0f74af0526b75ff0", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "e998cd8f0f74af0526b75ff0", +"postgres": "e998cd8f0f74af0526b75ff0", +"postgresql": "e998cd8f0f74af0526b75ff0", +"snowflake": "652ff8b21f638eac8fdc46c5", +"tsql": "e998cd8f0f74af0526b75ff0" +} +], +[ +"type", +{ +"DuckDB": "58b79aaeb9587eafe21bc119", +"None": "58b79aaeb9587eafe21bc119", +"bigquery": "58b79aaeb9587eafe21bc119", +"databricks": "58b79aaeb9587eafe21bc119", +"duckdb": "58b79aaeb9587eafe21bc119", +"generic": "58b79aaeb9587eafe21bc119", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "58b79aaeb9587eafe21bc119", +"postgres": "58b79aaeb9587eafe21bc119", +"postgresql": "58b79aaeb9587eafe21bc119", +"snowflake": "58b79aaeb9587eafe21bc119", +"tsql": "58b79aaeb9587eafe21bc119" +} +], +[ +"type", +{ +"DuckDB": "776e4bf23c8ef10ffaceade2", +"None": "776e4bf23c8ef10ffaceade2", +"bigquery": "776e4bf23c8ef10ffaceade2", +"databricks": "776e4bf23c8ef10ffaceade2", +"duckdb": "776e4bf23c8ef10ffaceade2", +"generic": "776e4bf23c8ef10ffaceade2", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "776e4bf23c8ef10ffaceade2", +"postgres": "776e4bf23c8ef10ffaceade2", +"postgresql": "776e4bf23c8ef10ffaceade2", +"snowflake": "776e4bf23c8ef10ffaceade2", +"tsql": "776e4bf23c8ef10ffaceade2" +} +], +[ +"type", +{ +"DuckDB": "73d31c6e78cdc3b595b9c4e9", +"None": "73d31c6e78cdc3b595b9c4e9", +"bigquery": "73d31c6e78cdc3b595b9c4e9", +"databricks": "73d31c6e78cdc3b595b9c4e9", +"duckdb": "73d31c6e78cdc3b595b9c4e9", +"generic": "73d31c6e78cdc3b595b9c4e9", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "73d31c6e78cdc3b595b9c4e9", +"postgres": "73d31c6e78cdc3b595b9c4e9", +"postgresql": "73d31c6e78cdc3b595b9c4e9", +"snowflake": "73d31c6e78cdc3b595b9c4e9", +"tsql": "73d31c6e78cdc3b595b9c4e9" +} +], +[ +"type", +{ +"DuckDB": "57922064a7dc546cbb50e42b", +"None": "57922064a7dc546cbb50e42b", +"bigquery": "57922064a7dc546cbb50e42b", +"databricks": "57922064a7dc546cbb50e42b", +"duckdb": "57922064a7dc546cbb50e42b", +"generic": "57922064a7dc546cbb50e42b", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "57922064a7dc546cbb50e42b", +"postgres": "57922064a7dc546cbb50e42b", +"postgresql": "57922064a7dc546cbb50e42b", +"snowflake": "57922064a7dc546cbb50e42b", +"tsql": "57922064a7dc546cbb50e42b" +} +], +[ +"type", +{ +"DuckDB": "e408f2d8251e1675179187e6", +"None": "e408f2d8251e1675179187e6", +"bigquery": "e408f2d8251e1675179187e6", +"databricks": "e408f2d8251e1675179187e6", +"duckdb": "e408f2d8251e1675179187e6", +"generic": "e408f2d8251e1675179187e6", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "e408f2d8251e1675179187e6", +"postgres": "e408f2d8251e1675179187e6", +"postgresql": "e408f2d8251e1675179187e6", +"snowflake": "e408f2d8251e1675179187e6", +"tsql": "e408f2d8251e1675179187e6" +} +], +[ +"type", +{ +"DuckDB": "aab0389e2b5470136660bf8a", +"None": "aab0389e2b5470136660bf8a", +"bigquery": "c9b810639795a7bfab91b98d", +"databricks": "aab0389e2b5470136660bf8a", +"duckdb": "aab0389e2b5470136660bf8a", +"generic": "aab0389e2b5470136660bf8a", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "aab0389e2b5470136660bf8a", +"postgres": "aab0389e2b5470136660bf8a", +"postgresql": "aab0389e2b5470136660bf8a", +"snowflake": "97a20344d811fb77c7690863", +"tsql": "aab0389e2b5470136660bf8a" +} +], +[ +"type", +{ +"DuckDB": "5c528c7b4329aeb692ec6e94", +"None": "5c528c7b4329aeb692ec6e94", +"bigquery": "5c528c7b4329aeb692ec6e94", +"databricks": "5c528c7b4329aeb692ec6e94", +"duckdb": "5c528c7b4329aeb692ec6e94", +"generic": "5c528c7b4329aeb692ec6e94", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "5c528c7b4329aeb692ec6e94", +"postgres": "5c528c7b4329aeb692ec6e94", +"postgresql": "5c528c7b4329aeb692ec6e94", +"snowflake": "5c528c7b4329aeb692ec6e94", +"tsql": "5c528c7b4329aeb692ec6e94" +} +], +[ +"type", +{ +"DuckDB": "96ecb0bd0c27167bf4e31a08", +"None": "96ecb0bd0c27167bf4e31a08", +"bigquery": "96ecb0bd0c27167bf4e31a08", +"databricks": "96ecb0bd0c27167bf4e31a08", +"duckdb": "96ecb0bd0c27167bf4e31a08", +"generic": "96ecb0bd0c27167bf4e31a08", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "96ecb0bd0c27167bf4e31a08", +"postgres": "96ecb0bd0c27167bf4e31a08", +"postgresql": "96ecb0bd0c27167bf4e31a08", +"snowflake": "96ecb0bd0c27167bf4e31a08", +"tsql": "96ecb0bd0c27167bf4e31a08" +} +], +[ +"type", +{ +"DuckDB": "b46dfa976d5ba04f95bea32b", +"None": "b46dfa976d5ba04f95bea32b", +"bigquery": "68d2179839f17f0eb289d1aa", +"databricks": "b46dfa976d5ba04f95bea32b", +"duckdb": "b46dfa976d5ba04f95bea32b", +"generic": "b46dfa976d5ba04f95bea32b", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "b46dfa976d5ba04f95bea32b", +"postgres": "34dcdfe3e3afe6140e1353e0", +"postgresql": "34dcdfe3e3afe6140e1353e0", +"snowflake": "b46dfa976d5ba04f95bea32b", +"tsql": "1d8b945fd793ecdcacb90c21" +} +], +[ +"type", +{ +"DuckDB": "f8262a8fca64e4491f151610", +"None": "dee6957f9182718819d5f721", +"bigquery": "c9c3ab06d6a47f6501ca2f3f", +"databricks": "47f8ea982c36ab449140ac7a", +"duckdb": "f8262a8fca64e4491f151610", +"generic": "dee6957f9182718819d5f721", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "dee6957f9182718819d5f721", +"postgres": "5bc5cf0052fdc17435b19fc2", +"postgresql": "5bc5cf0052fdc17435b19fc2", +"snowflake": "f8262a8fca64e4491f151610", +"tsql": "dee6957f9182718819d5f721" +} +], +[ +"type", +{ +"DuckDB": "b694aa93969368381cb9d9bd", +"None": "b694aa93969368381cb9d9bd", +"bigquery": "df6620c838173adb34d41a29", +"databricks": "b694aa93969368381cb9d9bd", +"duckdb": "b694aa93969368381cb9d9bd", +"generic": "b694aa93969368381cb9d9bd", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "b694aa93969368381cb9d9bd", +"postgres": "b694aa93969368381cb9d9bd", +"postgresql": "b694aa93969368381cb9d9bd", +"snowflake": "58d5f123164e58c358315897", +"tsql": "b694aa93969368381cb9d9bd" +} +], +[ +"type", +{ +"DuckDB": "c50a316d091c821866e4bfba", +"None": "c50a316d091c821866e4bfba", +"bigquery": "c50a316d091c821866e4bfba", +"databricks": "c50a316d091c821866e4bfba", +"duckdb": "c50a316d091c821866e4bfba", +"generic": "c50a316d091c821866e4bfba", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "c50a316d091c821866e4bfba", +"postgres": "c50a316d091c821866e4bfba", +"postgresql": "c50a316d091c821866e4bfba", +"snowflake": "c50a316d091c821866e4bfba", +"tsql": "c50a316d091c821866e4bfba" +} +], +[ +"type", +{ +"DuckDB": "2a0e1cbf59d282b31816d003", +"None": "2a0e1cbf59d282b31816d003", +"bigquery": "a49cf160806465e17f3bb015", +"databricks": "a49cf160806465e17f3bb015", +"duckdb": "2a0e1cbf59d282b31816d003", +"generic": "2a0e1cbf59d282b31816d003", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "a49cf160806465e17f3bb015", +"postgres": "2a0e1cbf59d282b31816d003", +"postgresql": "2a0e1cbf59d282b31816d003", +"snowflake": "8cdd1c724939d35c854480a1", +"tsql": "2a0e1cbf59d282b31816d003" +} +], +[ +"type", +{ +"DuckDB": "2bfa352725f9d8a91250f75e", +"None": "2bfa352725f9d8a91250f75e", +"bigquery": "2bfa352725f9d8a91250f75e", +"databricks": "2bfa352725f9d8a91250f75e", +"duckdb": "2bfa352725f9d8a91250f75e", +"generic": "2bfa352725f9d8a91250f75e", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "2bfa352725f9d8a91250f75e", +"postgres": "2bfa352725f9d8a91250f75e", +"postgresql": "2bfa352725f9d8a91250f75e", +"snowflake": "2bfa352725f9d8a91250f75e", +"tsql": "2bfa352725f9d8a91250f75e" +} +], +[ +"type", +{ +"DuckDB": "401e8475dd39d667a86332fd", +"None": "401e8475dd39d667a86332fd", +"bigquery": "122a82cc999a6e522d790b87", +"databricks": "e33f1ebea03ff1cb2c6e78c4", +"duckdb": "401e8475dd39d667a86332fd", +"generic": "401e8475dd39d667a86332fd", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "401e8475dd39d667a86332fd", +"postgres": "401e8475dd39d667a86332fd", +"postgresql": "401e8475dd39d667a86332fd", +"snowflake": "5f8d9b6f22793dc26cf2fd62", +"tsql": "0bb39b405fb474593040f307" +} +], +[ +"type", +{ +"DuckDB": "4062ec81199547543ab068fb", +"None": "4062ec81199547543ab068fb", +"bigquery": "7009fc15fd2c35608ab16caf", +"databricks": "0739784ba4c53d23afd45a6b", +"duckdb": "4062ec81199547543ab068fb", +"generic": "4062ec81199547543ab068fb", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "4062ec81199547543ab068fb", +"postgres": "4062ec81199547543ab068fb", +"postgresql": "4062ec81199547543ab068fb", +"snowflake": "0739784ba4c53d23afd45a6b", +"tsql": "0739784ba4c53d23afd45a6b" +} +], +[ +"type", +{ +"DuckDB": "2bfa352725f9d8a91250f75e", +"None": "2bfa352725f9d8a91250f75e", +"bigquery": "2bfa352725f9d8a91250f75e", +"databricks": "2bfa352725f9d8a91250f75e", +"duckdb": "2bfa352725f9d8a91250f75e", +"generic": "2bfa352725f9d8a91250f75e", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "2bfa352725f9d8a91250f75e", +"postgres": "2bfa352725f9d8a91250f75e", +"postgresql": "2bfa352725f9d8a91250f75e", +"snowflake": "2bfa352725f9d8a91250f75e", +"tsql": "2bfa352725f9d8a91250f75e" +} +], +[ +"type", +{ +"DuckDB": "c344d36a6751b773df74ee3c", +"None": "87fed6659d6324c5ef0c6ee2", +"bigquery": "87fed6659d6324c5ef0c6ee2", +"databricks": "87fed6659d6324c5ef0c6ee2", +"duckdb": "c344d36a6751b773df74ee3c", +"generic": "87fed6659d6324c5ef0c6ee2", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "87fed6659d6324c5ef0c6ee2", +"postgres": "87fed6659d6324c5ef0c6ee2", +"postgresql": "87fed6659d6324c5ef0c6ee2", +"snowflake": "87fed6659d6324c5ef0c6ee2", +"tsql": "87fed6659d6324c5ef0c6ee2" +} +], +[ +"type", +{ +"DuckDB": "de89632e277dbc8c97115419", +"None": "de89632e277dbc8c97115419", +"bigquery": "de89632e277dbc8c97115419", +"databricks": "de89632e277dbc8c97115419", +"duckdb": "de89632e277dbc8c97115419", +"generic": "de89632e277dbc8c97115419", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "de89632e277dbc8c97115419", +"postgres": "de89632e277dbc8c97115419", +"postgresql": "de89632e277dbc8c97115419", +"snowflake": "4b356542044f1267fcfc487a", +"tsql": "de89632e277dbc8c97115419" +} +], +[ +"type", +{ +"DuckDB": "3147a9e06daa6de4a4df5abc", +"None": "3147a9e06daa6de4a4df5abc", +"bigquery": "f276e907770196606577c932", +"databricks": "3147a9e06daa6de4a4df5abc", +"duckdb": "3147a9e06daa6de4a4df5abc", +"generic": "3147a9e06daa6de4a4df5abc", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "3147a9e06daa6de4a4df5abc", +"postgres": "3147a9e06daa6de4a4df5abc", +"postgresql": "3147a9e06daa6de4a4df5abc", +"snowflake": "67b5874a2c569226c490211f", +"tsql": "3147a9e06daa6de4a4df5abc" +} +], +[ +"type", +{ +"DuckDB": "b2598e21f41a4625fa001e55", +"None": "b2598e21f41a4625fa001e55", +"bigquery": "b2598e21f41a4625fa001e55", +"databricks": "b2598e21f41a4625fa001e55", +"duckdb": "b2598e21f41a4625fa001e55", +"generic": "b2598e21f41a4625fa001e55", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "b2598e21f41a4625fa001e55", +"postgres": "b2598e21f41a4625fa001e55", +"postgresql": "b2598e21f41a4625fa001e55", +"snowflake": "b2598e21f41a4625fa001e55", +"tsql": "b2598e21f41a4625fa001e55" +} +], +[ +"type", +{ +"DuckDB": "8a7aa7fa75696327320e0add", +"None": "8a7aa7fa75696327320e0add", +"bigquery": "e62af34c2d31bc9ab880629e", +"databricks": "e62af34c2d31bc9ab880629e", +"duckdb": "8a7aa7fa75696327320e0add", +"generic": "8a7aa7fa75696327320e0add", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "e62af34c2d31bc9ab880629e", +"postgres": "8a7aa7fa75696327320e0add", +"postgresql": "8a7aa7fa75696327320e0add", +"snowflake": "8a7aa7fa75696327320e0add", +"tsql": "8a7aa7fa75696327320e0add" +} +], +[ +"type", +{ +"DuckDB": "d61c83ef8bfdf043fa672cb5", +"None": "d61c83ef8bfdf043fa672cb5", +"bigquery": "c9b810639795a7bfab91b98d", +"databricks": "d61c83ef8bfdf043fa672cb5", +"duckdb": "d61c83ef8bfdf043fa672cb5", +"generic": "d61c83ef8bfdf043fa672cb5", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "d61c83ef8bfdf043fa672cb5", +"postgres": "d61c83ef8bfdf043fa672cb5", +"postgresql": "d61c83ef8bfdf043fa672cb5", +"snowflake": "97a20344d811fb77c7690863", +"tsql": "d61c83ef8bfdf043fa672cb5" +} +], +[ +"type", +{ +"DuckDB": "aae2b1fe6f2d9807ecde412b", +"None": "aae2b1fe6f2d9807ecde412b", +"bigquery": "e1c36a5cdd2427ff2b089ac9", +"databricks": "aae2b1fe6f2d9807ecde412b", +"duckdb": "aae2b1fe6f2d9807ecde412b", +"generic": "aae2b1fe6f2d9807ecde412b", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "aae2b1fe6f2d9807ecde412b", +"postgres": "aae2b1fe6f2d9807ecde412b", +"postgresql": "aae2b1fe6f2d9807ecde412b", +"snowflake": "aae2b1fe6f2d9807ecde412b", +"tsql": "aae2b1fe6f2d9807ecde412b" +} +], +[ +"type", +{ +"DuckDB": "f7fca17b74cc50ae3de8c826", +"None": "f7fca17b74cc50ae3de8c826", +"bigquery": "f7fca17b74cc50ae3de8c826", +"databricks": "f7fca17b74cc50ae3de8c826", +"duckdb": "f7fca17b74cc50ae3de8c826", +"generic": "f7fca17b74cc50ae3de8c826", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "f7fca17b74cc50ae3de8c826", +"postgres": "f7fca17b74cc50ae3de8c826", +"postgresql": "f7fca17b74cc50ae3de8c826", +"snowflake": "55155766823b6a3a5e882fc2", +"tsql": "f7fca17b74cc50ae3de8c826" +} +], +[ +"type", +{ +"DuckDB": "95050a5e73c2bff179a785b7", +"None": "95050a5e73c2bff179a785b7", +"bigquery": "95050a5e73c2bff179a785b7", +"databricks": "95050a5e73c2bff179a785b7", +"duckdb": "95050a5e73c2bff179a785b7", +"generic": "95050a5e73c2bff179a785b7", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "95050a5e73c2bff179a785b7", +"postgres": "95050a5e73c2bff179a785b7", +"postgresql": "95050a5e73c2bff179a785b7", +"snowflake": "95050a5e73c2bff179a785b7", +"tsql": "95050a5e73c2bff179a785b7" +} +], +[ +"type", +{ +"DuckDB": "ebc821a95b9286e22c2b26d0", +"None": "ebc821a95b9286e22c2b26d0", +"bigquery": "19a1a80ffc06169f32694de8", +"databricks": "ebc821a95b9286e22c2b26d0", +"duckdb": "ebc821a95b9286e22c2b26d0", +"generic": "ebc821a95b9286e22c2b26d0", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "ebc821a95b9286e22c2b26d0", +"postgres": "ebc821a95b9286e22c2b26d0", +"postgresql": "ebc821a95b9286e22c2b26d0", +"snowflake": "ebc821a95b9286e22c2b26d0", +"tsql": "ebc821a95b9286e22c2b26d0" +} +], +[ +"type", +{ +"DuckDB": "e46d4be44ab9e500e9190d26", +"None": "e46d4be44ab9e500e9190d26", +"bigquery": "e6ffdece2977be55da73b59a", +"databricks": "e46d4be44ab9e500e9190d26", +"duckdb": "e46d4be44ab9e500e9190d26", +"generic": "e46d4be44ab9e500e9190d26", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "e46d4be44ab9e500e9190d26", +"postgres": "e46d4be44ab9e500e9190d26", +"postgresql": "e46d4be44ab9e500e9190d26", +"snowflake": "e46d4be44ab9e500e9190d26", +"tsql": "e46d4be44ab9e500e9190d26" +} +], +[ +"type", +{ +"DuckDB": "314ed506f24e92300a425780", +"None": "314ed506f24e92300a425780", +"bigquery": "314ed506f24e92300a425780", +"databricks": "314ed506f24e92300a425780", +"duckdb": "314ed506f24e92300a425780", +"generic": "314ed506f24e92300a425780", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "314ed506f24e92300a425780", +"postgres": "314ed506f24e92300a425780", +"postgresql": "314ed506f24e92300a425780", +"snowflake": "314ed506f24e92300a425780", +"tsql": "314ed506f24e92300a425780" +} +], +[ +"type", +{ +"DuckDB": "f4c43a87a78970bca1f88b09", +"None": "f4c43a87a78970bca1f88b09", +"bigquery": "f4c43a87a78970bca1f88b09", +"databricks": "f4c43a87a78970bca1f88b09", +"duckdb": "f4c43a87a78970bca1f88b09", +"generic": "f4c43a87a78970bca1f88b09", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "f4c43a87a78970bca1f88b09", +"postgres": "f4c43a87a78970bca1f88b09", +"postgresql": "f4c43a87a78970bca1f88b09", +"snowflake": "652ff8b21f638eac8fdc46c5", +"tsql": "f4c43a87a78970bca1f88b09" +} +], +[ +"type", +{ +"DuckDB": "f8d53ecf4ba59d519bb15d38", +"None": "f8d53ecf4ba59d519bb15d38", +"bigquery": "f8d53ecf4ba59d519bb15d38", +"databricks": "f8d53ecf4ba59d519bb15d38", +"duckdb": "f8d53ecf4ba59d519bb15d38", +"generic": "f8d53ecf4ba59d519bb15d38", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "f8d53ecf4ba59d519bb15d38", +"postgres": "f8d53ecf4ba59d519bb15d38", +"postgresql": "f8d53ecf4ba59d519bb15d38", +"snowflake": "f8d53ecf4ba59d519bb15d38", +"tsql": "f8d53ecf4ba59d519bb15d38" +} +], +[ +"type", +{ +"DuckDB": "d6e37cd37419bfb26e09b080", +"None": "d6e37cd37419bfb26e09b080", +"bigquery": "d6e37cd37419bfb26e09b080", +"databricks": "d6e37cd37419bfb26e09b080", +"duckdb": "d6e37cd37419bfb26e09b080", +"generic": "d6e37cd37419bfb26e09b080", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "d6e37cd37419bfb26e09b080", +"postgres": "d6e37cd37419bfb26e09b080", +"postgresql": "d6e37cd37419bfb26e09b080", +"snowflake": "d6e37cd37419bfb26e09b080", +"tsql": "d6e37cd37419bfb26e09b080" +} +], +[ +"type", +{ +"DuckDB": "94f6df33eccb97170eccb01b", +"None": "94f6df33eccb97170eccb01b", +"bigquery": "94f6df33eccb97170eccb01b", +"databricks": "94f6df33eccb97170eccb01b", +"duckdb": "94f6df33eccb97170eccb01b", +"generic": "94f6df33eccb97170eccb01b", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "94f6df33eccb97170eccb01b", +"postgres": "94f6df33eccb97170eccb01b", +"postgresql": "94f6df33eccb97170eccb01b", +"snowflake": "94f6df33eccb97170eccb01b", +"tsql": "94f6df33eccb97170eccb01b" +} +], +[ +"type", +{ +"DuckDB": "8c0b6775b8364e21d86e6e85", +"None": "8c0b6775b8364e21d86e6e85", +"bigquery": "8c0b6775b8364e21d86e6e85", +"databricks": "8c0b6775b8364e21d86e6e85", +"duckdb": "8c0b6775b8364e21d86e6e85", +"generic": "8c0b6775b8364e21d86e6e85", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "8c0b6775b8364e21d86e6e85", +"postgres": "8c0b6775b8364e21d86e6e85", +"postgresql": "8c0b6775b8364e21d86e6e85", +"snowflake": "8c0b6775b8364e21d86e6e85", +"tsql": "8c0b6775b8364e21d86e6e85" +} +], +[ +"type", +{ +"DuckDB": "2038903a8b2174e3b3525f45", +"None": "2038903a8b2174e3b3525f45", +"bigquery": "2038903a8b2174e3b3525f45", +"databricks": "2038903a8b2174e3b3525f45", +"duckdb": "2038903a8b2174e3b3525f45", +"generic": "2038903a8b2174e3b3525f45", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "2038903a8b2174e3b3525f45", +"postgres": "2038903a8b2174e3b3525f45", +"postgresql": "2038903a8b2174e3b3525f45", +"snowflake": "2038903a8b2174e3b3525f45", +"tsql": "2038903a8b2174e3b3525f45" +} +], +[ +"type", +{ +"DuckDB": "57a219193ee01aa40a7a339d", +"None": "1cff449f8adc98f1234ffeec", +"bigquery": "c49aa38b33ba6204f42571c8", +"databricks": "1cff449f8adc98f1234ffeec", +"duckdb": "57a219193ee01aa40a7a339d", +"generic": "1cff449f8adc98f1234ffeec", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "1cff449f8adc98f1234ffeec", +"postgres": "1cff449f8adc98f1234ffeec", +"postgresql": "1cff449f8adc98f1234ffeec", +"snowflake": "bfb659237d70eae4d07a6d10", +"tsql": "1cff449f8adc98f1234ffeec" +} +], +[ +"type", +{ +"DuckDB": "e0faa139ea3b65b1356bd333", +"None": "e0faa139ea3b65b1356bd333", +"bigquery": "e0faa139ea3b65b1356bd333", +"databricks": "e0faa139ea3b65b1356bd333", +"duckdb": "e0faa139ea3b65b1356bd333", +"generic": "e0faa139ea3b65b1356bd333", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "e0faa139ea3b65b1356bd333", +"postgres": "e0faa139ea3b65b1356bd333", +"postgresql": "e0faa139ea3b65b1356bd333", +"snowflake": "e0faa139ea3b65b1356bd333", +"tsql": "e0faa139ea3b65b1356bd333" +} +], +[ +"type", +{ +"DuckDB": "42d4a23d9a52e79d0c3458d3", +"None": "a3acd7ba35e81a800f967bd3", +"bigquery": "3c0719ca5c83e0a20d0b0b42", +"databricks": "a3acd7ba35e81a800f967bd3", +"duckdb": "42d4a23d9a52e79d0c3458d3", +"generic": "a3acd7ba35e81a800f967bd3", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "a3acd7ba35e81a800f967bd3", +"postgres": "a3acd7ba35e81a800f967bd3", +"postgresql": "a3acd7ba35e81a800f967bd3", +"snowflake": "a3acd7ba35e81a800f967bd3", +"tsql": "a3acd7ba35e81a800f967bd3" +} +], +[ +"type", +{ +"DuckDB": "2795ccedbfd3fa0bed5fdfcd", +"None": "2795ccedbfd3fa0bed5fdfcd", +"bigquery": "2795ccedbfd3fa0bed5fdfcd", +"databricks": "2795ccedbfd3fa0bed5fdfcd", +"duckdb": "2795ccedbfd3fa0bed5fdfcd", +"generic": "2795ccedbfd3fa0bed5fdfcd", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "2795ccedbfd3fa0bed5fdfcd", +"postgres": "2795ccedbfd3fa0bed5fdfcd", +"postgresql": "2795ccedbfd3fa0bed5fdfcd", +"snowflake": "2795ccedbfd3fa0bed5fdfcd", +"tsql": "2795ccedbfd3fa0bed5fdfcd" +} +], +[ +"type", +{ +"DuckDB": "5abf4ec799a2ec32fb10da7e", +"None": "de89632e277dbc8c97115419", +"bigquery": "de89632e277dbc8c97115419", +"databricks": "de89632e277dbc8c97115419", +"duckdb": "5abf4ec799a2ec32fb10da7e", +"generic": "de89632e277dbc8c97115419", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "de89632e277dbc8c97115419", +"postgres": "de89632e277dbc8c97115419", +"postgresql": "de89632e277dbc8c97115419", +"snowflake": "4b356542044f1267fcfc487a", +"tsql": "de89632e277dbc8c97115419" +} +], +[ +"type", +{ +"DuckDB": "4a014523269fae92f3ad421a", +"None": "4a014523269fae92f3ad421a", +"bigquery": "4a014523269fae92f3ad421a", +"databricks": "4a014523269fae92f3ad421a", +"duckdb": "4a014523269fae92f3ad421a", +"generic": "4a014523269fae92f3ad421a", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "4a014523269fae92f3ad421a", +"postgres": "4a014523269fae92f3ad421a", +"postgresql": "4a014523269fae92f3ad421a", +"snowflake": "4a014523269fae92f3ad421a", +"tsql": "4a014523269fae92f3ad421a" +} +], +[ +"type", +{ +"DuckDB": "684469f7d4198e43e63072ce", +"None": "684469f7d4198e43e63072ce", +"bigquery": "684469f7d4198e43e63072ce", +"databricks": "684469f7d4198e43e63072ce", +"duckdb": "684469f7d4198e43e63072ce", +"generic": "684469f7d4198e43e63072ce", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "684469f7d4198e43e63072ce", +"postgres": "684469f7d4198e43e63072ce", +"postgresql": "684469f7d4198e43e63072ce", +"snowflake": "684469f7d4198e43e63072ce", +"tsql": "684469f7d4198e43e63072ce" +} +], +[ +"type", +{ +"DuckDB": "e998cd8f0f74af0526b75ff0", +"None": "e998cd8f0f74af0526b75ff0", +"bigquery": "a428302e4848ffe877284c84", +"databricks": "e998cd8f0f74af0526b75ff0", +"duckdb": "e998cd8f0f74af0526b75ff0", +"generic": "e998cd8f0f74af0526b75ff0", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "e998cd8f0f74af0526b75ff0", +"postgres": "e998cd8f0f74af0526b75ff0", +"postgresql": "e998cd8f0f74af0526b75ff0", +"snowflake": "652ff8b21f638eac8fdc46c5", +"tsql": "e998cd8f0f74af0526b75ff0" +} +], +[ +"type", +{ +"DuckDB": "110327dc45eac0e8d54a96dc", +"None": "110327dc45eac0e8d54a96dc", +"bigquery": "1a804f317a3e9a0016925b04", +"databricks": "1a804f317a3e9a0016925b04", +"duckdb": "110327dc45eac0e8d54a96dc", +"generic": "110327dc45eac0e8d54a96dc", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "1a804f317a3e9a0016925b04", +"postgres": "110327dc45eac0e8d54a96dc", +"postgresql": "110327dc45eac0e8d54a96dc", +"snowflake": "110327dc45eac0e8d54a96dc", +"tsql": "110327dc45eac0e8d54a96dc" +} +], +[ +"type", +{ +"DuckDB": "5abf4ec799a2ec32fb10da7e", +"None": "5abf4ec799a2ec32fb10da7e", +"bigquery": "5abf4ec799a2ec32fb10da7e", +"databricks": "5abf4ec799a2ec32fb10da7e", +"duckdb": "5abf4ec799a2ec32fb10da7e", +"generic": "5abf4ec799a2ec32fb10da7e", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "5abf4ec799a2ec32fb10da7e", +"postgres": "5abf4ec799a2ec32fb10da7e", +"postgresql": "5abf4ec799a2ec32fb10da7e", +"snowflake": "a5656d70e208254d1d3e9b4f", +"tsql": "5abf4ec799a2ec32fb10da7e" +} +], +[ +"type", +{ +"DuckDB": "f7fca17b74cc50ae3de8c826", +"None": "f7fca17b74cc50ae3de8c826", +"bigquery": "f7fca17b74cc50ae3de8c826", +"databricks": "f7fca17b74cc50ae3de8c826", +"duckdb": "f7fca17b74cc50ae3de8c826", +"generic": "f7fca17b74cc50ae3de8c826", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "f7fca17b74cc50ae3de8c826", +"postgres": "f7fca17b74cc50ae3de8c826", +"postgresql": "f7fca17b74cc50ae3de8c826", +"snowflake": "55155766823b6a3a5e882fc2", +"tsql": "f7fca17b74cc50ae3de8c826" +} +], +[ +"type", +{ +"DuckDB": "4d02ddd0ab80d0d46bf48a5f", +"None": "4d02ddd0ab80d0d46bf48a5f", +"bigquery": "4d02ddd0ab80d0d46bf48a5f", +"databricks": "4d02ddd0ab80d0d46bf48a5f", +"duckdb": "4d02ddd0ab80d0d46bf48a5f", +"generic": "4d02ddd0ab80d0d46bf48a5f", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "4d02ddd0ab80d0d46bf48a5f", +"postgres": "4d02ddd0ab80d0d46bf48a5f", +"postgresql": "4d02ddd0ab80d0d46bf48a5f", +"snowflake": "4d02ddd0ab80d0d46bf48a5f", +"tsql": "4d02ddd0ab80d0d46bf48a5f" +} +], +[ +"type", +{ +"DuckDB": "0ca1be8f7d61ca627e620450", +"None": "0ca1be8f7d61ca627e620450", +"bigquery": "e1c36a5cdd2427ff2b089ac9", +"databricks": "0ca1be8f7d61ca627e620450", +"duckdb": "0ca1be8f7d61ca627e620450", +"generic": "0ca1be8f7d61ca627e620450", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "0ca1be8f7d61ca627e620450", +"postgres": "0ca1be8f7d61ca627e620450", +"postgresql": "0ca1be8f7d61ca627e620450", +"snowflake": "18db5afe2c1e80d1ee652b54", +"tsql": "0ca1be8f7d61ca627e620450" +} +], +[ +"type", +{ +"DuckDB": "c50a316d091c821866e4bfba", +"None": "c50a316d091c821866e4bfba", +"bigquery": "c50a316d091c821866e4bfba", +"databricks": "c50a316d091c821866e4bfba", +"duckdb": "c50a316d091c821866e4bfba", +"generic": "c50a316d091c821866e4bfba", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "c50a316d091c821866e4bfba", +"postgres": "c50a316d091c821866e4bfba", +"postgresql": "c50a316d091c821866e4bfba", +"snowflake": "c50a316d091c821866e4bfba", +"tsql": "c50a316d091c821866e4bfba" +} +], +[ +"type", +{ +"DuckDB": "d5af64f521c46f0f5c6d1ad0", +"None": "d5af64f521c46f0f5c6d1ad0", +"bigquery": "d5af64f521c46f0f5c6d1ad0", +"databricks": "d5af64f521c46f0f5c6d1ad0", +"duckdb": "d5af64f521c46f0f5c6d1ad0", +"generic": "d5af64f521c46f0f5c6d1ad0", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "d5af64f521c46f0f5c6d1ad0", +"postgres": "d5af64f521c46f0f5c6d1ad0", +"postgresql": "d5af64f521c46f0f5c6d1ad0", +"snowflake": "d5af64f521c46f0f5c6d1ad0", +"tsql": "d5af64f521c46f0f5c6d1ad0" +} +], +[ +"type", +{ +"DuckDB": "38e28682c0f47e13e642ab1c", +"None": "38e28682c0f47e13e642ab1c", +"bigquery": "96315ac85cc1ab3d0ea56ca2", +"databricks": "6e4f718d80b641c205a88635", +"duckdb": "38e28682c0f47e13e642ab1c", +"generic": "38e28682c0f47e13e642ab1c", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "25f9faed41d5d23ca3fa8175", +"postgres": "38e28682c0f47e13e642ab1c", +"postgresql": "38e28682c0f47e13e642ab1c", +"snowflake": "41cf14d12db9a99ffd9a4514", +"tsql": "38e28682c0f47e13e642ab1c" +} +], +[ +"type", +{ +"DuckDB": "0a735e1254c48785122ee5a3", +"None": "558da38ec4d9d5d6c72f60cf", +"bigquery": "e6ffdece2977be55da73b59a", +"databricks": "558da38ec4d9d5d6c72f60cf", +"duckdb": "0a735e1254c48785122ee5a3", +"generic": "558da38ec4d9d5d6c72f60cf", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "558da38ec4d9d5d6c72f60cf", +"postgres": "558da38ec4d9d5d6c72f60cf", +"postgresql": "558da38ec4d9d5d6c72f60cf", +"snowflake": "558da38ec4d9d5d6c72f60cf", +"tsql": "558da38ec4d9d5d6c72f60cf" +} +], +[ +"type", +{ +"DuckDB": "c16b4b4f382469fb186a9022", +"None": "c16b4b4f382469fb186a9022", +"bigquery": "c16b4b4f382469fb186a9022", +"databricks": "c16b4b4f382469fb186a9022", +"duckdb": "c16b4b4f382469fb186a9022", +"generic": "c16b4b4f382469fb186a9022", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "c16b4b4f382469fb186a9022", +"postgres": "c16b4b4f382469fb186a9022", +"postgresql": "c16b4b4f382469fb186a9022", +"snowflake": "c16b4b4f382469fb186a9022", +"tsql": "c16b4b4f382469fb186a9022" +} +], +[ +"type", +{ +"DuckDB": "38b2ec94bf02be40007ce525", +"None": "38b2ec94bf02be40007ce525", +"bigquery": "38b2ec94bf02be40007ce525", +"databricks": "38b2ec94bf02be40007ce525", +"duckdb": "38b2ec94bf02be40007ce525", +"generic": "38b2ec94bf02be40007ce525", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "38b2ec94bf02be40007ce525", +"postgres": "38b2ec94bf02be40007ce525", +"postgresql": "38b2ec94bf02be40007ce525", +"snowflake": "38b2ec94bf02be40007ce525", +"tsql": "38b2ec94bf02be40007ce525" +} +], +[ +"type", +{ +"DuckDB": "9e4a50a8aab648a9737f7d0c", +"None": "9e4a50a8aab648a9737f7d0c", +"bigquery": "d9a4e245156e760303573500", +"databricks": "9e4a50a8aab648a9737f7d0c", +"duckdb": "9e4a50a8aab648a9737f7d0c", +"generic": "9e4a50a8aab648a9737f7d0c", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "9e4a50a8aab648a9737f7d0c", +"postgres": "36d29258901a4d8c296baa68", +"postgresql": "36d29258901a4d8c296baa68", +"snowflake": "9e4a50a8aab648a9737f7d0c", +"tsql": "355e032cc5c0f24695836b3d" +} +], +[ +"type", +{ +"DuckDB": "f43dac38f34a1c0618a3f812", +"None": "f43dac38f34a1c0618a3f812", +"bigquery": "946d5ee30ab7469c57d850df", +"databricks": "f43dac38f34a1c0618a3f812", +"duckdb": "f43dac38f34a1c0618a3f812", +"generic": "f43dac38f34a1c0618a3f812", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "f43dac38f34a1c0618a3f812", +"postgres": "f43dac38f34a1c0618a3f812", +"postgresql": "f43dac38f34a1c0618a3f812", +"snowflake": "f43dac38f34a1c0618a3f812", +"tsql": "f43dac38f34a1c0618a3f812" +} +], +[ +"type", +{ +"DuckDB": "e8605878c6fffc044556a858", +"None": "e8605878c6fffc044556a858", +"bigquery": "e8605878c6fffc044556a858", +"databricks": "e8605878c6fffc044556a858", +"duckdb": "e8605878c6fffc044556a858", +"generic": "e8605878c6fffc044556a858", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "e8605878c6fffc044556a858", +"postgres": "e8605878c6fffc044556a858", +"postgresql": "e8605878c6fffc044556a858", +"snowflake": "e8605878c6fffc044556a858", +"tsql": "e8605878c6fffc044556a858" +} +], +[ +"type", +{ +"DuckDB": "e8ef65ce7616ceeafffe41f6", +"None": "e8ef65ce7616ceeafffe41f6", +"bigquery": "e8ef65ce7616ceeafffe41f6", +"databricks": "e8ef65ce7616ceeafffe41f6", +"duckdb": "e8ef65ce7616ceeafffe41f6", +"generic": "e8ef65ce7616ceeafffe41f6", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "e8ef65ce7616ceeafffe41f6", +"postgres": "e8ef65ce7616ceeafffe41f6", +"postgresql": "e8ef65ce7616ceeafffe41f6", +"snowflake": "e8ef65ce7616ceeafffe41f6", +"tsql": "e8ef65ce7616ceeafffe41f6" +} +], +[ +"type", +{ +"DuckDB": "77ffdb80029bd6e2cca768ad", +"None": "77ffdb80029bd6e2cca768ad", +"bigquery": "77ffdb80029bd6e2cca768ad", +"databricks": "77ffdb80029bd6e2cca768ad", +"duckdb": "77ffdb80029bd6e2cca768ad", +"generic": "77ffdb80029bd6e2cca768ad", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "77ffdb80029bd6e2cca768ad", +"postgres": "77ffdb80029bd6e2cca768ad", +"postgresql": "77ffdb80029bd6e2cca768ad", +"snowflake": "77ffdb80029bd6e2cca768ad", +"tsql": "77ffdb80029bd6e2cca768ad" +} +], +[ +"type", +{ +"DuckDB": "c4346d0257336219f1d26890", +"None": "c4346d0257336219f1d26890", +"bigquery": "b5c4d5044b2a6e70633f0d0a", +"databricks": "c4346d0257336219f1d26890", +"duckdb": "c4346d0257336219f1d26890", +"generic": "c4346d0257336219f1d26890", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "c4346d0257336219f1d26890", +"postgres": "c4346d0257336219f1d26890", +"postgresql": "c4346d0257336219f1d26890", +"snowflake": "4e24a80b20b9dee0cbbfac17", +"tsql": "c4346d0257336219f1d26890" +} +], +[ +"type", +{ +"DuckDB": "70fb4728c3adcf6dbe4975d5", +"None": "70fb4728c3adcf6dbe4975d5", +"bigquery": "70fb4728c3adcf6dbe4975d5", +"databricks": "70fb4728c3adcf6dbe4975d5", +"duckdb": "70fb4728c3adcf6dbe4975d5", +"generic": "70fb4728c3adcf6dbe4975d5", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "70fb4728c3adcf6dbe4975d5", +"postgres": "70fb4728c3adcf6dbe4975d5", +"postgresql": "70fb4728c3adcf6dbe4975d5", +"snowflake": "70fb4728c3adcf6dbe4975d5", +"tsql": "70fb4728c3adcf6dbe4975d5" +} +], +[ +"type", +{ +"DuckDB": "3e611643f0beab4953c4e09b", +"None": "3e611643f0beab4953c4e09b", +"bigquery": "2a0918be53051fe629d9ff8f", +"databricks": "3e611643f0beab4953c4e09b", +"duckdb": "3e611643f0beab4953c4e09b", +"generic": "3e611643f0beab4953c4e09b", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "3e611643f0beab4953c4e09b", +"postgres": "3e611643f0beab4953c4e09b", +"postgresql": "3e611643f0beab4953c4e09b", +"snowflake": "3e611643f0beab4953c4e09b", +"tsql": "3e611643f0beab4953c4e09b" +} +], +[ +"type", +{ +"DuckDB": "776e4bf23c8ef10ffaceade2", +"None": "776e4bf23c8ef10ffaceade2", +"bigquery": "776e4bf23c8ef10ffaceade2", +"databricks": "776e4bf23c8ef10ffaceade2", +"duckdb": "776e4bf23c8ef10ffaceade2", +"generic": "776e4bf23c8ef10ffaceade2", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "776e4bf23c8ef10ffaceade2", +"postgres": "776e4bf23c8ef10ffaceade2", +"postgresql": "776e4bf23c8ef10ffaceade2", +"snowflake": "776e4bf23c8ef10ffaceade2", +"tsql": "776e4bf23c8ef10ffaceade2" +} +], +[ +"type", +{ +"DuckDB": "3915f3f73328f0838497b2d5", +"None": "3915f3f73328f0838497b2d5", +"bigquery": "946d5ee30ab7469c57d850df", +"databricks": "3915f3f73328f0838497b2d5", +"duckdb": "3915f3f73328f0838497b2d5", +"generic": "3915f3f73328f0838497b2d5", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "3915f3f73328f0838497b2d5", +"postgres": "3915f3f73328f0838497b2d5", +"postgresql": "3915f3f73328f0838497b2d5", +"snowflake": "f43dac38f34a1c0618a3f812", +"tsql": "3915f3f73328f0838497b2d5" +} +], +[ +"type", +{ +"DuckDB": "5abf4ec799a2ec32fb10da7e", +"None": "5abf4ec799a2ec32fb10da7e", +"bigquery": "5abf4ec799a2ec32fb10da7e", +"databricks": "5abf4ec799a2ec32fb10da7e", +"duckdb": "5abf4ec799a2ec32fb10da7e", +"generic": "5abf4ec799a2ec32fb10da7e", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "5abf4ec799a2ec32fb10da7e", +"postgres": "5abf4ec799a2ec32fb10da7e", +"postgresql": "5abf4ec799a2ec32fb10da7e", +"snowflake": "a5656d70e208254d1d3e9b4f", +"tsql": "5abf4ec799a2ec32fb10da7e" +} +], +[ +"type", +{ +"DuckDB": "eed0645c1e86fa1a6e35ccaa", +"None": "eed0645c1e86fa1a6e35ccaa", +"bigquery": "013a8446f043affffcf194f8", +"databricks": "eed0645c1e86fa1a6e35ccaa", +"duckdb": "eed0645c1e86fa1a6e35ccaa", +"generic": "eed0645c1e86fa1a6e35ccaa", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "eed0645c1e86fa1a6e35ccaa", +"postgres": "eed0645c1e86fa1a6e35ccaa", +"postgresql": "eed0645c1e86fa1a6e35ccaa", +"snowflake": "97a20344d811fb77c7690863", +"tsql": "eed0645c1e86fa1a6e35ccaa" +} +], +[ +"type", +{ +"DuckDB": "c50a316d091c821866e4bfba", +"None": "c50a316d091c821866e4bfba", +"bigquery": "c50a316d091c821866e4bfba", +"databricks": "c50a316d091c821866e4bfba", +"duckdb": "c50a316d091c821866e4bfba", +"generic": "c50a316d091c821866e4bfba", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "c50a316d091c821866e4bfba", +"postgres": "c50a316d091c821866e4bfba", +"postgresql": "c50a316d091c821866e4bfba", +"snowflake": "c50a316d091c821866e4bfba", +"tsql": "c50a316d091c821866e4bfba" +} +], +[ +"type", +{ +"DuckDB": "962ea05bab624c1f8c259a65", +"None": "962ea05bab624c1f8c259a65", +"bigquery": "962ea05bab624c1f8c259a65", +"databricks": "962ea05bab624c1f8c259a65", +"duckdb": "962ea05bab624c1f8c259a65", +"generic": "962ea05bab624c1f8c259a65", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "962ea05bab624c1f8c259a65", +"postgres": "962ea05bab624c1f8c259a65", +"postgresql": "962ea05bab624c1f8c259a65", +"snowflake": "962ea05bab624c1f8c259a65", +"tsql": "962ea05bab624c1f8c259a65" +} +], +[ +"type", +{ +"DuckDB": "207acc46dcc150502155f4a3", +"None": "d638c2852078bf3facb9dc9e", +"bigquery": "285a15e7c9efb8c0d32d6070", +"databricks": "d638c2852078bf3facb9dc9e", +"duckdb": "207acc46dcc150502155f4a3", +"generic": "d638c2852078bf3facb9dc9e", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "6c03a3450ea4742ee7396e3c", +"postgres": "6c49aec265f259dd95b5310e", +"postgresql": "6c49aec265f259dd95b5310e", +"snowflake": "ef2c05747b795f92c0b523ee", +"tsql": "2954e90d1d02f8a24fb095ea" +} +], +[ +"type", +{ +"DuckDB": "9d006c5299feb04426ce31ac", +"None": "e2879cf4770e7f48d2dd704a", +"bigquery": "c9b810639795a7bfab91b98d", +"databricks": "e2879cf4770e7f48d2dd704a", +"duckdb": "9d006c5299feb04426ce31ac", +"generic": "e2879cf4770e7f48d2dd704a", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "e2879cf4770e7f48d2dd704a", +"postgres": "e2879cf4770e7f48d2dd704a", +"postgresql": "e2879cf4770e7f48d2dd704a", +"snowflake": "97a20344d811fb77c7690863", +"tsql": "e2879cf4770e7f48d2dd704a" +} +], +[ +"type", +{ +"DuckDB": "1eb7fb4e8cf75773c5573562", +"None": "1eb7fb4e8cf75773c5573562", +"bigquery": "c9b810639795a7bfab91b98d", +"databricks": "1eb7fb4e8cf75773c5573562", +"duckdb": "1eb7fb4e8cf75773c5573562", +"generic": "1eb7fb4e8cf75773c5573562", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "1eb7fb4e8cf75773c5573562", +"postgres": "1eb7fb4e8cf75773c5573562", +"postgresql": "1eb7fb4e8cf75773c5573562", +"snowflake": "97a20344d811fb77c7690863", +"tsql": "1eb7fb4e8cf75773c5573562" +} +], +[ +"type", +{ +"DuckDB": "6a726882dbf443e39240fc33", +"None": "6a726882dbf443e39240fc33", +"bigquery": "6a726882dbf443e39240fc33", +"databricks": "6a726882dbf443e39240fc33", +"duckdb": "6a726882dbf443e39240fc33", +"generic": "6a726882dbf443e39240fc33", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "6a726882dbf443e39240fc33", +"postgres": "6a726882dbf443e39240fc33", +"postgresql": "6a726882dbf443e39240fc33", +"snowflake": "6a726882dbf443e39240fc33", +"tsql": "6a726882dbf443e39240fc33" +} +], +[ +"type", +{ +"DuckDB": "c4860fb394ecca5e4515f1c9", +"None": "c4860fb394ecca5e4515f1c9", +"bigquery": "c4860fb394ecca5e4515f1c9", +"databricks": "c4860fb394ecca5e4515f1c9", +"duckdb": "c4860fb394ecca5e4515f1c9", +"generic": "c4860fb394ecca5e4515f1c9", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "c4860fb394ecca5e4515f1c9", +"postgres": "c4860fb394ecca5e4515f1c9", +"postgresql": "c4860fb394ecca5e4515f1c9", +"snowflake": "c4860fb394ecca5e4515f1c9", +"tsql": "c4860fb394ecca5e4515f1c9" +} +], +[ +"type", +{ +"DuckDB": "363159f251e264604338e690", +"None": "363159f251e264604338e690", +"bigquery": "363159f251e264604338e690", +"databricks": "363159f251e264604338e690", +"duckdb": "363159f251e264604338e690", +"generic": "363159f251e264604338e690", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "363159f251e264604338e690", +"postgres": "363159f251e264604338e690", +"postgresql": "363159f251e264604338e690", +"snowflake": "363159f251e264604338e690", +"tsql": "363159f251e264604338e690" +} +], +[ +"type", +{ +"DuckDB": "fe1d4d12e4b12d78f4ce545d", +"None": "fe1d4d12e4b12d78f4ce545d", +"bigquery": "fe1d4d12e4b12d78f4ce545d", +"databricks": "fe1d4d12e4b12d78f4ce545d", +"duckdb": "fe1d4d12e4b12d78f4ce545d", +"generic": "fe1d4d12e4b12d78f4ce545d", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "fe1d4d12e4b12d78f4ce545d", +"postgres": "fe1d4d12e4b12d78f4ce545d", +"postgresql": "fe1d4d12e4b12d78f4ce545d", +"snowflake": "fe1d4d12e4b12d78f4ce545d", +"tsql": "fe1d4d12e4b12d78f4ce545d" +} +], +[ +"type", +{ +"DuckDB": "5829c1427d562e21c1ed4dfe", +"None": "5829c1427d562e21c1ed4dfe", +"bigquery": "5829c1427d562e21c1ed4dfe", +"databricks": "5829c1427d562e21c1ed4dfe", +"duckdb": "5829c1427d562e21c1ed4dfe", +"generic": "5829c1427d562e21c1ed4dfe", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "5829c1427d562e21c1ed4dfe", +"postgres": "5829c1427d562e21c1ed4dfe", +"postgresql": "5829c1427d562e21c1ed4dfe", +"snowflake": "5829c1427d562e21c1ed4dfe", +"tsql": "5829c1427d562e21c1ed4dfe" +} +], +[ +"type", +{ +"DuckDB": "79278352c17c9de0f5a28af5", +"None": "79278352c17c9de0f5a28af5", +"bigquery": "c9b810639795a7bfab91b98d", +"databricks": "79278352c17c9de0f5a28af5", +"duckdb": "79278352c17c9de0f5a28af5", +"generic": "79278352c17c9de0f5a28af5", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "79278352c17c9de0f5a28af5", +"postgres": "79278352c17c9de0f5a28af5", +"postgresql": "79278352c17c9de0f5a28af5", +"snowflake": "97a20344d811fb77c7690863", +"tsql": "79278352c17c9de0f5a28af5" +} +], +[ +"type", +{ +"DuckDB": "e3ba57c3380e7ca53675e905", +"None": "85dad253f82f475892a7b35b", +"bigquery": "85dad253f82f475892a7b35b", +"databricks": "534433bc99c8d49f592ba435", +"duckdb": "e3ba57c3380e7ca53675e905", +"generic": "85dad253f82f475892a7b35b", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "3dd1a4411040373d9cd82f86", +"postgres": "463c3432687f6ea95aa60355", +"postgresql": "463c3432687f6ea95aa60355", +"snowflake": "0161e12cd4d2efd1b5557348", +"tsql": "87673dc143bcd33d8688dc34" +} +], +[ +"type", +{ +"DuckDB": "1fe8a2d5a41383bd8e502808", +"None": "1fe8a2d5a41383bd8e502808", +"bigquery": "70f3d045595fbd43219efb36", +"databricks": "70f3d045595fbd43219efb36", +"duckdb": "1fe8a2d5a41383bd8e502808", +"generic": "1fe8a2d5a41383bd8e502808", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "70f3d045595fbd43219efb36", +"postgres": "1fe8a2d5a41383bd8e502808", +"postgresql": "1fe8a2d5a41383bd8e502808", +"snowflake": "1fe8a2d5a41383bd8e502808", +"tsql": "1fe8a2d5a41383bd8e502808" +} +], +[ +"type", +{ +"DuckDB": "e46d4be44ab9e500e9190d26", +"None": "e46d4be44ab9e500e9190d26", +"bigquery": "e6ffdece2977be55da73b59a", +"databricks": "e46d4be44ab9e500e9190d26", +"duckdb": "e46d4be44ab9e500e9190d26", +"generic": "e46d4be44ab9e500e9190d26", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "e46d4be44ab9e500e9190d26", +"postgres": "e46d4be44ab9e500e9190d26", +"postgresql": "e46d4be44ab9e500e9190d26", +"snowflake": "e46d4be44ab9e500e9190d26", +"tsql": "e46d4be44ab9e500e9190d26" +} +], +[ +"type", +{ +"DuckDB": "1c58068460e5c94bc2f83d53", +"None": "1c58068460e5c94bc2f83d53", +"bigquery": "1c58068460e5c94bc2f83d53", +"databricks": "1c58068460e5c94bc2f83d53", +"duckdb": "1c58068460e5c94bc2f83d53", +"generic": "1c58068460e5c94bc2f83d53", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "1c58068460e5c94bc2f83d53", +"postgres": "1c58068460e5c94bc2f83d53", +"postgresql": "1c58068460e5c94bc2f83d53", +"snowflake": "1c58068460e5c94bc2f83d53", +"tsql": "1c58068460e5c94bc2f83d53" +} +], +[ +"type", +{ +"DuckDB": "79278352c17c9de0f5a28af5", +"None": "79278352c17c9de0f5a28af5", +"bigquery": "c9b810639795a7bfab91b98d", +"databricks": "79278352c17c9de0f5a28af5", +"duckdb": "79278352c17c9de0f5a28af5", +"generic": "79278352c17c9de0f5a28af5", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "79278352c17c9de0f5a28af5", +"postgres": "79278352c17c9de0f5a28af5", +"postgresql": "79278352c17c9de0f5a28af5", +"snowflake": "97a20344d811fb77c7690863", +"tsql": "79278352c17c9de0f5a28af5" +} +], +[ +"type", +{ +"DuckDB": "1eb7fb4e8cf75773c5573562", +"None": "1eb7fb4e8cf75773c5573562", +"bigquery": "c9b810639795a7bfab91b98d", +"databricks": "1eb7fb4e8cf75773c5573562", +"duckdb": "1eb7fb4e8cf75773c5573562", +"generic": "1eb7fb4e8cf75773c5573562", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "1eb7fb4e8cf75773c5573562", +"postgres": "1eb7fb4e8cf75773c5573562", +"postgresql": "1eb7fb4e8cf75773c5573562", +"snowflake": "97a20344d811fb77c7690863", +"tsql": "1eb7fb4e8cf75773c5573562" +} +], +[ +"type", +{ +"DuckDB": "26e762643db86e7646e57cba", +"None": "26e762643db86e7646e57cba", +"bigquery": "26e762643db86e7646e57cba", +"databricks": "26e762643db86e7646e57cba", +"duckdb": "26e762643db86e7646e57cba", +"generic": "26e762643db86e7646e57cba", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "26e762643db86e7646e57cba", +"postgres": "26e762643db86e7646e57cba", +"postgresql": "26e762643db86e7646e57cba", +"snowflake": "26e762643db86e7646e57cba", +"tsql": "26e762643db86e7646e57cba" +} +], +[ +"type", +{ +"DuckDB": "19a1a80ffc06169f32694de8", +"None": "19a1a80ffc06169f32694de8", +"bigquery": "19a1a80ffc06169f32694de8", +"databricks": "19a1a80ffc06169f32694de8", +"duckdb": "19a1a80ffc06169f32694de8", +"generic": "19a1a80ffc06169f32694de8", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "19a1a80ffc06169f32694de8", +"postgres": "19a1a80ffc06169f32694de8", +"postgresql": "19a1a80ffc06169f32694de8", +"snowflake": "19a1a80ffc06169f32694de8", +"tsql": "19a1a80ffc06169f32694de8" +} +], +[ +"type", +{ +"DuckDB": "243652b8dd9a0f3ac3501ed4", +"None": "f74ed75cd28860b40bc2c2e4", +"bigquery": "f74ed75cd28860b40bc2c2e4", +"databricks": "7c0baf18eb7c47a1c83b71c3", +"duckdb": "243652b8dd9a0f3ac3501ed4", +"generic": "f74ed75cd28860b40bc2c2e4", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "6c03a3450ea4742ee7396e3c", +"postgres": "240398aee89da87a2f8274c9", +"postgresql": "240398aee89da87a2f8274c9", +"snowflake": "7422d281eba97abeec05a617", +"tsql": "d1dc9a140dbe2eb1874c6ad7" +} +], +[ +"type", +{ +"DuckDB": "72bd5e38b32893397eb51579", +"None": "1bdf5908ca249b2331a0427c", +"bigquery": "1bdf5908ca249b2331a0427c", +"databricks": "1bdf5908ca249b2331a0427c", +"duckdb": "72bd5e38b32893397eb51579", +"generic": "1bdf5908ca249b2331a0427c", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "1bdf5908ca249b2331a0427c", +"postgres": "1bdf5908ca249b2331a0427c", +"postgresql": "1bdf5908ca249b2331a0427c", +"snowflake": "8ff614b7306c0edbe36ce00b", +"tsql": "1bdf5908ca249b2331a0427c" +} +], +[ +"type", +{ +"DuckDB": "d725148d39793a0cbb9a6013", +"None": "d725148d39793a0cbb9a6013", +"bigquery": "d725148d39793a0cbb9a6013", +"databricks": "d725148d39793a0cbb9a6013", +"duckdb": "d725148d39793a0cbb9a6013", +"generic": "d725148d39793a0cbb9a6013", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "d725148d39793a0cbb9a6013", +"postgres": "d725148d39793a0cbb9a6013", +"postgresql": "d725148d39793a0cbb9a6013", +"snowflake": "d725148d39793a0cbb9a6013", +"tsql": "d725148d39793a0cbb9a6013" +} +], +[ +"type", +{ +"DuckDB": "fe0bedb7dda0e9247a51fdee", +"None": "fe0bedb7dda0e9247a51fdee", +"bigquery": "fe0bedb7dda0e9247a51fdee", +"databricks": "fe0bedb7dda0e9247a51fdee", +"duckdb": "fe0bedb7dda0e9247a51fdee", +"generic": "fe0bedb7dda0e9247a51fdee", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "fe0bedb7dda0e9247a51fdee", +"postgres": "fe0bedb7dda0e9247a51fdee", +"postgresql": "fe0bedb7dda0e9247a51fdee", +"snowflake": "fe0bedb7dda0e9247a51fdee", +"tsql": "fe0bedb7dda0e9247a51fdee" +} +], +[ +"type", +{ +"DuckDB": "2c44dc35fd1ef8701101802e", +"None": "2c44dc35fd1ef8701101802e", +"bigquery": "a428302e4848ffe877284c84", +"databricks": "2c44dc35fd1ef8701101802e", +"duckdb": "2c44dc35fd1ef8701101802e", +"generic": "2c44dc35fd1ef8701101802e", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "2c44dc35fd1ef8701101802e", +"postgres": "2c44dc35fd1ef8701101802e", +"postgresql": "2c44dc35fd1ef8701101802e", +"snowflake": "652ff8b21f638eac8fdc46c5", +"tsql": "2c44dc35fd1ef8701101802e" +} +], +[ +"type", +{ +"DuckDB": "c4346d0257336219f1d26890", +"None": "c4346d0257336219f1d26890", +"bigquery": "b5c4d5044b2a6e70633f0d0a", +"databricks": "c4346d0257336219f1d26890", +"duckdb": "c4346d0257336219f1d26890", +"generic": "c4346d0257336219f1d26890", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "c4346d0257336219f1d26890", +"postgres": "c4346d0257336219f1d26890", +"postgresql": "c4346d0257336219f1d26890", +"snowflake": "4e24a80b20b9dee0cbbfac17", +"tsql": "c4346d0257336219f1d26890" +} +], +[ +"type", +{ +"DuckDB": "73ed909ac0c80ba48ae6d17c", +"None": "73ed909ac0c80ba48ae6d17c", +"bigquery": "73ed909ac0c80ba48ae6d17c", +"databricks": "73ed909ac0c80ba48ae6d17c", +"duckdb": "73ed909ac0c80ba48ae6d17c", +"generic": "73ed909ac0c80ba48ae6d17c", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "73ed909ac0c80ba48ae6d17c", +"postgres": "73ed909ac0c80ba48ae6d17c", +"postgresql": "73ed909ac0c80ba48ae6d17c", +"snowflake": "73ed909ac0c80ba48ae6d17c", +"tsql": "73ed909ac0c80ba48ae6d17c" +} +], +[ +"type", +{ +"DuckDB": "445eba49a8d5ccbd6775e1b6", +"None": "445eba49a8d5ccbd6775e1b6", +"bigquery": "445eba49a8d5ccbd6775e1b6", +"databricks": "445eba49a8d5ccbd6775e1b6", +"duckdb": "445eba49a8d5ccbd6775e1b6", +"generic": "445eba49a8d5ccbd6775e1b6", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "445eba49a8d5ccbd6775e1b6", +"postgres": "445eba49a8d5ccbd6775e1b6", +"postgresql": "445eba49a8d5ccbd6775e1b6", +"snowflake": "445eba49a8d5ccbd6775e1b6", +"tsql": "445eba49a8d5ccbd6775e1b6" +} +], +[ +"type", +{ +"DuckDB": "097487e169d70127caa10537", +"None": "097487e169d70127caa10537", +"bigquery": "097487e169d70127caa10537", +"databricks": "097487e169d70127caa10537", +"duckdb": "097487e169d70127caa10537", +"generic": "097487e169d70127caa10537", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "097487e169d70127caa10537", +"postgres": "097487e169d70127caa10537", +"postgresql": "097487e169d70127caa10537", +"snowflake": "097487e169d70127caa10537", +"tsql": "097487e169d70127caa10537" +} +], +[ +"type", +{ +"DuckDB": "6226bc03436ecf8fccd39252", +"None": "5aa51d84ac5e6c7a9306f348", +"bigquery": "5aa51d84ac5e6c7a9306f348", +"databricks": "5aa51d84ac5e6c7a9306f348", +"duckdb": "6226bc03436ecf8fccd39252", +"generic": "5aa51d84ac5e6c7a9306f348", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "5aa51d84ac5e6c7a9306f348", +"postgres": "5aa51d84ac5e6c7a9306f348", +"postgresql": "5aa51d84ac5e6c7a9306f348", +"snowflake": "5aa51d84ac5e6c7a9306f348", +"tsql": "5aa51d84ac5e6c7a9306f348" +} +], +[ +"type", +{ +"DuckDB": "383310937b9286f8d0206ea4", +"None": "383310937b9286f8d0206ea4", +"bigquery": "383310937b9286f8d0206ea4", +"databricks": "383310937b9286f8d0206ea4", +"duckdb": "383310937b9286f8d0206ea4", +"generic": "383310937b9286f8d0206ea4", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "383310937b9286f8d0206ea4", +"postgres": "383310937b9286f8d0206ea4", +"postgresql": "383310937b9286f8d0206ea4", +"snowflake": "383310937b9286f8d0206ea4", +"tsql": "383310937b9286f8d0206ea4" +} +], +[ +"type", +{ +"DuckDB": "3efe8bb57c98fcbe74096b3c", +"None": "3efe8bb57c98fcbe74096b3c", +"bigquery": "68d2179839f17f0eb289d1aa", +"databricks": "e3bc1b8bad22d8104417b00f", +"duckdb": "3efe8bb57c98fcbe74096b3c", +"generic": "3efe8bb57c98fcbe74096b3c", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "1d8b945fd793ecdcacb90c21", +"postgres": "3efe8bb57c98fcbe74096b3c", +"postgresql": "3efe8bb57c98fcbe74096b3c", +"snowflake": "1d8b945fd793ecdcacb90c21", +"tsql": "3efe8bb57c98fcbe74096b3c" +} +], +[ +"type", +{ +"DuckDB": "a428302e4848ffe877284c84", +"None": "a428302e4848ffe877284c84", +"bigquery": "a428302e4848ffe877284c84", +"databricks": "a428302e4848ffe877284c84", +"duckdb": "a428302e4848ffe877284c84", +"generic": "a428302e4848ffe877284c84", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "a428302e4848ffe877284c84", +"postgres": "a428302e4848ffe877284c84", +"postgresql": "a428302e4848ffe877284c84", +"snowflake": "652ff8b21f638eac8fdc46c5", +"tsql": "a428302e4848ffe877284c84" +} +], +[ +"type", +{ +"DuckDB": "bbb97828cd28c64282709796", +"None": "bbb97828cd28c64282709796", +"bigquery": "bbb97828cd28c64282709796", +"databricks": "bbb97828cd28c64282709796", +"duckdb": "bbb97828cd28c64282709796", +"generic": "bbb97828cd28c64282709796", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "bbb97828cd28c64282709796", +"postgres": "bbb97828cd28c64282709796", +"postgresql": "bbb97828cd28c64282709796", +"snowflake": "bbb97828cd28c64282709796", +"tsql": "bbb97828cd28c64282709796" +} +], +[ +"type", +{ +"DuckDB": "33edbb37fe70dd760e97e937", +"None": "33edbb37fe70dd760e97e937", +"bigquery": "33edbb37fe70dd760e97e937", +"databricks": "33edbb37fe70dd760e97e937", +"duckdb": "33edbb37fe70dd760e97e937", +"generic": "33edbb37fe70dd760e97e937", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "33edbb37fe70dd760e97e937", +"postgres": "33edbb37fe70dd760e97e937", +"postgresql": "33edbb37fe70dd760e97e937", +"snowflake": "33edbb37fe70dd760e97e937", +"tsql": "33edbb37fe70dd760e97e937" +} +], +[ +"type", +{ +"DuckDB": "19a1a80ffc06169f32694de8", +"None": "19a1a80ffc06169f32694de8", +"bigquery": "19a1a80ffc06169f32694de8", +"databricks": "19a1a80ffc06169f32694de8", +"duckdb": "19a1a80ffc06169f32694de8", +"generic": "19a1a80ffc06169f32694de8", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "19a1a80ffc06169f32694de8", +"postgres": "19a1a80ffc06169f32694de8", +"postgresql": "19a1a80ffc06169f32694de8", +"snowflake": "19a1a80ffc06169f32694de8", +"tsql": "19a1a80ffc06169f32694de8" +} +], +[ +"type", +{ +"DuckDB": "c50a316d091c821866e4bfba", +"None": "c50a316d091c821866e4bfba", +"bigquery": "c50a316d091c821866e4bfba", +"databricks": "c50a316d091c821866e4bfba", +"duckdb": "c50a316d091c821866e4bfba", +"generic": "c50a316d091c821866e4bfba", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "c50a316d091c821866e4bfba", +"postgres": "c50a316d091c821866e4bfba", +"postgresql": "c50a316d091c821866e4bfba", +"snowflake": "c50a316d091c821866e4bfba", +"tsql": "c50a316d091c821866e4bfba" +} +], +[ +"type", +{ +"DuckDB": "638ca9212b62ada31a448c62", +"None": "1fec266134381c760a254d16", +"bigquery": "1fec266134381c760a254d16", +"databricks": "1fec266134381c760a254d16", +"duckdb": "638ca9212b62ada31a448c62", +"generic": "1fec266134381c760a254d16", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "1fec266134381c760a254d16", +"postgres": "1fec266134381c760a254d16", +"postgresql": "1fec266134381c760a254d16", +"snowflake": "1fec266134381c760a254d16", +"tsql": "1fec266134381c760a254d16" +} +], +[ +"type", +{ +"DuckDB": "c50a316d091c821866e4bfba", +"None": "c50a316d091c821866e4bfba", +"bigquery": "c50a316d091c821866e4bfba", +"databricks": "c50a316d091c821866e4bfba", +"duckdb": "c50a316d091c821866e4bfba", +"generic": "c50a316d091c821866e4bfba", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "c50a316d091c821866e4bfba", +"postgres": "c50a316d091c821866e4bfba", +"postgresql": "c50a316d091c821866e4bfba", +"snowflake": "c50a316d091c821866e4bfba", +"tsql": "c50a316d091c821866e4bfba" +} +], +[ +"type", +{ +"DuckDB": "0a735e1254c48785122ee5a3", +"None": "558da38ec4d9d5d6c72f60cf", +"bigquery": "e6ffdece2977be55da73b59a", +"databricks": "558da38ec4d9d5d6c72f60cf", +"duckdb": "0a735e1254c48785122ee5a3", +"generic": "558da38ec4d9d5d6c72f60cf", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "558da38ec4d9d5d6c72f60cf", +"postgres": "558da38ec4d9d5d6c72f60cf", +"postgresql": "558da38ec4d9d5d6c72f60cf", +"snowflake": "558da38ec4d9d5d6c72f60cf", +"tsql": "558da38ec4d9d5d6c72f60cf" +} +], +[ +"type", +{ +"DuckDB": "38742651e9a5007a4262fae8", +"None": "38742651e9a5007a4262fae8", +"bigquery": "38742651e9a5007a4262fae8", +"databricks": "38742651e9a5007a4262fae8", +"duckdb": "38742651e9a5007a4262fae8", +"generic": "38742651e9a5007a4262fae8", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "38742651e9a5007a4262fae8", +"postgres": "38742651e9a5007a4262fae8", +"postgresql": "38742651e9a5007a4262fae8", +"snowflake": "38742651e9a5007a4262fae8", +"tsql": "38742651e9a5007a4262fae8" +} +], +[ +"type", +{ +"DuckDB": "de89632e277dbc8c97115419", +"None": "de89632e277dbc8c97115419", +"bigquery": "de89632e277dbc8c97115419", +"databricks": "de89632e277dbc8c97115419", +"duckdb": "de89632e277dbc8c97115419", +"generic": "de89632e277dbc8c97115419", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "de89632e277dbc8c97115419", +"postgres": "de89632e277dbc8c97115419", +"postgresql": "de89632e277dbc8c97115419", +"snowflake": "4b356542044f1267fcfc487a", +"tsql": "de89632e277dbc8c97115419" +} +], +[ +"type", +{ +"DuckDB": "cdf6c5188287878061490c2a", +"None": "cdf6c5188287878061490c2a", +"bigquery": "8b225d02320fa30e4a4e6cb1", +"databricks": "f6e9bda6dd824d392effea47", +"duckdb": "cdf6c5188287878061490c2a", +"generic": "cdf6c5188287878061490c2a", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "5598594492668be60871af14", +"postgres": "cdf6c5188287878061490c2a", +"postgresql": "cdf6c5188287878061490c2a", +"snowflake": "5c643769adf301c8da08643f", +"tsql": "cdf6c5188287878061490c2a" +} +], +[ +"type", +{ +"DuckDB": "e7455ff80a579a99488df79b", +"None": "e7455ff80a579a99488df79b", +"bigquery": "e7455ff80a579a99488df79b", +"databricks": "e7455ff80a579a99488df79b", +"duckdb": "e7455ff80a579a99488df79b", +"generic": "e7455ff80a579a99488df79b", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "e7455ff80a579a99488df79b", +"postgres": "e7455ff80a579a99488df79b", +"postgresql": "e7455ff80a579a99488df79b", +"snowflake": "e7455ff80a579a99488df79b", +"tsql": "e7455ff80a579a99488df79b" +} +], +[ +"type", +{ +"DuckDB": "2c6b371b030464f525066893", +"None": "2c6b371b030464f525066893", +"bigquery": "2c6b371b030464f525066893", +"databricks": "2c6b371b030464f525066893", +"duckdb": "2c6b371b030464f525066893", +"generic": "2c6b371b030464f525066893", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "2c6b371b030464f525066893", +"postgres": "2c6b371b030464f525066893", +"postgresql": "2c6b371b030464f525066893", +"snowflake": "2c6b371b030464f525066893", +"tsql": "2c6b371b030464f525066893" +} +], +[ +"type", +{ +"DuckDB": "881106a4a0d2de0ff7c56373", +"None": "881106a4a0d2de0ff7c56373", +"bigquery": "881106a4a0d2de0ff7c56373", +"databricks": "881106a4a0d2de0ff7c56373", +"duckdb": "881106a4a0d2de0ff7c56373", +"generic": "881106a4a0d2de0ff7c56373", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "881106a4a0d2de0ff7c56373", +"postgres": "881106a4a0d2de0ff7c56373", +"postgresql": "881106a4a0d2de0ff7c56373", +"snowflake": "881106a4a0d2de0ff7c56373", +"tsql": "881106a4a0d2de0ff7c56373" +} +], +[ +"type", +{ +"DuckDB": "461923a0d34defd0c726d6e5", +"None": "461923a0d34defd0c726d6e5", +"bigquery": "b5c4d5044b2a6e70633f0d0a", +"databricks": "461923a0d34defd0c726d6e5", +"duckdb": "461923a0d34defd0c726d6e5", +"generic": "461923a0d34defd0c726d6e5", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "461923a0d34defd0c726d6e5", +"postgres": "461923a0d34defd0c726d6e5", +"postgresql": "461923a0d34defd0c726d6e5", +"snowflake": "461923a0d34defd0c726d6e5", +"tsql": "461923a0d34defd0c726d6e5" +} +], +[ +"type", +{ +"DuckDB": "d2c97d221599d038d9875873", +"None": "d2c97d221599d038d9875873", +"bigquery": "d2c97d221599d038d9875873", +"databricks": "d2c97d221599d038d9875873", +"duckdb": "d2c97d221599d038d9875873", +"generic": "d2c97d221599d038d9875873", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "d2c97d221599d038d9875873", +"postgres": "d2c97d221599d038d9875873", +"postgresql": "d2c97d221599d038d9875873", +"snowflake": "d2c97d221599d038d9875873", +"tsql": "d2c97d221599d038d9875873" +} +], +[ +"type", +{ +"DuckDB": "07aa3fe366bb8a3f270ea3d3", +"None": "07aa3fe366bb8a3f270ea3d3", +"bigquery": "07aa3fe366bb8a3f270ea3d3", +"databricks": "07aa3fe366bb8a3f270ea3d3", +"duckdb": "07aa3fe366bb8a3f270ea3d3", +"generic": "07aa3fe366bb8a3f270ea3d3", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "07aa3fe366bb8a3f270ea3d3", +"postgres": "07aa3fe366bb8a3f270ea3d3", +"postgresql": "07aa3fe366bb8a3f270ea3d3", +"snowflake": "07aa3fe366bb8a3f270ea3d3", +"tsql": "07aa3fe366bb8a3f270ea3d3" +} +], +[ +"type", +{ +"DuckDB": "d47776cdb5b03cf4b1e7b63c", +"None": "d47776cdb5b03cf4b1e7b63c", +"bigquery": "d47776cdb5b03cf4b1e7b63c", +"databricks": "d47776cdb5b03cf4b1e7b63c", +"duckdb": "d47776cdb5b03cf4b1e7b63c", +"generic": "d47776cdb5b03cf4b1e7b63c", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "d47776cdb5b03cf4b1e7b63c", +"postgres": "d47776cdb5b03cf4b1e7b63c", +"postgresql": "d47776cdb5b03cf4b1e7b63c", +"snowflake": "d47776cdb5b03cf4b1e7b63c", +"tsql": "d47776cdb5b03cf4b1e7b63c" +} +], +[ +"type", +{ +"DuckDB": "eed0645c1e86fa1a6e35ccaa", +"None": "eed0645c1e86fa1a6e35ccaa", +"bigquery": "013a8446f043affffcf194f8", +"databricks": "eed0645c1e86fa1a6e35ccaa", +"duckdb": "eed0645c1e86fa1a6e35ccaa", +"generic": "eed0645c1e86fa1a6e35ccaa", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "eed0645c1e86fa1a6e35ccaa", +"postgres": "eed0645c1e86fa1a6e35ccaa", +"postgresql": "eed0645c1e86fa1a6e35ccaa", +"snowflake": "97a20344d811fb77c7690863", +"tsql": "eed0645c1e86fa1a6e35ccaa" +} +], +[ +"type", +{ +"DuckDB": "a428302e4848ffe877284c84", +"None": "a428302e4848ffe877284c84", +"bigquery": "a428302e4848ffe877284c84", +"databricks": "a428302e4848ffe877284c84", +"duckdb": "a428302e4848ffe877284c84", +"generic": "a428302e4848ffe877284c84", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "a428302e4848ffe877284c84", +"postgres": "a428302e4848ffe877284c84", +"postgresql": "a428302e4848ffe877284c84", +"snowflake": "652ff8b21f638eac8fdc46c5", +"tsql": "a428302e4848ffe877284c84" +} +], +[ +"type", +{ +"DuckDB": "3959952046272deb40567543", +"None": "3959952046272deb40567543", +"bigquery": "3959952046272deb40567543", +"databricks": "3959952046272deb40567543", +"duckdb": "3959952046272deb40567543", +"generic": "3959952046272deb40567543", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "3959952046272deb40567543", +"postgres": "3959952046272deb40567543", +"postgresql": "3959952046272deb40567543", +"snowflake": "3959952046272deb40567543", +"tsql": "3959952046272deb40567543" +} +], +[ +"type", +{ +"DuckDB": "c426d93641829fa3d8f49b8d", +"None": "c426d93641829fa3d8f49b8d", +"bigquery": "c426d93641829fa3d8f49b8d", +"databricks": "c426d93641829fa3d8f49b8d", +"duckdb": "c426d93641829fa3d8f49b8d", +"generic": "c426d93641829fa3d8f49b8d", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "c426d93641829fa3d8f49b8d", +"postgres": "c426d93641829fa3d8f49b8d", +"postgresql": "c426d93641829fa3d8f49b8d", +"snowflake": "c426d93641829fa3d8f49b8d", +"tsql": "c426d93641829fa3d8f49b8d" +} +], +[ +"type", +{ +"DuckDB": "da33de41a707d0e067e415fd", +"None": "da33de41a707d0e067e415fd", +"bigquery": "da33de41a707d0e067e415fd", +"databricks": "da33de41a707d0e067e415fd", +"duckdb": "da33de41a707d0e067e415fd", +"generic": "da33de41a707d0e067e415fd", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "da33de41a707d0e067e415fd", +"postgres": "da33de41a707d0e067e415fd", +"postgresql": "da33de41a707d0e067e415fd", +"snowflake": "da33de41a707d0e067e415fd", +"tsql": "da33de41a707d0e067e415fd" +} +], +[ +"type", +{ +"DuckDB": "3147a9e06daa6de4a4df5abc", +"None": "3147a9e06daa6de4a4df5abc", +"bigquery": "f276e907770196606577c932", +"databricks": "3147a9e06daa6de4a4df5abc", +"duckdb": "3147a9e06daa6de4a4df5abc", +"generic": "3147a9e06daa6de4a4df5abc", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "3147a9e06daa6de4a4df5abc", +"postgres": "3147a9e06daa6de4a4df5abc", +"postgresql": "3147a9e06daa6de4a4df5abc", +"snowflake": "67b5874a2c569226c490211f", +"tsql": "3147a9e06daa6de4a4df5abc" +} +], +[ +"type", +{ +"DuckDB": "e2879cf4770e7f48d2dd704a", +"None": "e2879cf4770e7f48d2dd704a", +"bigquery": "c9b810639795a7bfab91b98d", +"databricks": "e2879cf4770e7f48d2dd704a", +"duckdb": "e2879cf4770e7f48d2dd704a", +"generic": "e2879cf4770e7f48d2dd704a", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "e2879cf4770e7f48d2dd704a", +"postgres": "e2879cf4770e7f48d2dd704a", +"postgresql": "e2879cf4770e7f48d2dd704a", +"snowflake": "97a20344d811fb77c7690863", +"tsql": "e2879cf4770e7f48d2dd704a" +} +], +[ +"type", +{ +"DuckDB": "c50a316d091c821866e4bfba", +"None": "c50a316d091c821866e4bfba", +"bigquery": "c50a316d091c821866e4bfba", +"databricks": "c50a316d091c821866e4bfba", +"duckdb": "c50a316d091c821866e4bfba", +"generic": "c50a316d091c821866e4bfba", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "c50a316d091c821866e4bfba", +"postgres": "c50a316d091c821866e4bfba", +"postgresql": "c50a316d091c821866e4bfba", +"snowflake": "c50a316d091c821866e4bfba", +"tsql": "c50a316d091c821866e4bfba" +} +], +[ +"type", +{ +"DuckDB": "be15dde1d6e0b4bb3f6da66f", +"None": "be15dde1d6e0b4bb3f6da66f", +"bigquery": "be15dde1d6e0b4bb3f6da66f", +"databricks": "be15dde1d6e0b4bb3f6da66f", +"duckdb": "be15dde1d6e0b4bb3f6da66f", +"generic": "be15dde1d6e0b4bb3f6da66f", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "be15dde1d6e0b4bb3f6da66f", +"postgres": "be15dde1d6e0b4bb3f6da66f", +"postgresql": "be15dde1d6e0b4bb3f6da66f", +"snowflake": "be15dde1d6e0b4bb3f6da66f", +"tsql": "be15dde1d6e0b4bb3f6da66f" +} +], +[ +"type", +{ +"DuckDB": "4062ec81199547543ab068fb", +"None": "4062ec81199547543ab068fb", +"bigquery": "7009fc15fd2c35608ab16caf", +"databricks": "0739784ba4c53d23afd45a6b", +"duckdb": "4062ec81199547543ab068fb", +"generic": "4062ec81199547543ab068fb", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "4062ec81199547543ab068fb", +"postgres": "4062ec81199547543ab068fb", +"postgresql": "4062ec81199547543ab068fb", +"snowflake": "0739784ba4c53d23afd45a6b", +"tsql": "0739784ba4c53d23afd45a6b" +} +], +[ +"type", +{ +"DuckDB": "73151c1398b30e5c5d18f4ce", +"None": "73151c1398b30e5c5d18f4ce", +"bigquery": "73151c1398b30e5c5d18f4ce", +"databricks": "73151c1398b30e5c5d18f4ce", +"duckdb": "73151c1398b30e5c5d18f4ce", +"generic": "73151c1398b30e5c5d18f4ce", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "73151c1398b30e5c5d18f4ce", +"postgres": "73151c1398b30e5c5d18f4ce", +"postgresql": "73151c1398b30e5c5d18f4ce", +"snowflake": "73151c1398b30e5c5d18f4ce", +"tsql": "73151c1398b30e5c5d18f4ce" +} +], +[ +"type", +{ +"DuckDB": "e3d9a113277b9c69432b32d1", +"None": "e3d9a113277b9c69432b32d1", +"bigquery": "e3d9a113277b9c69432b32d1", +"databricks": "4cda99191af9adfbe91e70f6", +"duckdb": "e3d9a113277b9c69432b32d1", +"generic": "e3d9a113277b9c69432b32d1", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "4cda99191af9adfbe91e70f6", +"postgres": "e3d9a113277b9c69432b32d1", +"postgresql": "e3d9a113277b9c69432b32d1", +"snowflake": "e3d9a113277b9c69432b32d1", +"tsql": "e3d9a113277b9c69432b32d1" +} +], +[ +"type", +{ +"DuckDB": "f6c3d80bfee0ec0b286b82b5", +"None": "b137c998bdaa2555d912e8fa", +"bigquery": "b137c998bdaa2555d912e8fa", +"databricks": "b137c998bdaa2555d912e8fa", +"duckdb": "f6c3d80bfee0ec0b286b82b5", +"generic": "b137c998bdaa2555d912e8fa", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "b137c998bdaa2555d912e8fa", +"postgres": "b137c998bdaa2555d912e8fa", +"postgresql": "b137c998bdaa2555d912e8fa", +"snowflake": "b137c998bdaa2555d912e8fa", +"tsql": "b137c998bdaa2555d912e8fa" +} +], +[ +"type", +{ +"DuckDB": "7a924f1a13854aa3260f3f57", +"None": "7a924f1a13854aa3260f3f57", +"bigquery": "7a924f1a13854aa3260f3f57", +"databricks": "7a924f1a13854aa3260f3f57", +"duckdb": "7a924f1a13854aa3260f3f57", +"generic": "7a924f1a13854aa3260f3f57", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "7a924f1a13854aa3260f3f57", +"postgres": "7a924f1a13854aa3260f3f57", +"postgresql": "7a924f1a13854aa3260f3f57", +"snowflake": "7a924f1a13854aa3260f3f57", +"tsql": "7a924f1a13854aa3260f3f57" +} +], +[ +"type", +{ +"DuckDB": "66f7ca02161349d637fa7d4e", +"None": "66f7ca02161349d637fa7d4e", +"bigquery": "d90a78129f7050a540984f6f", +"databricks": "d90a78129f7050a540984f6f", +"duckdb": "66f7ca02161349d637fa7d4e", +"generic": "66f7ca02161349d637fa7d4e", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "d90a78129f7050a540984f6f", +"postgres": "66f7ca02161349d637fa7d4e", +"postgresql": "66f7ca02161349d637fa7d4e", +"snowflake": "66f7ca02161349d637fa7d4e", +"tsql": "66f7ca02161349d637fa7d4e" +} +], +[ +"type", +{ +"DuckDB": "104d3e046c47032c37f947b8", +"None": "104d3e046c47032c37f947b8", +"bigquery": "104d3e046c47032c37f947b8", +"databricks": "104d3e046c47032c37f947b8", +"duckdb": "104d3e046c47032c37f947b8", +"generic": "104d3e046c47032c37f947b8", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "104d3e046c47032c37f947b8", +"postgres": "104d3e046c47032c37f947b8", +"postgresql": "104d3e046c47032c37f947b8", +"snowflake": "104d3e046c47032c37f947b8", +"tsql": "104d3e046c47032c37f947b8" +} +], +[ +"type", +{ +"DuckDB": "79278352c17c9de0f5a28af5", +"None": "79278352c17c9de0f5a28af5", +"bigquery": "c9b810639795a7bfab91b98d", +"databricks": "79278352c17c9de0f5a28af5", +"duckdb": "79278352c17c9de0f5a28af5", +"generic": "79278352c17c9de0f5a28af5", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "79278352c17c9de0f5a28af5", +"postgres": "79278352c17c9de0f5a28af5", +"postgresql": "79278352c17c9de0f5a28af5", +"snowflake": "97a20344d811fb77c7690863", +"tsql": "79278352c17c9de0f5a28af5" +} +], +[ +"type", +{ +"DuckDB": "79278352c17c9de0f5a28af5", +"None": "79278352c17c9de0f5a28af5", +"bigquery": "c9b810639795a7bfab91b98d", +"databricks": "79278352c17c9de0f5a28af5", +"duckdb": "79278352c17c9de0f5a28af5", +"generic": "79278352c17c9de0f5a28af5", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "79278352c17c9de0f5a28af5", +"postgres": "79278352c17c9de0f5a28af5", +"postgresql": "79278352c17c9de0f5a28af5", +"snowflake": "97a20344d811fb77c7690863", +"tsql": "79278352c17c9de0f5a28af5" +} +], +[ +"type", +{ +"DuckDB": "f3150219c38dba6b9f922447", +"None": "f3150219c38dba6b9f922447", +"bigquery": "f3150219c38dba6b9f922447", +"databricks": "f3150219c38dba6b9f922447", +"duckdb": "f3150219c38dba6b9f922447", +"generic": "f3150219c38dba6b9f922447", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "f3150219c38dba6b9f922447", +"postgres": "f3150219c38dba6b9f922447", +"postgresql": "f3150219c38dba6b9f922447", +"snowflake": "f3150219c38dba6b9f922447", +"tsql": "f3150219c38dba6b9f922447" +} +], +[ +"type", +{ +"DuckDB": "f6140be64a327a15b42b923d", +"None": "f6140be64a327a15b42b923d", +"bigquery": "f6140be64a327a15b42b923d", +"databricks": "f6140be64a327a15b42b923d", +"duckdb": "f6140be64a327a15b42b923d", +"generic": "f6140be64a327a15b42b923d", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "f6140be64a327a15b42b923d", +"postgres": "f6140be64a327a15b42b923d", +"postgresql": "f6140be64a327a15b42b923d", +"snowflake": "f6140be64a327a15b42b923d", +"tsql": "f6140be64a327a15b42b923d" +} +], +[ +"type", +{ +"DuckDB": "e408f2d8251e1675179187e6", +"None": "e408f2d8251e1675179187e6", +"bigquery": "e408f2d8251e1675179187e6", +"databricks": "e408f2d8251e1675179187e6", +"duckdb": "e408f2d8251e1675179187e6", +"generic": "e408f2d8251e1675179187e6", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "e408f2d8251e1675179187e6", +"postgres": "e408f2d8251e1675179187e6", +"postgresql": "e408f2d8251e1675179187e6", +"snowflake": "e408f2d8251e1675179187e6", +"tsql": "e408f2d8251e1675179187e6" +} +], +[ +"type", +{ +"DuckDB": "3959952046272deb40567543", +"None": "3959952046272deb40567543", +"bigquery": "3959952046272deb40567543", +"databricks": "3959952046272deb40567543", +"duckdb": "3959952046272deb40567543", +"generic": "3959952046272deb40567543", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "3959952046272deb40567543", +"postgres": "3959952046272deb40567543", +"postgresql": "3959952046272deb40567543", +"snowflake": "3959952046272deb40567543", +"tsql": "3959952046272deb40567543" +} +], +[ +"type", +{ +"DuckDB": "ebc821a95b9286e22c2b26d0", +"None": "ebc821a95b9286e22c2b26d0", +"bigquery": "19a1a80ffc06169f32694de8", +"databricks": "ebc821a95b9286e22c2b26d0", +"duckdb": "ebc821a95b9286e22c2b26d0", +"generic": "ebc821a95b9286e22c2b26d0", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "ebc821a95b9286e22c2b26d0", +"postgres": "ebc821a95b9286e22c2b26d0", +"postgresql": "ebc821a95b9286e22c2b26d0", +"snowflake": "ebc821a95b9286e22c2b26d0", +"tsql": "ebc821a95b9286e22c2b26d0" +} +], +[ +"type", +{ +"DuckDB": "087a9417cb511ff7bcfd6ccb", +"None": "383f8922f4b6f167d384037d", +"bigquery": "383f8922f4b6f167d384037d", +"databricks": "383f8922f4b6f167d384037d", +"duckdb": "087a9417cb511ff7bcfd6ccb", +"generic": "383f8922f4b6f167d384037d", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "383f8922f4b6f167d384037d", +"postgres": "383f8922f4b6f167d384037d", +"postgresql": "383f8922f4b6f167d384037d", +"snowflake": "383f8922f4b6f167d384037d", +"tsql": "383f8922f4b6f167d384037d" +} +], +[ +"type", +{ +"DuckDB": "a428302e4848ffe877284c84", +"None": "a428302e4848ffe877284c84", +"bigquery": "a428302e4848ffe877284c84", +"databricks": "a428302e4848ffe877284c84", +"duckdb": "a428302e4848ffe877284c84", +"generic": "a428302e4848ffe877284c84", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "a428302e4848ffe877284c84", +"postgres": "a428302e4848ffe877284c84", +"postgresql": "a428302e4848ffe877284c84", +"snowflake": "652ff8b21f638eac8fdc46c5", +"tsql": "a428302e4848ffe877284c84" +} +], +[ +"type", +{ +"DuckDB": "5d0a19a893dbf0c1e6e9f15c", +"None": "5d0a19a893dbf0c1e6e9f15c", +"bigquery": "5d0a19a893dbf0c1e6e9f15c", +"databricks": "5d0a19a893dbf0c1e6e9f15c", +"duckdb": "5d0a19a893dbf0c1e6e9f15c", +"generic": "5d0a19a893dbf0c1e6e9f15c", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "5d0a19a893dbf0c1e6e9f15c", +"postgres": "5d0a19a893dbf0c1e6e9f15c", +"postgresql": "5d0a19a893dbf0c1e6e9f15c", +"snowflake": "5d0a19a893dbf0c1e6e9f15c", +"tsql": "5d0a19a893dbf0c1e6e9f15c" +} +], +[ +"type", +{ +"DuckDB": "2460e6e632163bbe7ecaf8a2", +"None": "2460e6e632163bbe7ecaf8a2", +"bigquery": "2460e6e632163bbe7ecaf8a2", +"databricks": "2460e6e632163bbe7ecaf8a2", +"duckdb": "2460e6e632163bbe7ecaf8a2", +"generic": "2460e6e632163bbe7ecaf8a2", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "2460e6e632163bbe7ecaf8a2", +"postgres": "2460e6e632163bbe7ecaf8a2", +"postgresql": "2460e6e632163bbe7ecaf8a2", +"snowflake": "2460e6e632163bbe7ecaf8a2", +"tsql": "2460e6e632163bbe7ecaf8a2" +} +], +[ +"type", +{ +"DuckDB": "38b2ec94bf02be40007ce525", +"None": "38b2ec94bf02be40007ce525", +"bigquery": "38b2ec94bf02be40007ce525", +"databricks": "38b2ec94bf02be40007ce525", +"duckdb": "38b2ec94bf02be40007ce525", +"generic": "38b2ec94bf02be40007ce525", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "38b2ec94bf02be40007ce525", +"postgres": "38b2ec94bf02be40007ce525", +"postgresql": "38b2ec94bf02be40007ce525", +"snowflake": "38b2ec94bf02be40007ce525", +"tsql": "38b2ec94bf02be40007ce525" +} +], +[ +"type", +{ +"DuckDB": "3b0d47536653277b7d98e328", +"None": "3b0d47536653277b7d98e328", +"bigquery": "3b0d47536653277b7d98e328", +"databricks": "3b0d47536653277b7d98e328", +"duckdb": "3b0d47536653277b7d98e328", +"generic": "3b0d47536653277b7d98e328", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "3b0d47536653277b7d98e328", +"postgres": "3b0d47536653277b7d98e328", +"postgresql": "3b0d47536653277b7d98e328", +"snowflake": "3b0d47536653277b7d98e328", +"tsql": "3b0d47536653277b7d98e328" +} +], +[ +"type", +{ +"DuckDB": "da08a000bb111759556a61cc", +"None": "df518e3c53cd9a166efacdb4", +"bigquery": "0439c1de159d15c43453a07b", +"databricks": "8352e528bde15549f0d0d870", +"duckdb": "da08a000bb111759556a61cc", +"generic": "df518e3c53cd9a166efacdb4", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "73477f3a6e7e1fd4288ea98f", +"postgres": "df518e3c53cd9a166efacdb4", +"postgresql": "df518e3c53cd9a166efacdb4", +"snowflake": "58581fd57ff3a9d0f74420dc", +"tsql": "e8893244b745b4ab365bbe20" +} +], +[ +"type", +{ +"DuckDB": "1f9deff638e476a7f168220b", +"None": "1f9deff638e476a7f168220b", +"bigquery": "1f9deff638e476a7f168220b", +"databricks": "eeac51d8e73fdd4f598fd1cd", +"duckdb": "1f9deff638e476a7f168220b", +"generic": "1f9deff638e476a7f168220b", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "eeac51d8e73fdd4f598fd1cd", +"postgres": "1f9deff638e476a7f168220b", +"postgresql": "1f9deff638e476a7f168220b", +"snowflake": "1f9deff638e476a7f168220b", +"tsql": "1f9deff638e476a7f168220b" +} +], +[ +"type", +{ +"DuckDB": "ebfad3a0b99f87bcac831ded", +"None": "ebfad3a0b99f87bcac831ded", +"bigquery": "ebfad3a0b99f87bcac831ded", +"databricks": "ebfad3a0b99f87bcac831ded", +"duckdb": "ebfad3a0b99f87bcac831ded", +"generic": "ebfad3a0b99f87bcac831ded", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "ebfad3a0b99f87bcac831ded", +"postgres": "ebfad3a0b99f87bcac831ded", +"postgresql": "ebfad3a0b99f87bcac831ded", +"snowflake": "ebfad3a0b99f87bcac831ded", +"tsql": "ebfad3a0b99f87bcac831ded" +} +], +[ +"type", +{ +"DuckDB": "5620e893a908c6743b863bf6", +"None": "5620e893a908c6743b863bf6", +"bigquery": "4281b54de06f589b3507035a", +"databricks": "4281b54de06f589b3507035a", +"duckdb": "5620e893a908c6743b863bf6", +"generic": "5620e893a908c6743b863bf6", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "4281b54de06f589b3507035a", +"postgres": "5620e893a908c6743b863bf6", +"postgresql": "5620e893a908c6743b863bf6", +"snowflake": "5620e893a908c6743b863bf6", +"tsql": "5620e893a908c6743b863bf6" +} +], +[ +"type", +{ +"DuckDB": "48b9d23d0bb10c99b1325f6b", +"None": "48b9d23d0bb10c99b1325f6b", +"bigquery": "48b9d23d0bb10c99b1325f6b", +"databricks": "48b9d23d0bb10c99b1325f6b", +"duckdb": "48b9d23d0bb10c99b1325f6b", +"generic": "48b9d23d0bb10c99b1325f6b", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "48b9d23d0bb10c99b1325f6b", +"postgres": "48b9d23d0bb10c99b1325f6b", +"postgresql": "48b9d23d0bb10c99b1325f6b", +"snowflake": "48b9d23d0bb10c99b1325f6b", +"tsql": "48b9d23d0bb10c99b1325f6b" +} +], +[ +"type", +{ +"DuckDB": "024a48135994929163b8f97b", +"None": "8f0cf40e26c5ef0cbf1da302", +"bigquery": "8f0cf40e26c5ef0cbf1da302", +"databricks": "8f0cf40e26c5ef0cbf1da302", +"duckdb": "024a48135994929163b8f97b", +"generic": "8f0cf40e26c5ef0cbf1da302", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "6c03a3450ea4742ee7396e3c", +"postgres": "024a48135994929163b8f97b", +"postgresql": "024a48135994929163b8f97b", +"snowflake": "cc36c0fadc1a5838c69f0b9e", +"tsql": "d1dc9a140dbe2eb1874c6ad7" +} +], +[ +"type", +{ +"DuckDB": "4d0f0db1a550ed1e0da1a043", +"None": "4d0f0db1a550ed1e0da1a043", +"bigquery": "4d0f0db1a550ed1e0da1a043", +"databricks": "4d0f0db1a550ed1e0da1a043", +"duckdb": "4d0f0db1a550ed1e0da1a043", +"generic": "4d0f0db1a550ed1e0da1a043", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "4d0f0db1a550ed1e0da1a043", +"postgres": "4d0f0db1a550ed1e0da1a043", +"postgresql": "4d0f0db1a550ed1e0da1a043", +"snowflake": "4d0f0db1a550ed1e0da1a043", +"tsql": "4d0f0db1a550ed1e0da1a043" +} +], +[ +"type", +{ +"DuckDB": "1275b5b0c52f69cf592c004b", +"None": "1275b5b0c52f69cf592c004b", +"bigquery": "1275b5b0c52f69cf592c004b", +"databricks": "1275b5b0c52f69cf592c004b", +"duckdb": "1275b5b0c52f69cf592c004b", +"generic": "1275b5b0c52f69cf592c004b", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "1275b5b0c52f69cf592c004b", +"postgres": "1275b5b0c52f69cf592c004b", +"postgresql": "1275b5b0c52f69cf592c004b", +"snowflake": "1275b5b0c52f69cf592c004b", +"tsql": "1275b5b0c52f69cf592c004b" +} +], +[ +"type", +{ +"DuckDB": "fb5907c56dd752ac5f1dbd95", +"None": "fb5907c56dd752ac5f1dbd95", +"bigquery": "fb5907c56dd752ac5f1dbd95", +"databricks": "fb5907c56dd752ac5f1dbd95", +"duckdb": "fb5907c56dd752ac5f1dbd95", +"generic": "fb5907c56dd752ac5f1dbd95", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "fb5907c56dd752ac5f1dbd95", +"postgres": "fb5907c56dd752ac5f1dbd95", +"postgresql": "fb5907c56dd752ac5f1dbd95", +"snowflake": "fb5907c56dd752ac5f1dbd95", +"tsql": "fb5907c56dd752ac5f1dbd95" +} +], +[ +"type", +{ +"DuckDB": "c82815abe30b3d099903f838", +"None": "c82815abe30b3d099903f838", +"bigquery": "c82815abe30b3d099903f838", +"databricks": "c82815abe30b3d099903f838", +"duckdb": "c82815abe30b3d099903f838", +"generic": "c82815abe30b3d099903f838", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "c82815abe30b3d099903f838", +"postgres": "c82815abe30b3d099903f838", +"postgresql": "c82815abe30b3d099903f838", +"snowflake": "c82815abe30b3d099903f838", +"tsql": "07ca53fdc57a22a78ad75787" +} +], +[ +"type", +{ +"DuckDB": "182a094bae8a9a33f67845ad", +"None": "182a094bae8a9a33f67845ad", +"bigquery": "182a094bae8a9a33f67845ad", +"databricks": "182a094bae8a9a33f67845ad", +"duckdb": "182a094bae8a9a33f67845ad", +"generic": "182a094bae8a9a33f67845ad", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "182a094bae8a9a33f67845ad", +"postgres": "182a094bae8a9a33f67845ad", +"postgresql": "182a094bae8a9a33f67845ad", +"snowflake": "182a094bae8a9a33f67845ad", +"tsql": "182a094bae8a9a33f67845ad" +} +], +[ +"type", +{ +"DuckDB": "f4c43a87a78970bca1f88b09", +"None": "f4c43a87a78970bca1f88b09", +"bigquery": "f4c43a87a78970bca1f88b09", +"databricks": "f4c43a87a78970bca1f88b09", +"duckdb": "f4c43a87a78970bca1f88b09", +"generic": "f4c43a87a78970bca1f88b09", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "f4c43a87a78970bca1f88b09", +"postgres": "f4c43a87a78970bca1f88b09", +"postgresql": "f4c43a87a78970bca1f88b09", +"snowflake": "652ff8b21f638eac8fdc46c5", +"tsql": "f4c43a87a78970bca1f88b09" +} +], +[ +"type", +{ +"DuckDB": "330fec4d6c49ac503e302b43", +"None": "330fec4d6c49ac503e302b43", +"bigquery": "330fec4d6c49ac503e302b43", +"databricks": "330fec4d6c49ac503e302b43", +"duckdb": "330fec4d6c49ac503e302b43", +"generic": "330fec4d6c49ac503e302b43", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "330fec4d6c49ac503e302b43", +"postgres": "f38ef32a483f1c4f89ae309e", +"postgresql": "f38ef32a483f1c4f89ae309e", +"snowflake": "652ff8b21f638eac8fdc46c5", +"tsql": "330fec4d6c49ac503e302b43" +} +], +[ +"type", +{ +"DuckDB": "669084d1ea704ae5b8ee05c2", +"None": "669084d1ea704ae5b8ee05c2", +"bigquery": "669084d1ea704ae5b8ee05c2", +"databricks": "669084d1ea704ae5b8ee05c2", +"duckdb": "669084d1ea704ae5b8ee05c2", +"generic": "669084d1ea704ae5b8ee05c2", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "669084d1ea704ae5b8ee05c2", +"postgres": "669084d1ea704ae5b8ee05c2", +"postgresql": "669084d1ea704ae5b8ee05c2", +"snowflake": "669084d1ea704ae5b8ee05c2", +"tsql": "669084d1ea704ae5b8ee05c2" +} +], +[ +"type", +{ +"DuckDB": "8203bd5901a8ec71ff7c103e", +"None": "8203bd5901a8ec71ff7c103e", +"bigquery": "2a0918be53051fe629d9ff8f", +"databricks": "8203bd5901a8ec71ff7c103e", +"duckdb": "8203bd5901a8ec71ff7c103e", +"generic": "8203bd5901a8ec71ff7c103e", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "8203bd5901a8ec71ff7c103e", +"postgres": "8203bd5901a8ec71ff7c103e", +"postgresql": "8203bd5901a8ec71ff7c103e", +"snowflake": "8203bd5901a8ec71ff7c103e", +"tsql": "8203bd5901a8ec71ff7c103e" +} +], +[ +"type", +{ +"DuckDB": "9ff8ffdba7614214fe44bd7f", +"None": "9ff8ffdba7614214fe44bd7f", +"bigquery": "9ff8ffdba7614214fe44bd7f", +"databricks": "9ff8ffdba7614214fe44bd7f", +"duckdb": "9ff8ffdba7614214fe44bd7f", +"generic": "9ff8ffdba7614214fe44bd7f", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "9ff8ffdba7614214fe44bd7f", +"postgres": "9ff8ffdba7614214fe44bd7f", +"postgresql": "9ff8ffdba7614214fe44bd7f", +"snowflake": "9ff8ffdba7614214fe44bd7f", +"tsql": "9ff8ffdba7614214fe44bd7f" +} +], +[ +"type", +{ +"DuckDB": "05ebf79d18b2ae4eaa41f450", +"None": "336fd1b7a1f7d8105c29280c", +"bigquery": "aa04c66b4fed5190c90308fd", +"databricks": "336fd1b7a1f7d8105c29280c", +"duckdb": "05ebf79d18b2ae4eaa41f450", +"generic": "336fd1b7a1f7d8105c29280c", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "336fd1b7a1f7d8105c29280c", +"postgres": "336fd1b7a1f7d8105c29280c", +"postgresql": "336fd1b7a1f7d8105c29280c", +"snowflake": "336fd1b7a1f7d8105c29280c", +"tsql": "336fd1b7a1f7d8105c29280c" +} +], +[ +"type", +{ +"DuckDB": "fa45b7e4a9ef3b5a9c5781af", +"None": "fa45b7e4a9ef3b5a9c5781af", +"bigquery": "fa45b7e4a9ef3b5a9c5781af", +"databricks": "fa45b7e4a9ef3b5a9c5781af", +"duckdb": "fa45b7e4a9ef3b5a9c5781af", +"generic": "fa45b7e4a9ef3b5a9c5781af", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "fa45b7e4a9ef3b5a9c5781af", +"postgres": "fa45b7e4a9ef3b5a9c5781af", +"postgresql": "fa45b7e4a9ef3b5a9c5781af", +"snowflake": "fa45b7e4a9ef3b5a9c5781af", +"tsql": "fa45b7e4a9ef3b5a9c5781af" +} +], +[ +"type", +{ +"DuckDB": "a22797fa0ef22aadba4ac3ec", +"None": "a22797fa0ef22aadba4ac3ec", +"bigquery": "a22797fa0ef22aadba4ac3ec", +"databricks": "a22797fa0ef22aadba4ac3ec", +"duckdb": "a22797fa0ef22aadba4ac3ec", +"generic": "a22797fa0ef22aadba4ac3ec", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "a22797fa0ef22aadba4ac3ec", +"postgres": "a22797fa0ef22aadba4ac3ec", +"postgresql": "a22797fa0ef22aadba4ac3ec", +"snowflake": "a22797fa0ef22aadba4ac3ec", +"tsql": "a22797fa0ef22aadba4ac3ec" +} +], +[ +"type", +{ +"DuckDB": "881106a4a0d2de0ff7c56373", +"None": "881106a4a0d2de0ff7c56373", +"bigquery": "881106a4a0d2de0ff7c56373", +"databricks": "881106a4a0d2de0ff7c56373", +"duckdb": "881106a4a0d2de0ff7c56373", +"generic": "881106a4a0d2de0ff7c56373", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "881106a4a0d2de0ff7c56373", +"postgres": "881106a4a0d2de0ff7c56373", +"postgresql": "881106a4a0d2de0ff7c56373", +"snowflake": "881106a4a0d2de0ff7c56373", +"tsql": "881106a4a0d2de0ff7c56373" +} +], +[ +"type", +{ +"DuckDB": "2705f19942a4194a72576911", +"None": "2705f19942a4194a72576911", +"bigquery": "6f763a99e9c69109526b40c0", +"databricks": "2705f19942a4194a72576911", +"duckdb": "2705f19942a4194a72576911", +"generic": "2705f19942a4194a72576911", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "2705f19942a4194a72576911", +"postgres": "2705f19942a4194a72576911", +"postgresql": "2705f19942a4194a72576911", +"snowflake": "2705f19942a4194a72576911", +"tsql": "2705f19942a4194a72576911" +} +], +[ +"type", +{ +"DuckDB": "79483dab720e706b74936744", +"None": "79483dab720e706b74936744", +"bigquery": "79483dab720e706b74936744", +"databricks": "79483dab720e706b74936744", +"duckdb": "79483dab720e706b74936744", +"generic": "79483dab720e706b74936744", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "79483dab720e706b74936744", +"postgres": "79483dab720e706b74936744", +"postgresql": "79483dab720e706b74936744", +"snowflake": "79483dab720e706b74936744", +"tsql": "79483dab720e706b74936744" +} +], +[ +"type", +{ +"DuckDB": "7032aa8254308ba815883957", +"None": "7032aa8254308ba815883957", +"bigquery": "7032aa8254308ba815883957", +"databricks": "7032aa8254308ba815883957", +"duckdb": "7032aa8254308ba815883957", +"generic": "7032aa8254308ba815883957", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "7032aa8254308ba815883957", +"postgres": "7032aa8254308ba815883957", +"postgresql": "7032aa8254308ba815883957", +"snowflake": "7032aa8254308ba815883957", +"tsql": "7032aa8254308ba815883957" +} +], +[ +"type", +{ +"DuckDB": "6f763a99e9c69109526b40c0", +"None": "6f763a99e9c69109526b40c0", +"bigquery": "6f763a99e9c69109526b40c0", +"databricks": "6f763a99e9c69109526b40c0", +"duckdb": "6f763a99e9c69109526b40c0", +"generic": "6f763a99e9c69109526b40c0", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "6f763a99e9c69109526b40c0", +"postgres": "6f763a99e9c69109526b40c0", +"postgresql": "6f763a99e9c69109526b40c0", +"snowflake": "2705f19942a4194a72576911", +"tsql": "6f763a99e9c69109526b40c0" +} +], +[ +"type", +{ +"DuckDB": "d9a22eb846c0561f4d74700b", +"None": "d9a22eb846c0561f4d74700b", +"bigquery": "d9a22eb846c0561f4d74700b", +"databricks": "d9a22eb846c0561f4d74700b", +"duckdb": "d9a22eb846c0561f4d74700b", +"generic": "d9a22eb846c0561f4d74700b", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "d9a22eb846c0561f4d74700b", +"postgres": "d9a22eb846c0561f4d74700b", +"postgresql": "d9a22eb846c0561f4d74700b", +"snowflake": "9b5f44707b5f4764b82741be", +"tsql": "d9a22eb846c0561f4d74700b" +} +], +[ +"type", +{ +"DuckDB": "ce3765fd18ee6aff1394ac23", +"None": "ce3765fd18ee6aff1394ac23", +"bigquery": "ce3765fd18ee6aff1394ac23", +"databricks": "ce3765fd18ee6aff1394ac23", +"duckdb": "ce3765fd18ee6aff1394ac23", +"generic": "ce3765fd18ee6aff1394ac23", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "ce3765fd18ee6aff1394ac23", +"postgres": "ce3765fd18ee6aff1394ac23", +"postgresql": "ce3765fd18ee6aff1394ac23", +"snowflake": "ce3765fd18ee6aff1394ac23", +"tsql": "ce3765fd18ee6aff1394ac23" +} +], +[ +"type", +{ +"DuckDB": "70fb4728c3adcf6dbe4975d5", +"None": "70fb4728c3adcf6dbe4975d5", +"bigquery": "70fb4728c3adcf6dbe4975d5", +"databricks": "70fb4728c3adcf6dbe4975d5", +"duckdb": "70fb4728c3adcf6dbe4975d5", +"generic": "70fb4728c3adcf6dbe4975d5", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "70fb4728c3adcf6dbe4975d5", +"postgres": "70fb4728c3adcf6dbe4975d5", +"postgresql": "70fb4728c3adcf6dbe4975d5", +"snowflake": "70fb4728c3adcf6dbe4975d5", +"tsql": "70fb4728c3adcf6dbe4975d5" +} +], +[ +"type", +{ +"DuckDB": "78b2cf275c640af54feeca31", +"None": "78b2cf275c640af54feeca31", +"bigquery": "1e75e5227bea0ae294ac7af1", +"databricks": "78b2cf275c640af54feeca31", +"duckdb": "78b2cf275c640af54feeca31", +"generic": "78b2cf275c640af54feeca31", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "78b2cf275c640af54feeca31", +"postgres": "78b2cf275c640af54feeca31", +"postgresql": "78b2cf275c640af54feeca31", +"snowflake": "8ff614b7306c0edbe36ce00b", +"tsql": "78b2cf275c640af54feeca31" +} +], +[ +"type", +{ +"DuckDB": "87eaac3f093587d1d34762da", +"None": "87eaac3f093587d1d34762da", +"bigquery": "87eaac3f093587d1d34762da", +"databricks": "87eaac3f093587d1d34762da", +"duckdb": "87eaac3f093587d1d34762da", +"generic": "87eaac3f093587d1d34762da", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "87eaac3f093587d1d34762da", +"postgres": "87eaac3f093587d1d34762da", +"postgresql": "87eaac3f093587d1d34762da", +"snowflake": "87eaac3f093587d1d34762da", +"tsql": "87eaac3f093587d1d34762da" +} +], +[ +"type", +{ +"DuckDB": "23ee196b7bd6039855a1460f", +"None": "23ee196b7bd6039855a1460f", +"bigquery": "23ee196b7bd6039855a1460f", +"databricks": "23ee196b7bd6039855a1460f", +"duckdb": "23ee196b7bd6039855a1460f", +"generic": "23ee196b7bd6039855a1460f", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "23ee196b7bd6039855a1460f", +"postgres": "23ee196b7bd6039855a1460f", +"postgresql": "23ee196b7bd6039855a1460f", +"snowflake": "5d25d5e13f81700741695ed4", +"tsql": "23ee196b7bd6039855a1460f" +} +], +[ +"type", +{ +"DuckDB": "aab0389e2b5470136660bf8a", +"None": "aab0389e2b5470136660bf8a", +"bigquery": "c9b810639795a7bfab91b98d", +"databricks": "aab0389e2b5470136660bf8a", +"duckdb": "aab0389e2b5470136660bf8a", +"generic": "aab0389e2b5470136660bf8a", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "aab0389e2b5470136660bf8a", +"postgres": "aab0389e2b5470136660bf8a", +"postgresql": "aab0389e2b5470136660bf8a", +"snowflake": "97a20344d811fb77c7690863", +"tsql": "aab0389e2b5470136660bf8a" +} +], +[ +"type", +{ +"DuckDB": "fe23594c781e79cbb0c8927a", +"None": "fe23594c781e79cbb0c8927a", +"bigquery": "fe23594c781e79cbb0c8927a", +"databricks": "fe23594c781e79cbb0c8927a", +"duckdb": "fe23594c781e79cbb0c8927a", +"generic": "fe23594c781e79cbb0c8927a", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "fe23594c781e79cbb0c8927a", +"postgres": "fe23594c781e79cbb0c8927a", +"postgresql": "fe23594c781e79cbb0c8927a", +"snowflake": "38b2ec94bf02be40007ce525", +"tsql": "fe23594c781e79cbb0c8927a" +} +], +[ +"type", +{ +"DuckDB": "97cf3d84c55104df9751ec06", +"None": "97cf3d84c55104df9751ec06", +"bigquery": "97cf3d84c55104df9751ec06", +"databricks": "97cf3d84c55104df9751ec06", +"duckdb": "97cf3d84c55104df9751ec06", +"generic": "97cf3d84c55104df9751ec06", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "97cf3d84c55104df9751ec06", +"postgres": "97cf3d84c55104df9751ec06", +"postgresql": "97cf3d84c55104df9751ec06", +"snowflake": "97cf3d84c55104df9751ec06", +"tsql": "97cf3d84c55104df9751ec06" +} +], +[ +"type", +{ +"DuckDB": "0703bf71a54942bdaa28406e", +"None": "0703bf71a54942bdaa28406e", +"bigquery": "a428302e4848ffe877284c84", +"databricks": "0703bf71a54942bdaa28406e", +"duckdb": "0703bf71a54942bdaa28406e", +"generic": "0703bf71a54942bdaa28406e", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "0703bf71a54942bdaa28406e", +"postgres": "0703bf71a54942bdaa28406e", +"postgresql": "0703bf71a54942bdaa28406e", +"snowflake": "652ff8b21f638eac8fdc46c5", +"tsql": "441f377c46ddc162ec0a5976" +} +], +[ +"type", +{ +"DuckDB": "18db5afe2c1e80d1ee652b54", +"None": "18db5afe2c1e80d1ee652b54", +"bigquery": "e1c36a5cdd2427ff2b089ac9", +"databricks": "18db5afe2c1e80d1ee652b54", +"duckdb": "18db5afe2c1e80d1ee652b54", +"generic": "18db5afe2c1e80d1ee652b54", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "18db5afe2c1e80d1ee652b54", +"postgres": "18db5afe2c1e80d1ee652b54", +"postgresql": "18db5afe2c1e80d1ee652b54", +"snowflake": "18db5afe2c1e80d1ee652b54", +"tsql": "18db5afe2c1e80d1ee652b54" +} +], +[ +"type", +{ +"DuckDB": "5e46ad7c70253689a5c6bb7f", +"None": "5e46ad7c70253689a5c6bb7f", +"bigquery": "5e46ad7c70253689a5c6bb7f", +"databricks": "5e46ad7c70253689a5c6bb7f", +"duckdb": "5e46ad7c70253689a5c6bb7f", +"generic": "5e46ad7c70253689a5c6bb7f", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "5e46ad7c70253689a5c6bb7f", +"postgres": "5e46ad7c70253689a5c6bb7f", +"postgresql": "5e46ad7c70253689a5c6bb7f", +"snowflake": "5e46ad7c70253689a5c6bb7f", +"tsql": "5e46ad7c70253689a5c6bb7f" +} +], +[ +"type", +{ +"DuckDB": "3147a9e06daa6de4a4df5abc", +"None": "3147a9e06daa6de4a4df5abc", +"bigquery": "f276e907770196606577c932", +"databricks": "3147a9e06daa6de4a4df5abc", +"duckdb": "3147a9e06daa6de4a4df5abc", +"generic": "3147a9e06daa6de4a4df5abc", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "3147a9e06daa6de4a4df5abc", +"postgres": "3147a9e06daa6de4a4df5abc", +"postgresql": "3147a9e06daa6de4a4df5abc", +"snowflake": "67b5874a2c569226c490211f", +"tsql": "3147a9e06daa6de4a4df5abc" +} +], +[ +"type", +{ +"DuckDB": "8789309b90fc585ddbbe90f9", +"None": "8789309b90fc585ddbbe90f9", +"bigquery": "8789309b90fc585ddbbe90f9", +"databricks": "8789309b90fc585ddbbe90f9", +"duckdb": "8789309b90fc585ddbbe90f9", +"generic": "8789309b90fc585ddbbe90f9", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "8789309b90fc585ddbbe90f9", +"postgres": "8789309b90fc585ddbbe90f9", +"postgresql": "8789309b90fc585ddbbe90f9", +"snowflake": "8789309b90fc585ddbbe90f9", +"tsql": "8789309b90fc585ddbbe90f9" +} +], +[ +"type", +{ +"DuckDB": "5990107b647ce24001477492", +"None": "5990107b647ce24001477492", +"bigquery": "5990107b647ce24001477492", +"databricks": "5990107b647ce24001477492", +"duckdb": "5990107b647ce24001477492", +"generic": "5990107b647ce24001477492", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "5990107b647ce24001477492", +"postgres": "5990107b647ce24001477492", +"postgresql": "5990107b647ce24001477492", +"snowflake": "5990107b647ce24001477492", +"tsql": "5990107b647ce24001477492" +} +], +[ +"type", +{ +"DuckDB": "8441d00030df06ad6a5534d3", +"None": "8441d00030df06ad6a5534d3", +"bigquery": "c9b810639795a7bfab91b98d", +"databricks": "8441d00030df06ad6a5534d3", +"duckdb": "8441d00030df06ad6a5534d3", +"generic": "8441d00030df06ad6a5534d3", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "8441d00030df06ad6a5534d3", +"postgres": "8441d00030df06ad6a5534d3", +"postgresql": "8441d00030df06ad6a5534d3", +"snowflake": "97a20344d811fb77c7690863", +"tsql": "8441d00030df06ad6a5534d3" +} +], +[ +"type", +{ +"DuckDB": "f15c56475abfc73488abe63b", +"None": "f15c56475abfc73488abe63b", +"bigquery": "a428302e4848ffe877284c84", +"databricks": "f15c56475abfc73488abe63b", +"duckdb": "f15c56475abfc73488abe63b", +"generic": "f15c56475abfc73488abe63b", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "f15c56475abfc73488abe63b", +"postgres": "f15c56475abfc73488abe63b", +"postgresql": "f15c56475abfc73488abe63b", +"snowflake": "652ff8b21f638eac8fdc46c5", +"tsql": "f15c56475abfc73488abe63b" +} +], +[ +"type", +{ +"DuckDB": "e2879cf4770e7f48d2dd704a", +"None": "e2879cf4770e7f48d2dd704a", +"bigquery": "c9b810639795a7bfab91b98d", +"databricks": "e2879cf4770e7f48d2dd704a", +"duckdb": "e2879cf4770e7f48d2dd704a", +"generic": "e2879cf4770e7f48d2dd704a", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "e2879cf4770e7f48d2dd704a", +"postgres": "e2879cf4770e7f48d2dd704a", +"postgresql": "e2879cf4770e7f48d2dd704a", +"snowflake": "97a20344d811fb77c7690863", +"tsql": "e2879cf4770e7f48d2dd704a" +} +], +[ +"type", +{ +"DuckDB": "8317b957016bdf11135b4836", +"None": "0a21e78538ff353d773b4eea", +"bigquery": "0a21e78538ff353d773b4eea", +"databricks": "0a21e78538ff353d773b4eea", +"duckdb": "8317b957016bdf11135b4836", +"generic": "0a21e78538ff353d773b4eea", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "6c03a3450ea4742ee7396e3c", +"postgres": "8317b957016bdf11135b4836", +"postgresql": "8317b957016bdf11135b4836", +"snowflake": "c2976683dc7003c9f4e8d7d0", +"tsql": "45310b1154cae517b4caedff" +} +], +[ +"type", +{ +"DuckDB": "e72e438b895cc91eaf4be018", +"None": "a1b6a3abd5c2785b419400de", +"bigquery": "f4105e8e41859869d2746e1d", +"databricks": "a1b6a3abd5c2785b419400de", +"duckdb": "e72e438b895cc91eaf4be018", +"generic": "a1b6a3abd5c2785b419400de", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "a1b6a3abd5c2785b419400de", +"postgres": "a1b6a3abd5c2785b419400de", +"postgresql": "a1b6a3abd5c2785b419400de", +"snowflake": "6031cfaf0d57e25f8a111524", +"tsql": "a1b6a3abd5c2785b419400de" +} +], +[ +"type", +{ +"DuckDB": "c729c38d2df6efedc6288247", +"None": "eea1002d88cc68fad7424aca", +"bigquery": "eea1002d88cc68fad7424aca", +"databricks": "eea1002d88cc68fad7424aca", +"duckdb": "c729c38d2df6efedc6288247", +"generic": "eea1002d88cc68fad7424aca", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "eea1002d88cc68fad7424aca", +"postgres": "eea1002d88cc68fad7424aca", +"postgresql": "eea1002d88cc68fad7424aca", +"snowflake": "eea1002d88cc68fad7424aca", +"tsql": "eea1002d88cc68fad7424aca" +} +], +[ +"type", +{ +"DuckDB": "1ebac487198b6c90b027faab", +"None": "1ebac487198b6c90b027faab", +"bigquery": "a428302e4848ffe877284c84", +"databricks": "1ebac487198b6c90b027faab", +"duckdb": "1ebac487198b6c90b027faab", +"generic": "1ebac487198b6c90b027faab", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "1ebac487198b6c90b027faab", +"postgres": "1ebac487198b6c90b027faab", +"postgresql": "1ebac487198b6c90b027faab", +"snowflake": "652ff8b21f638eac8fdc46c5", +"tsql": "c692d974ee3f362ecb38f27c" +} +], +[ +"type", +{ +"DuckDB": "110327dc45eac0e8d54a96dc", +"None": "110327dc45eac0e8d54a96dc", +"bigquery": "1a804f317a3e9a0016925b04", +"databricks": "1a804f317a3e9a0016925b04", +"duckdb": "110327dc45eac0e8d54a96dc", +"generic": "110327dc45eac0e8d54a96dc", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "1a804f317a3e9a0016925b04", +"postgres": "110327dc45eac0e8d54a96dc", +"postgresql": "110327dc45eac0e8d54a96dc", +"snowflake": "110327dc45eac0e8d54a96dc", +"tsql": "110327dc45eac0e8d54a96dc" +} +], +[ +"type", +{ +"DuckDB": "8562dfdaf4f03fa06585b288", +"None": "8562dfdaf4f03fa06585b288", +"bigquery": "8562dfdaf4f03fa06585b288", +"databricks": "8562dfdaf4f03fa06585b288", +"duckdb": "8562dfdaf4f03fa06585b288", +"generic": "8562dfdaf4f03fa06585b288", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "8562dfdaf4f03fa06585b288", +"postgres": "8562dfdaf4f03fa06585b288", +"postgresql": "8562dfdaf4f03fa06585b288", +"snowflake": "8562dfdaf4f03fa06585b288", +"tsql": "8562dfdaf4f03fa06585b288" +} +], +[ +"type", +{ +"DuckDB": "2bfa352725f9d8a91250f75e", +"None": "2bfa352725f9d8a91250f75e", +"bigquery": "2bfa352725f9d8a91250f75e", +"databricks": "2bfa352725f9d8a91250f75e", +"duckdb": "2bfa352725f9d8a91250f75e", +"generic": "2bfa352725f9d8a91250f75e", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "2bfa352725f9d8a91250f75e", +"postgres": "2bfa352725f9d8a91250f75e", +"postgresql": "2bfa352725f9d8a91250f75e", +"snowflake": "2bfa352725f9d8a91250f75e", +"tsql": "2bfa352725f9d8a91250f75e" +} +], +[ +"type", +{ +"DuckDB": "38b2ec94bf02be40007ce525", +"None": "38b2ec94bf02be40007ce525", +"bigquery": "38b2ec94bf02be40007ce525", +"databricks": "38b2ec94bf02be40007ce525", +"duckdb": "38b2ec94bf02be40007ce525", +"generic": "38b2ec94bf02be40007ce525", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "38b2ec94bf02be40007ce525", +"postgres": "38b2ec94bf02be40007ce525", +"postgresql": "38b2ec94bf02be40007ce525", +"snowflake": "38b2ec94bf02be40007ce525", +"tsql": "38b2ec94bf02be40007ce525" +} +], +[ +"type", +{ +"DuckDB": "a428302e4848ffe877284c84", +"None": "a428302e4848ffe877284c84", +"bigquery": "a428302e4848ffe877284c84", +"databricks": "a428302e4848ffe877284c84", +"duckdb": "a428302e4848ffe877284c84", +"generic": "a428302e4848ffe877284c84", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "a428302e4848ffe877284c84", +"postgres": "a428302e4848ffe877284c84", +"postgresql": "a428302e4848ffe877284c84", +"snowflake": "652ff8b21f638eac8fdc46c5", +"tsql": "a428302e4848ffe877284c84" +} +], +[ +"type", +{ +"DuckDB": "a0f9ede1ffaaa874ee2066b3", +"None": "a0f9ede1ffaaa874ee2066b3", +"bigquery": "ba7f36f1ed1e8dae4a3a836e", +"databricks": "0111ff4826a58e7709648841", +"duckdb": "a0f9ede1ffaaa874ee2066b3", +"generic": "a0f9ede1ffaaa874ee2066b3", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "a0f9ede1ffaaa874ee2066b3", +"postgres": "be386e1639549e84c97742c5", +"postgresql": "be386e1639549e84c97742c5", +"snowflake": "8c43a62af28ed0ed164b472b", +"tsql": "a0f9ede1ffaaa874ee2066b3" +} +], +[ +"type", +{ +"DuckDB": "733b04338829c5844270d25e", +"None": "733b04338829c5844270d25e", +"bigquery": "733b04338829c5844270d25e", +"databricks": "733b04338829c5844270d25e", +"duckdb": "733b04338829c5844270d25e", +"generic": "733b04338829c5844270d25e", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "733b04338829c5844270d25e", +"postgres": "733b04338829c5844270d25e", +"postgresql": "733b04338829c5844270d25e", +"snowflake": "733b04338829c5844270d25e", +"tsql": "733b04338829c5844270d25e" +} +], +[ +"type", +{ +"DuckDB": "5abf4ec799a2ec32fb10da7e", +"None": "5abf4ec799a2ec32fb10da7e", +"bigquery": "5abf4ec799a2ec32fb10da7e", +"databricks": "5abf4ec799a2ec32fb10da7e", +"duckdb": "5abf4ec799a2ec32fb10da7e", +"generic": "5abf4ec799a2ec32fb10da7e", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "5abf4ec799a2ec32fb10da7e", +"postgres": "5abf4ec799a2ec32fb10da7e", +"postgresql": "5abf4ec799a2ec32fb10da7e", +"snowflake": "a5656d70e208254d1d3e9b4f", +"tsql": "5abf4ec799a2ec32fb10da7e" +} +], +[ +"type", +{ +"DuckDB": "08736485547ba339930697e9", +"None": "08736485547ba339930697e9", +"bigquery": "08736485547ba339930697e9", +"databricks": "08736485547ba339930697e9", +"duckdb": "08736485547ba339930697e9", +"generic": "08736485547ba339930697e9", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "08736485547ba339930697e9", +"postgres": "08736485547ba339930697e9", +"postgresql": "08736485547ba339930697e9", +"snowflake": "08736485547ba339930697e9", +"tsql": "08736485547ba339930697e9" +} +], +[ +"type", +{ +"DuckDB": "7cd31289a5b99b5a5e24492d", +"None": "7cd31289a5b99b5a5e24492d", +"bigquery": "7cd31289a5b99b5a5e24492d", +"databricks": "7cd31289a5b99b5a5e24492d", +"duckdb": "7cd31289a5b99b5a5e24492d", +"generic": "7cd31289a5b99b5a5e24492d", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "7cd31289a5b99b5a5e24492d", +"postgres": "7cd31289a5b99b5a5e24492d", +"postgresql": "7cd31289a5b99b5a5e24492d", +"snowflake": "7cd31289a5b99b5a5e24492d", +"tsql": "7cd31289a5b99b5a5e24492d" +} +], +[ +"type", +{ +"DuckDB": "a9d9e03f8e981cec9dca7694", +"None": "a9d9e03f8e981cec9dca7694", +"bigquery": "a9d9e03f8e981cec9dca7694", +"databricks": "a9d9e03f8e981cec9dca7694", +"duckdb": "a9d9e03f8e981cec9dca7694", +"generic": "a9d9e03f8e981cec9dca7694", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "a9d9e03f8e981cec9dca7694", +"postgres": "a9d9e03f8e981cec9dca7694", +"postgresql": "a9d9e03f8e981cec9dca7694", +"snowflake": "a9d9e03f8e981cec9dca7694", +"tsql": "a9d9e03f8e981cec9dca7694" +} +], +[ +"type", +{ +"DuckDB": "8b8d5f75ba6dec68b4cebc6b", +"None": "8b8d5f75ba6dec68b4cebc6b", +"bigquery": "8b8d5f75ba6dec68b4cebc6b", +"databricks": "8b8d5f75ba6dec68b4cebc6b", +"duckdb": "8b8d5f75ba6dec68b4cebc6b", +"generic": "8b8d5f75ba6dec68b4cebc6b", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "8b8d5f75ba6dec68b4cebc6b", +"postgres": "8b8d5f75ba6dec68b4cebc6b", +"postgresql": "8b8d5f75ba6dec68b4cebc6b", +"snowflake": "8b8d5f75ba6dec68b4cebc6b", +"tsql": "8b8d5f75ba6dec68b4cebc6b" +} +], +[ +"type", +{ +"DuckDB": "3959952046272deb40567543", +"None": "3959952046272deb40567543", +"bigquery": "3959952046272deb40567543", +"databricks": "3959952046272deb40567543", +"duckdb": "3959952046272deb40567543", +"generic": "3959952046272deb40567543", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "3959952046272deb40567543", +"postgres": "3959952046272deb40567543", +"postgresql": "3959952046272deb40567543", +"snowflake": "3959952046272deb40567543", +"tsql": "3959952046272deb40567543" +} +], +[ +"type", +{ +"DuckDB": "c5d56d00f80f43bfec07a7c2", +"None": "8441d00030df06ad6a5534d3", +"bigquery": "c9b810639795a7bfab91b98d", +"databricks": "8441d00030df06ad6a5534d3", +"duckdb": "c5d56d00f80f43bfec07a7c2", +"generic": "8441d00030df06ad6a5534d3", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "8441d00030df06ad6a5534d3", +"postgres": "8441d00030df06ad6a5534d3", +"postgresql": "8441d00030df06ad6a5534d3", +"snowflake": "97a20344d811fb77c7690863", +"tsql": "8441d00030df06ad6a5534d3" +} +], +[ +"type", +{ +"DuckDB": "251aba3fef503ce64556c701", +"None": "251aba3fef503ce64556c701", +"bigquery": "c50a316d091c821866e4bfba", +"databricks": "251aba3fef503ce64556c701", +"duckdb": "251aba3fef503ce64556c701", +"generic": "251aba3fef503ce64556c701", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "251aba3fef503ce64556c701", +"postgres": "251aba3fef503ce64556c701", +"postgresql": "251aba3fef503ce64556c701", +"snowflake": "c50a316d091c821866e4bfba", +"tsql": "251aba3fef503ce64556c701" +} +], +[ +"type", +{ +"DuckDB": "5855bf076c2cc936300b1e0a", +"None": "5855bf076c2cc936300b1e0a", +"bigquery": "5855bf076c2cc936300b1e0a", +"databricks": "5855bf076c2cc936300b1e0a", +"duckdb": "5855bf076c2cc936300b1e0a", +"generic": "5855bf076c2cc936300b1e0a", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "5855bf076c2cc936300b1e0a", +"postgres": "5855bf076c2cc936300b1e0a", +"postgresql": "5855bf076c2cc936300b1e0a", +"snowflake": "5855bf076c2cc936300b1e0a", +"tsql": "5855bf076c2cc936300b1e0a" +} +], +[ +"type", +{ +"DuckDB": "d9315b336b73c3d8d4b6e9a3", +"None": "f10bdd4d40eb495cbcecd31d", +"bigquery": "f10bdd4d40eb495cbcecd31d", +"databricks": "f10bdd4d40eb495cbcecd31d", +"duckdb": "d9315b336b73c3d8d4b6e9a3", +"generic": "f10bdd4d40eb495cbcecd31d", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "f2ed52f6bf46b4db9343551c", +"postgres": "f2ed52f6bf46b4db9343551c", +"postgresql": "f2ed52f6bf46b4db9343551c", +"snowflake": "f2ed52f6bf46b4db9343551c", +"tsql": "f2ed52f6bf46b4db9343551c" +} +], +[ +"type", +{ +"DuckDB": "e2879cf4770e7f48d2dd704a", +"None": "e2879cf4770e7f48d2dd704a", +"bigquery": "c9b810639795a7bfab91b98d", +"databricks": "e2879cf4770e7f48d2dd704a", +"duckdb": "e2879cf4770e7f48d2dd704a", +"generic": "e2879cf4770e7f48d2dd704a", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "e2879cf4770e7f48d2dd704a", +"postgres": "e2879cf4770e7f48d2dd704a", +"postgresql": "e2879cf4770e7f48d2dd704a", +"snowflake": "97a20344d811fb77c7690863", +"tsql": "e2879cf4770e7f48d2dd704a" +} +], +[ +"type", +{ +"DuckDB": "42f8fe02ce664d09ff39167c", +"None": "42f8fe02ce664d09ff39167c", +"bigquery": "42f8fe02ce664d09ff39167c", +"databricks": "42f8fe02ce664d09ff39167c", +"duckdb": "42f8fe02ce664d09ff39167c", +"generic": "42f8fe02ce664d09ff39167c", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "42f8fe02ce664d09ff39167c", +"postgres": "42f8fe02ce664d09ff39167c", +"postgresql": "42f8fe02ce664d09ff39167c", +"snowflake": "42f8fe02ce664d09ff39167c", +"tsql": "42f8fe02ce664d09ff39167c" +} +], +[ +"type", +{ +"DuckDB": "4ebb6333caac069be16c795d", +"None": "4ebb6333caac069be16c795d", +"bigquery": "4ebb6333caac069be16c795d", +"databricks": "4ebb6333caac069be16c795d", +"duckdb": "4ebb6333caac069be16c795d", +"generic": "4ebb6333caac069be16c795d", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "4ebb6333caac069be16c795d", +"postgres": "4ebb6333caac069be16c795d", +"postgresql": "4ebb6333caac069be16c795d", +"snowflake": "4ebb6333caac069be16c795d", +"tsql": "4ebb6333caac069be16c795d" +} +], +[ +"type", +{ +"DuckDB": "8a3f094f18fb4047f0febf59", +"None": "c844c96e1e3ffc72d5f90df9", +"bigquery": "5c28019dce48a74708c90a76", +"databricks": "c844c96e1e3ffc72d5f90df9", +"duckdb": "8a3f094f18fb4047f0febf59", +"generic": "c844c96e1e3ffc72d5f90df9", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "28eb0d6de9724959ce5ba43e", +"postgres": "c844c96e1e3ffc72d5f90df9", +"postgresql": "c844c96e1e3ffc72d5f90df9", +"snowflake": "c844c96e1e3ffc72d5f90df9", +"tsql": "a4a176ec3c56e2704a650963" +} +], +[ +"type", +{ +"DuckDB": "a428302e4848ffe877284c84", +"None": "a428302e4848ffe877284c84", +"bigquery": "a428302e4848ffe877284c84", +"databricks": "a428302e4848ffe877284c84", +"duckdb": "a428302e4848ffe877284c84", +"generic": "a428302e4848ffe877284c84", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "a428302e4848ffe877284c84", +"postgres": "a428302e4848ffe877284c84", +"postgresql": "a428302e4848ffe877284c84", +"snowflake": "652ff8b21f638eac8fdc46c5", +"tsql": "a428302e4848ffe877284c84" +} +], +[ +"type", +{ +"DuckDB": "8441d00030df06ad6a5534d3", +"None": "8441d00030df06ad6a5534d3", +"bigquery": "c9b810639795a7bfab91b98d", +"databricks": "8441d00030df06ad6a5534d3", +"duckdb": "8441d00030df06ad6a5534d3", +"generic": "8441d00030df06ad6a5534d3", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "8441d00030df06ad6a5534d3", +"postgres": "8441d00030df06ad6a5534d3", +"postgresql": "8441d00030df06ad6a5534d3", +"snowflake": "97a20344d811fb77c7690863", +"tsql": "8441d00030df06ad6a5534d3" +} +], +[ +"type", +{ +"DuckDB": "3915f3f73328f0838497b2d5", +"None": "3915f3f73328f0838497b2d5", +"bigquery": "946d5ee30ab7469c57d850df", +"databricks": "3915f3f73328f0838497b2d5", +"duckdb": "3915f3f73328f0838497b2d5", +"generic": "3915f3f73328f0838497b2d5", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "3915f3f73328f0838497b2d5", +"postgres": "3915f3f73328f0838497b2d5", +"postgresql": "3915f3f73328f0838497b2d5", +"snowflake": "f43dac38f34a1c0618a3f812", +"tsql": "3915f3f73328f0838497b2d5" +} +], +[ +"type", +{ +"DuckDB": "52e79b501b430a4c2b097344", +"None": "52e79b501b430a4c2b097344", +"bigquery": "52e79b501b430a4c2b097344", +"databricks": "52e79b501b430a4c2b097344", +"duckdb": "52e79b501b430a4c2b097344", +"generic": "52e79b501b430a4c2b097344", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "52e79b501b430a4c2b097344", +"postgres": "52e79b501b430a4c2b097344", +"postgresql": "52e79b501b430a4c2b097344", +"snowflake": "52e79b501b430a4c2b097344", +"tsql": "52e79b501b430a4c2b097344" +} +], +[ +"type", +{ +"DuckDB": "13f1401e7cd410600a4c9485", +"None": "13f1401e7cd410600a4c9485", +"bigquery": "74a30f6aa9def0b58afc616c", +"databricks": "13f1401e7cd410600a4c9485", +"duckdb": "13f1401e7cd410600a4c9485", +"generic": "13f1401e7cd410600a4c9485", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "13f1401e7cd410600a4c9485", +"postgres": "13f1401e7cd410600a4c9485", +"postgresql": "13f1401e7cd410600a4c9485", +"snowflake": "9b5f44707b5f4764b82741be", +"tsql": "13f1401e7cd410600a4c9485" +} +], +[ +"type", +{ +"DuckDB": "d2c97d221599d038d9875873", +"None": "d2c97d221599d038d9875873", +"bigquery": "d2c97d221599d038d9875873", +"databricks": "d2c97d221599d038d9875873", +"duckdb": "d2c97d221599d038d9875873", +"generic": "d2c97d221599d038d9875873", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "d2c97d221599d038d9875873", +"postgres": "d2c97d221599d038d9875873", +"postgresql": "d2c97d221599d038d9875873", +"snowflake": "d2c97d221599d038d9875873", +"tsql": "d2c97d221599d038d9875873" +} +], +[ +"type", +{ +"DuckDB": "802f1c1fcb97ddd5679172d2", +"None": "802f1c1fcb97ddd5679172d2", +"bigquery": "a428302e4848ffe877284c84", +"databricks": "802f1c1fcb97ddd5679172d2", +"duckdb": "802f1c1fcb97ddd5679172d2", +"generic": "802f1c1fcb97ddd5679172d2", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "802f1c1fcb97ddd5679172d2", +"postgres": "802f1c1fcb97ddd5679172d2", +"postgresql": "802f1c1fcb97ddd5679172d2", +"snowflake": "652ff8b21f638eac8fdc46c5", +"tsql": "08784560ad78e14a02cc066f" +} +], +[ +"type", +{ +"DuckDB": "60a23b7dcae6c79f4de83068", +"None": "60a23b7dcae6c79f4de83068", +"bigquery": "60a23b7dcae6c79f4de83068", +"databricks": "60a23b7dcae6c79f4de83068", +"duckdb": "60a23b7dcae6c79f4de83068", +"generic": "60a23b7dcae6c79f4de83068", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "60a23b7dcae6c79f4de83068", +"postgres": "60a23b7dcae6c79f4de83068", +"postgresql": "60a23b7dcae6c79f4de83068", +"snowflake": "60a23b7dcae6c79f4de83068", +"tsql": "60a23b7dcae6c79f4de83068" +} +], +[ +"type", +{ +"DuckDB": "4b356542044f1267fcfc487a", +"None": "4b356542044f1267fcfc487a", +"bigquery": "4b356542044f1267fcfc487a", +"databricks": "4b356542044f1267fcfc487a", +"duckdb": "4b356542044f1267fcfc487a", +"generic": "4b356542044f1267fcfc487a", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "4b356542044f1267fcfc487a", +"postgres": "4b356542044f1267fcfc487a", +"postgresql": "4b356542044f1267fcfc487a", +"snowflake": "4b356542044f1267fcfc487a", +"tsql": "4b356542044f1267fcfc487a" +} +], +[ +"type", +{ +"DuckDB": "3315bb12afea7b182498ce28", +"None": "3315bb12afea7b182498ce28", +"bigquery": "3315bb12afea7b182498ce28", +"databricks": "3315bb12afea7b182498ce28", +"duckdb": "3315bb12afea7b182498ce28", +"generic": "3315bb12afea7b182498ce28", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "3315bb12afea7b182498ce28", +"postgres": "3315bb12afea7b182498ce28", +"postgresql": "3315bb12afea7b182498ce28", +"snowflake": "3315bb12afea7b182498ce28", +"tsql": "3315bb12afea7b182498ce28" +} +], +[ +"type", +{ +"DuckDB": "2844656bba2e199281ab8d9b", +"None": "2844656bba2e199281ab8d9b", +"bigquery": "916f1a306af797bd328aec64", +"databricks": "916f1a306af797bd328aec64", +"duckdb": "2844656bba2e199281ab8d9b", +"generic": "2844656bba2e199281ab8d9b", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "916f1a306af797bd328aec64", +"postgres": "2844656bba2e199281ab8d9b", +"postgresql": "2844656bba2e199281ab8d9b", +"snowflake": "2844656bba2e199281ab8d9b", +"tsql": "2844656bba2e199281ab8d9b" +} +], +[ +"type", +{ +"DuckDB": "8a7aa7fa75696327320e0add", +"None": "8a7aa7fa75696327320e0add", +"bigquery": "e62af34c2d31bc9ab880629e", +"databricks": "e62af34c2d31bc9ab880629e", +"duckdb": "8a7aa7fa75696327320e0add", +"generic": "8a7aa7fa75696327320e0add", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "e62af34c2d31bc9ab880629e", +"postgres": "8a7aa7fa75696327320e0add", +"postgresql": "8a7aa7fa75696327320e0add", +"snowflake": "8a7aa7fa75696327320e0add", +"tsql": "8a7aa7fa75696327320e0add" +} +], +[ +"type", +{ +"DuckDB": "cbea30a905a72d3b17dc7211", +"None": "cbea30a905a72d3b17dc7211", +"bigquery": "cbea30a905a72d3b17dc7211", +"databricks": "cbea30a905a72d3b17dc7211", +"duckdb": "cbea30a905a72d3b17dc7211", +"generic": "cbea30a905a72d3b17dc7211", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "cbea30a905a72d3b17dc7211", +"postgres": "cbea30a905a72d3b17dc7211", +"postgresql": "cbea30a905a72d3b17dc7211", +"snowflake": "cbea30a905a72d3b17dc7211", +"tsql": "cbea30a905a72d3b17dc7211" +} +], +[ +"type", +{ +"DuckDB": "f15c56475abfc73488abe63b", +"None": "f15c56475abfc73488abe63b", +"bigquery": "a428302e4848ffe877284c84", +"databricks": "f15c56475abfc73488abe63b", +"duckdb": "f15c56475abfc73488abe63b", +"generic": "f15c56475abfc73488abe63b", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "f15c56475abfc73488abe63b", +"postgres": "f15c56475abfc73488abe63b", +"postgresql": "f15c56475abfc73488abe63b", +"snowflake": "652ff8b21f638eac8fdc46c5", +"tsql": "f15c56475abfc73488abe63b" +} +], +[ +"type", +{ +"DuckDB": "e8b6e0bd2ded7b9eec6209e4", +"None": "e8b6e0bd2ded7b9eec6209e4", +"bigquery": "e8b6e0bd2ded7b9eec6209e4", +"databricks": "e8b6e0bd2ded7b9eec6209e4", +"duckdb": "e8b6e0bd2ded7b9eec6209e4", +"generic": "e8b6e0bd2ded7b9eec6209e4", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "e8b6e0bd2ded7b9eec6209e4", +"postgres": "e8b6e0bd2ded7b9eec6209e4", +"postgresql": "e8b6e0bd2ded7b9eec6209e4", +"snowflake": "e8b6e0bd2ded7b9eec6209e4", +"tsql": "e8b6e0bd2ded7b9eec6209e4" +} +], +[ +"type", +{ +"DuckDB": "1d8b945fd793ecdcacb90c21", +"None": "1d8b945fd793ecdcacb90c21", +"bigquery": "68d2179839f17f0eb289d1aa", +"databricks": "e3bc1b8bad22d8104417b00f", +"duckdb": "1d8b945fd793ecdcacb90c21", +"generic": "1d8b945fd793ecdcacb90c21", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "1d8b945fd793ecdcacb90c21", +"postgres": "3efe8bb57c98fcbe74096b3c", +"postgresql": "3efe8bb57c98fcbe74096b3c", +"snowflake": "1d8b945fd793ecdcacb90c21", +"tsql": "1d8b945fd793ecdcacb90c21" +} +], +[ +"type", +{ +"DuckDB": "4e10d2f9eb8994ead08d1761", +"None": "4e10d2f9eb8994ead08d1761", +"bigquery": "4e10d2f9eb8994ead08d1761", +"databricks": "4e10d2f9eb8994ead08d1761", +"duckdb": "4e10d2f9eb8994ead08d1761", +"generic": "4e10d2f9eb8994ead08d1761", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "4e10d2f9eb8994ead08d1761", +"postgres": "4e10d2f9eb8994ead08d1761", +"postgresql": "4e10d2f9eb8994ead08d1761", +"snowflake": "4e10d2f9eb8994ead08d1761", +"tsql": "4e10d2f9eb8994ead08d1761" +} +], +[ +"type", +{ +"DuckDB": "3f71ab5f3c1c040da96f2cec", +"None": "3f71ab5f3c1c040da96f2cec", +"bigquery": "3f71ab5f3c1c040da96f2cec", +"databricks": "3f71ab5f3c1c040da96f2cec", +"duckdb": "3f71ab5f3c1c040da96f2cec", +"generic": "3f71ab5f3c1c040da96f2cec", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "3f71ab5f3c1c040da96f2cec", +"postgres": "3f71ab5f3c1c040da96f2cec", +"postgresql": "3f71ab5f3c1c040da96f2cec", +"snowflake": "3f71ab5f3c1c040da96f2cec", +"tsql": "3f71ab5f3c1c040da96f2cec" +} +], +[ +"type", +{ +"DuckDB": "35e216b6921bf843994f2eea", +"None": "46ec3e19e05a6cb29854ccac", +"bigquery": "46ec3e19e05a6cb29854ccac", +"databricks": "46ec3e19e05a6cb29854ccac", +"duckdb": "35e216b6921bf843994f2eea", +"generic": "46ec3e19e05a6cb29854ccac", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "46ec3e19e05a6cb29854ccac", +"postgres": "46ec3e19e05a6cb29854ccac", +"postgresql": "46ec3e19e05a6cb29854ccac", +"snowflake": "46ec3e19e05a6cb29854ccac", +"tsql": "46ec3e19e05a6cb29854ccac" +} +], +[ +"type", +{ +"DuckDB": "7515c0db413239044adef879", +"None": "7515c0db413239044adef879", +"bigquery": "f276e907770196606577c932", +"databricks": "7515c0db413239044adef879", +"duckdb": "7515c0db413239044adef879", +"generic": "7515c0db413239044adef879", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "7515c0db413239044adef879", +"postgres": "7515c0db413239044adef879", +"postgresql": "7515c0db413239044adef879", +"snowflake": "67b5874a2c569226c490211f", +"tsql": "7515c0db413239044adef879" +} +], +[ +"type", +{ +"DuckDB": "a428302e4848ffe877284c84", +"None": "a428302e4848ffe877284c84", +"bigquery": "a428302e4848ffe877284c84", +"databricks": "a428302e4848ffe877284c84", +"duckdb": "a428302e4848ffe877284c84", +"generic": "a428302e4848ffe877284c84", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "a428302e4848ffe877284c84", +"postgres": "a428302e4848ffe877284c84", +"postgresql": "a428302e4848ffe877284c84", +"snowflake": "652ff8b21f638eac8fdc46c5", +"tsql": "a428302e4848ffe877284c84" +} +], +[ +"type", +{ +"DuckDB": "4662a1758442ce44b830269f", +"None": "4662a1758442ce44b830269f", +"bigquery": "4662a1758442ce44b830269f", +"databricks": "4662a1758442ce44b830269f", +"duckdb": "4662a1758442ce44b830269f", +"generic": "4662a1758442ce44b830269f", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "4662a1758442ce44b830269f", +"postgres": "4662a1758442ce44b830269f", +"postgresql": "4662a1758442ce44b830269f", +"snowflake": "4662a1758442ce44b830269f", +"tsql": "4662a1758442ce44b830269f" +} +], +[ +"type", +{ +"DuckDB": "a55ce7977ac874a3b204217e", +"None": "86b982a98982cd844f498c36", +"bigquery": "86b982a98982cd844f498c36", +"databricks": "86b982a98982cd844f498c36", +"duckdb": "a55ce7977ac874a3b204217e", +"generic": "86b982a98982cd844f498c36", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "6c03a3450ea4742ee7396e3c", +"postgres": "a55ce7977ac874a3b204217e", +"postgresql": "a55ce7977ac874a3b204217e", +"snowflake": "5a4429eb67014c1c8f9e10d4", +"tsql": "a13763a505b15f311cd22d08" +} +], +[ +"type", +{ +"DuckDB": "62368fc15cefd5807807b209", +"None": "62368fc15cefd5807807b209", +"bigquery": "e6ffdece2977be55da73b59a", +"databricks": "62368fc15cefd5807807b209", +"duckdb": "62368fc15cefd5807807b209", +"generic": "62368fc15cefd5807807b209", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "62368fc15cefd5807807b209", +"postgres": "62368fc15cefd5807807b209", +"postgresql": "62368fc15cefd5807807b209", +"snowflake": "62368fc15cefd5807807b209", +"tsql": "62368fc15cefd5807807b209" +} +], +[ +"type", +{ +"DuckDB": "bbb97828cd28c64282709796", +"None": "bbb97828cd28c64282709796", +"bigquery": "bbb97828cd28c64282709796", +"databricks": "bbb97828cd28c64282709796", +"duckdb": "bbb97828cd28c64282709796", +"generic": "bbb97828cd28c64282709796", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "bbb97828cd28c64282709796", +"postgres": "bbb97828cd28c64282709796", +"postgresql": "bbb97828cd28c64282709796", +"snowflake": "bbb97828cd28c64282709796", +"tsql": "bbb97828cd28c64282709796" +} +], +[ +"type", +{ +"DuckDB": "3f71ab5f3c1c040da96f2cec", +"None": "3f71ab5f3c1c040da96f2cec", +"bigquery": "3f71ab5f3c1c040da96f2cec", +"databricks": "3f71ab5f3c1c040da96f2cec", +"duckdb": "3f71ab5f3c1c040da96f2cec", +"generic": "3f71ab5f3c1c040da96f2cec", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "3f71ab5f3c1c040da96f2cec", +"postgres": "3f71ab5f3c1c040da96f2cec", +"postgresql": "3f71ab5f3c1c040da96f2cec", +"snowflake": "3f71ab5f3c1c040da96f2cec", +"tsql": "3f71ab5f3c1c040da96f2cec" +} +], +[ +"type", +{ +"DuckDB": "38b2ec94bf02be40007ce525", +"None": "38b2ec94bf02be40007ce525", +"bigquery": "38b2ec94bf02be40007ce525", +"databricks": "38b2ec94bf02be40007ce525", +"duckdb": "38b2ec94bf02be40007ce525", +"generic": "38b2ec94bf02be40007ce525", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "38b2ec94bf02be40007ce525", +"postgres": "38b2ec94bf02be40007ce525", +"postgresql": "38b2ec94bf02be40007ce525", +"snowflake": "38b2ec94bf02be40007ce525", +"tsql": "38b2ec94bf02be40007ce525" +} +], +[ +"type", +{ +"DuckDB": "02861a11fe2b8f1a7351cb12", +"None": "3abc5e3c14192017bfd1ead5", +"bigquery": "f2c7751cca55dc87c36b6fc2", +"databricks": "f2c7751cca55dc87c36b6fc2", +"duckdb": "02861a11fe2b8f1a7351cb12", +"generic": "3abc5e3c14192017bfd1ead5", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "f2c7751cca55dc87c36b6fc2", +"postgres": "35efca2fc5df9bbd4013257a", +"postgresql": "35efca2fc5df9bbd4013257a", +"snowflake": "5b65e3054ea3260a0a6dd837", +"tsql": "f2c7751cca55dc87c36b6fc2" +} +], +[ +"type", +{ +"DuckDB": "d1a9a884331f069d89b0935f", +"None": "d1a9a884331f069d89b0935f", +"bigquery": "efe77000c8cb77e8bcc49328", +"databricks": "efe77000c8cb77e8bcc49328", +"duckdb": "d1a9a884331f069d89b0935f", +"generic": "d1a9a884331f069d89b0935f", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "efe77000c8cb77e8bcc49328", +"postgres": "d1a9a884331f069d89b0935f", +"postgresql": "d1a9a884331f069d89b0935f", +"snowflake": "d1a9a884331f069d89b0935f", +"tsql": "d1a9a884331f069d89b0935f" +} +], +[ +"type", +{ +"DuckDB": "ebc821a95b9286e22c2b26d0", +"None": "ebc821a95b9286e22c2b26d0", +"bigquery": "19a1a80ffc06169f32694de8", +"databricks": "ebc821a95b9286e22c2b26d0", +"duckdb": "ebc821a95b9286e22c2b26d0", +"generic": "ebc821a95b9286e22c2b26d0", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "ebc821a95b9286e22c2b26d0", +"postgres": "ebc821a95b9286e22c2b26d0", +"postgresql": "ebc821a95b9286e22c2b26d0", +"snowflake": "ebc821a95b9286e22c2b26d0", +"tsql": "ebc821a95b9286e22c2b26d0" +} +], +[ +"type", +{ +"DuckDB": "bce60580ef3a1dc4ce569fff", +"None": "bce60580ef3a1dc4ce569fff", +"bigquery": "bce60580ef3a1dc4ce569fff", +"databricks": "bce60580ef3a1dc4ce569fff", +"duckdb": "bce60580ef3a1dc4ce569fff", +"generic": "bce60580ef3a1dc4ce569fff", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "bce60580ef3a1dc4ce569fff", +"postgres": "bce60580ef3a1dc4ce569fff", +"postgresql": "bce60580ef3a1dc4ce569fff", +"snowflake": "bce60580ef3a1dc4ce569fff", +"tsql": "bce60580ef3a1dc4ce569fff" +} +], +[ +"type", +{ +"DuckDB": "aab0389e2b5470136660bf8a", +"None": "aab0389e2b5470136660bf8a", +"bigquery": "c9b810639795a7bfab91b98d", +"databricks": "aab0389e2b5470136660bf8a", +"duckdb": "aab0389e2b5470136660bf8a", +"generic": "aab0389e2b5470136660bf8a", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "aab0389e2b5470136660bf8a", +"postgres": "aab0389e2b5470136660bf8a", +"postgresql": "aab0389e2b5470136660bf8a", +"snowflake": "97a20344d811fb77c7690863", +"tsql": "aab0389e2b5470136660bf8a" +} +], +[ +"type", +{ +"DuckDB": "cc33965a669608ec39e8c246", +"None": "cc33965a669608ec39e8c246", +"bigquery": "cc33965a669608ec39e8c246", +"databricks": "cc33965a669608ec39e8c246", +"duckdb": "cc33965a669608ec39e8c246", +"generic": "cc33965a669608ec39e8c246", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "cc33965a669608ec39e8c246", +"postgres": "cc33965a669608ec39e8c246", +"postgresql": "cc33965a669608ec39e8c246", +"snowflake": "cc33965a669608ec39e8c246", +"tsql": "cc33965a669608ec39e8c246" +} +], +[ +"type", +{ +"DuckDB": "4381456d770bb42050076d00", +"None": "4381456d770bb42050076d00", +"bigquery": "4381456d770bb42050076d00", +"databricks": "4381456d770bb42050076d00", +"duckdb": "4381456d770bb42050076d00", +"generic": "4381456d770bb42050076d00", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "4381456d770bb42050076d00", +"postgres": "4381456d770bb42050076d00", +"postgresql": "4381456d770bb42050076d00", +"snowflake": "4381456d770bb42050076d00", +"tsql": "4381456d770bb42050076d00" +} +], +[ +"type", +{ +"DuckDB": "a34c63be87b77d81239d0b4b", +"None": "a34c63be87b77d81239d0b4b", +"bigquery": "a34c63be87b77d81239d0b4b", +"databricks": "a34c63be87b77d81239d0b4b", +"duckdb": "a34c63be87b77d81239d0b4b", +"generic": "a34c63be87b77d81239d0b4b", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "a34c63be87b77d81239d0b4b", +"postgres": "a34c63be87b77d81239d0b4b", +"postgresql": "a34c63be87b77d81239d0b4b", +"snowflake": "a34c63be87b77d81239d0b4b", +"tsql": "a34c63be87b77d81239d0b4b" +} +], +[ +"type", +{ +"DuckDB": "d61c83ef8bfdf043fa672cb5", +"None": "d61c83ef8bfdf043fa672cb5", +"bigquery": "c9b810639795a7bfab91b98d", +"databricks": "d61c83ef8bfdf043fa672cb5", +"duckdb": "d61c83ef8bfdf043fa672cb5", +"generic": "d61c83ef8bfdf043fa672cb5", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "d61c83ef8bfdf043fa672cb5", +"postgres": "d61c83ef8bfdf043fa672cb5", +"postgresql": "d61c83ef8bfdf043fa672cb5", +"snowflake": "97a20344d811fb77c7690863", +"tsql": "d61c83ef8bfdf043fa672cb5" +} +], +[ +"type", +{ +"DuckDB": "0703bf71a54942bdaa28406e", +"None": "0703bf71a54942bdaa28406e", +"bigquery": "a428302e4848ffe877284c84", +"databricks": "0703bf71a54942bdaa28406e", +"duckdb": "0703bf71a54942bdaa28406e", +"generic": "0703bf71a54942bdaa28406e", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "0703bf71a54942bdaa28406e", +"postgres": "0703bf71a54942bdaa28406e", +"postgresql": "0703bf71a54942bdaa28406e", +"snowflake": "652ff8b21f638eac8fdc46c5", +"tsql": "441f377c46ddc162ec0a5976" +} +], +[ +"type", +{ +"DuckDB": "0d58e20cd83f047b3b85cd1c", +"None": "0d58e20cd83f047b3b85cd1c", +"bigquery": "0d58e20cd83f047b3b85cd1c", +"databricks": "9f2957c784cb1f6b640c10f7", +"duckdb": "0d58e20cd83f047b3b85cd1c", +"generic": "0d58e20cd83f047b3b85cd1c", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "9f2957c784cb1f6b640c10f7", +"postgres": "0d58e20cd83f047b3b85cd1c", +"postgresql": "0d58e20cd83f047b3b85cd1c", +"snowflake": "0d58e20cd83f047b3b85cd1c", +"tsql": "0d58e20cd83f047b3b85cd1c" +} +], +[ +"type", +{ +"DuckDB": "fe23594c781e79cbb0c8927a", +"None": "fe23594c781e79cbb0c8927a", +"bigquery": "fe23594c781e79cbb0c8927a", +"databricks": "fe23594c781e79cbb0c8927a", +"duckdb": "fe23594c781e79cbb0c8927a", +"generic": "fe23594c781e79cbb0c8927a", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "fe23594c781e79cbb0c8927a", +"postgres": "fe23594c781e79cbb0c8927a", +"postgresql": "fe23594c781e79cbb0c8927a", +"snowflake": "38b2ec94bf02be40007ce525", +"tsql": "fe23594c781e79cbb0c8927a" +} +], +[ +"type", +{ +"DuckDB": "63e20906fe3504356e04d05e", +"None": "dba9493579be12efd69318ac", +"bigquery": "dba9493579be12efd69318ac", +"databricks": "dba9493579be12efd69318ac", +"duckdb": "63e20906fe3504356e04d05e", +"generic": "dba9493579be12efd69318ac", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "6c03a3450ea4742ee7396e3c", +"postgres": "63e20906fe3504356e04d05e", +"postgresql": "63e20906fe3504356e04d05e", +"snowflake": "30696690153e91e7ae197982", +"tsql": "d5df2c68a7c80c4cabfc9444" +} +], +[ +"type", +{ +"DuckDB": "7914189ff18b0e70ddf7d042", +"None": "7914189ff18b0e70ddf7d042", +"bigquery": "b0477b36767a62145aa9158c", +"databricks": "7914189ff18b0e70ddf7d042", +"duckdb": "7914189ff18b0e70ddf7d042", +"generic": "7914189ff18b0e70ddf7d042", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "7914189ff18b0e70ddf7d042", +"postgres": "7914189ff18b0e70ddf7d042", +"postgresql": "7914189ff18b0e70ddf7d042", +"snowflake": "652ff8b21f638eac8fdc46c5", +"tsql": "7914189ff18b0e70ddf7d042" +} +], +[ +"type", +{ +"DuckDB": "919b7ec6a7b49d8527b784cd", +"None": "919b7ec6a7b49d8527b784cd", +"bigquery": "204206d1d1eecf007966cc5b", +"databricks": "e3bc1b8bad22d8104417b00f", +"duckdb": "919b7ec6a7b49d8527b784cd", +"generic": "919b7ec6a7b49d8527b784cd", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "919b7ec6a7b49d8527b784cd", +"postgres": "a3b6b25265be330ec52a3322", +"postgresql": "a3b6b25265be330ec52a3322", +"snowflake": "919b7ec6a7b49d8527b784cd", +"tsql": "919b7ec6a7b49d8527b784cd" +} +], +[ +"type", +{ +"DuckDB": "42cd2b5892468e185781348b", +"None": "42cd2b5892468e185781348b", +"bigquery": "316ab5126bbd68359eedc4d9", +"databricks": "42cd2b5892468e185781348b", +"duckdb": "42cd2b5892468e185781348b", +"generic": "42cd2b5892468e185781348b", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "42cd2b5892468e185781348b", +"postgres": "42cd2b5892468e185781348b", +"postgresql": "42cd2b5892468e185781348b", +"snowflake": "652ff8b21f638eac8fdc46c5", +"tsql": "42cd2b5892468e185781348b" +} +], +[ +"type", +{ +"DuckDB": "35e216b6921bf843994f2eea", +"None": "46ec3e19e05a6cb29854ccac", +"bigquery": "46ec3e19e05a6cb29854ccac", +"databricks": "46ec3e19e05a6cb29854ccac", +"duckdb": "35e216b6921bf843994f2eea", +"generic": "46ec3e19e05a6cb29854ccac", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "46ec3e19e05a6cb29854ccac", +"postgres": "46ec3e19e05a6cb29854ccac", +"postgresql": "46ec3e19e05a6cb29854ccac", +"snowflake": "46ec3e19e05a6cb29854ccac", +"tsql": "46ec3e19e05a6cb29854ccac" +} +], +[ +"type", +{ +"DuckDB": "eed0645c1e86fa1a6e35ccaa", +"None": "eed0645c1e86fa1a6e35ccaa", +"bigquery": "013a8446f043affffcf194f8", +"databricks": "eed0645c1e86fa1a6e35ccaa", +"duckdb": "eed0645c1e86fa1a6e35ccaa", +"generic": "eed0645c1e86fa1a6e35ccaa", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "eed0645c1e86fa1a6e35ccaa", +"postgres": "eed0645c1e86fa1a6e35ccaa", +"postgresql": "eed0645c1e86fa1a6e35ccaa", +"snowflake": "97a20344d811fb77c7690863", +"tsql": "eed0645c1e86fa1a6e35ccaa" +} +], +[ +"type", +{ +"DuckDB": "a428302e4848ffe877284c84", +"None": "a428302e4848ffe877284c84", +"bigquery": "a428302e4848ffe877284c84", +"databricks": "a428302e4848ffe877284c84", +"duckdb": "a428302e4848ffe877284c84", +"generic": "a428302e4848ffe877284c84", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "a428302e4848ffe877284c84", +"postgres": "a428302e4848ffe877284c84", +"postgresql": "a428302e4848ffe877284c84", +"snowflake": "652ff8b21f638eac8fdc46c5", +"tsql": "a428302e4848ffe877284c84" +} +], +[ +"type", +{ +"DuckDB": "e57ac1541fb51b362cd5b470", +"None": "e57ac1541fb51b362cd5b470", +"bigquery": "e57ac1541fb51b362cd5b470", +"databricks": "e57ac1541fb51b362cd5b470", +"duckdb": "e57ac1541fb51b362cd5b470", +"generic": "e57ac1541fb51b362cd5b470", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "e57ac1541fb51b362cd5b470", +"postgres": "e57ac1541fb51b362cd5b470", +"postgresql": "e57ac1541fb51b362cd5b470", +"snowflake": "4b356542044f1267fcfc487a", +"tsql": "e57ac1541fb51b362cd5b470" +} +], +[ +"type", +{ +"DuckDB": "0f3d33062aebbc5edec7b64f", +"None": "0f3d33062aebbc5edec7b64f", +"bigquery": "0f3d33062aebbc5edec7b64f", +"databricks": "544d1979b70121c2f5770b6a", +"duckdb": "0f3d33062aebbc5edec7b64f", +"generic": "0f3d33062aebbc5edec7b64f", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "544d1979b70121c2f5770b6a", +"postgres": "0f3d33062aebbc5edec7b64f", +"postgresql": "0f3d33062aebbc5edec7b64f", +"snowflake": "0f3d33062aebbc5edec7b64f", +"tsql": "0f3d33062aebbc5edec7b64f" +} +], +[ +"type", +{ +"DuckDB": "b2c9b6ebca6c097f3caa0aa8", +"None": "b2c9b6ebca6c097f3caa0aa8", +"bigquery": "b2c9b6ebca6c097f3caa0aa8", +"databricks": "b2c9b6ebca6c097f3caa0aa8", +"duckdb": "b2c9b6ebca6c097f3caa0aa8", +"generic": "b2c9b6ebca6c097f3caa0aa8", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "b2c9b6ebca6c097f3caa0aa8", +"postgres": "b2c9b6ebca6c097f3caa0aa8", +"postgresql": "b2c9b6ebca6c097f3caa0aa8", +"snowflake": "b2c9b6ebca6c097f3caa0aa8", +"tsql": "b2c9b6ebca6c097f3caa0aa8" +} +], +[ +"type", +{ +"DuckDB": "c21a08c5ec73e14b4d409300", +"None": "c21a08c5ec73e14b4d409300", +"bigquery": "c21a08c5ec73e14b4d409300", +"databricks": "c21a08c5ec73e14b4d409300", +"duckdb": "c21a08c5ec73e14b4d409300", +"generic": "c21a08c5ec73e14b4d409300", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "c21a08c5ec73e14b4d409300", +"postgres": "c21a08c5ec73e14b4d409300", +"postgresql": "c21a08c5ec73e14b4d409300", +"snowflake": "c21a08c5ec73e14b4d409300", +"tsql": "c21a08c5ec73e14b4d409300" +} +], +[ +"type", +{ +"DuckDB": "fe23594c781e79cbb0c8927a", +"None": "fe23594c781e79cbb0c8927a", +"bigquery": "fe23594c781e79cbb0c8927a", +"databricks": "fe23594c781e79cbb0c8927a", +"duckdb": "fe23594c781e79cbb0c8927a", +"generic": "fe23594c781e79cbb0c8927a", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "fe23594c781e79cbb0c8927a", +"postgres": "fe23594c781e79cbb0c8927a", +"postgresql": "fe23594c781e79cbb0c8927a", +"snowflake": "38b2ec94bf02be40007ce525", +"tsql": "fe23594c781e79cbb0c8927a" +} +], +[ +"type", +{ +"DuckDB": "88582da8542d7d1abf567520", +"None": "88582da8542d7d1abf567520", +"bigquery": "88582da8542d7d1abf567520", +"databricks": "88582da8542d7d1abf567520", +"duckdb": "88582da8542d7d1abf567520", +"generic": "88582da8542d7d1abf567520", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "88582da8542d7d1abf567520", +"postgres": "88582da8542d7d1abf567520", +"postgresql": "88582da8542d7d1abf567520", +"snowflake": "88582da8542d7d1abf567520", +"tsql": "88582da8542d7d1abf567520" +} +], +[ +"type", +{ +"DuckDB": "8a10388471810a2bd58f7686", +"None": "8a10388471810a2bd58f7686", +"bigquery": "8a10388471810a2bd58f7686", +"databricks": "8a10388471810a2bd58f7686", +"duckdb": "8a10388471810a2bd58f7686", +"generic": "8a10388471810a2bd58f7686", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "8a10388471810a2bd58f7686", +"postgres": "8a10388471810a2bd58f7686", +"postgresql": "8a10388471810a2bd58f7686", +"snowflake": "8a10388471810a2bd58f7686", +"tsql": "8a10388471810a2bd58f7686" +} +], +[ +"type", +{ +"DuckDB": "ebc821a95b9286e22c2b26d0", +"None": "ebc821a95b9286e22c2b26d0", +"bigquery": "19a1a80ffc06169f32694de8", +"databricks": "ebc821a95b9286e22c2b26d0", +"duckdb": "ebc821a95b9286e22c2b26d0", +"generic": "ebc821a95b9286e22c2b26d0", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "ebc821a95b9286e22c2b26d0", +"postgres": "ebc821a95b9286e22c2b26d0", +"postgresql": "ebc821a95b9286e22c2b26d0", +"snowflake": "ebc821a95b9286e22c2b26d0", +"tsql": "ebc821a95b9286e22c2b26d0" +} +], +[ +"type", +{ +"DuckDB": "64fc778308b798a730b1d5c9", +"None": "64fc778308b798a730b1d5c9", +"bigquery": "64fc778308b798a730b1d5c9", +"databricks": "64fc778308b798a730b1d5c9", +"duckdb": "64fc778308b798a730b1d5c9", +"generic": "64fc778308b798a730b1d5c9", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "64fc778308b798a730b1d5c9", +"postgres": "64fc778308b798a730b1d5c9", +"postgresql": "64fc778308b798a730b1d5c9", +"snowflake": "64fc778308b798a730b1d5c9", +"tsql": "64fc778308b798a730b1d5c9" +} +], +[ +"type", +{ +"DuckDB": "679a90349a55ba7765c07664", +"None": "679a90349a55ba7765c07664", +"bigquery": "679a90349a55ba7765c07664", +"databricks": "679a90349a55ba7765c07664", +"duckdb": "679a90349a55ba7765c07664", +"generic": "679a90349a55ba7765c07664", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "679a90349a55ba7765c07664", +"postgres": "679a90349a55ba7765c07664", +"postgresql": "679a90349a55ba7765c07664", +"snowflake": "679a90349a55ba7765c07664", +"tsql": "679a90349a55ba7765c07664" +} +], +[ +"type", +{ +"DuckDB": "3f71ab5f3c1c040da96f2cec", +"None": "3f71ab5f3c1c040da96f2cec", +"bigquery": "3f71ab5f3c1c040da96f2cec", +"databricks": "3f71ab5f3c1c040da96f2cec", +"duckdb": "3f71ab5f3c1c040da96f2cec", +"generic": "3f71ab5f3c1c040da96f2cec", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "3f71ab5f3c1c040da96f2cec", +"postgres": "3f71ab5f3c1c040da96f2cec", +"postgresql": "3f71ab5f3c1c040da96f2cec", +"snowflake": "3f71ab5f3c1c040da96f2cec", +"tsql": "3f71ab5f3c1c040da96f2cec" +} +], +[ +"type", +{ +"DuckDB": "3147a9e06daa6de4a4df5abc", +"None": "3147a9e06daa6de4a4df5abc", +"bigquery": "f276e907770196606577c932", +"databricks": "3147a9e06daa6de4a4df5abc", +"duckdb": "3147a9e06daa6de4a4df5abc", +"generic": "3147a9e06daa6de4a4df5abc", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "3147a9e06daa6de4a4df5abc", +"postgres": "3147a9e06daa6de4a4df5abc", +"postgresql": "3147a9e06daa6de4a4df5abc", +"snowflake": "67b5874a2c569226c490211f", +"tsql": "3147a9e06daa6de4a4df5abc" +} +], +[ +"type", +{ +"DuckDB": "ff99ba717583eafc6fdd9442", +"None": "a915140f475538632ca59017", +"bigquery": "a915140f475538632ca59017", +"databricks": "a915140f475538632ca59017", +"duckdb": "ff99ba717583eafc6fdd9442", +"generic": "a915140f475538632ca59017", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "6c03a3450ea4742ee7396e3c", +"postgres": "39ac50273811909ae35979b7", +"postgresql": "39ac50273811909ae35979b7", +"snowflake": "ca443b97e784bced05b62f0b", +"tsql": "3b16d8eb223ae1333ecbc2bf" +} +], +[ +"type", +{ +"DuckDB": "e7683084f9cefaf3748cf526", +"None": "e7683084f9cefaf3748cf526", +"bigquery": "e7683084f9cefaf3748cf526", +"databricks": "e7683084f9cefaf3748cf526", +"duckdb": "e7683084f9cefaf3748cf526", +"generic": "e7683084f9cefaf3748cf526", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "e7683084f9cefaf3748cf526", +"postgres": "e7683084f9cefaf3748cf526", +"postgresql": "e7683084f9cefaf3748cf526", +"snowflake": "e7683084f9cefaf3748cf526", +"tsql": "e7683084f9cefaf3748cf526" +} +], +[ +"type", +{ +"DuckDB": "9626d393c137a37008bb4b89", +"None": "9626d393c137a37008bb4b89", +"bigquery": "9626d393c137a37008bb4b89", +"databricks": "9626d393c137a37008bb4b89", +"duckdb": "9626d393c137a37008bb4b89", +"generic": "9626d393c137a37008bb4b89", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "9626d393c137a37008bb4b89", +"postgres": "9626d393c137a37008bb4b89", +"postgresql": "9626d393c137a37008bb4b89", +"snowflake": "9626d393c137a37008bb4b89", +"tsql": "9626d393c137a37008bb4b89" +} +], +[ +"type", +{ +"DuckDB": "669084d1ea704ae5b8ee05c2", +"None": "669084d1ea704ae5b8ee05c2", +"bigquery": "669084d1ea704ae5b8ee05c2", +"databricks": "669084d1ea704ae5b8ee05c2", +"duckdb": "669084d1ea704ae5b8ee05c2", +"generic": "669084d1ea704ae5b8ee05c2", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "669084d1ea704ae5b8ee05c2", +"postgres": "669084d1ea704ae5b8ee05c2", +"postgresql": "669084d1ea704ae5b8ee05c2", +"snowflake": "669084d1ea704ae5b8ee05c2", +"tsql": "669084d1ea704ae5b8ee05c2" +} +], +[ +"type", +{ +"DuckDB": "4e47cae1f2f84f5e523dc43f", +"None": "4e47cae1f2f84f5e523dc43f", +"bigquery": "4e47cae1f2f84f5e523dc43f", +"databricks": "4e47cae1f2f84f5e523dc43f", +"duckdb": "4e47cae1f2f84f5e523dc43f", +"generic": "4e47cae1f2f84f5e523dc43f", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "4e47cae1f2f84f5e523dc43f", +"postgres": "4e47cae1f2f84f5e523dc43f", +"postgresql": "4e47cae1f2f84f5e523dc43f", +"snowflake": "4e47cae1f2f84f5e523dc43f", +"tsql": "4e47cae1f2f84f5e523dc43f" +} +], +[ +"type", +{ +"DuckDB": "8fe65454f387031aa6231faf", +"None": "8fe65454f387031aa6231faf", +"bigquery": "8fe65454f387031aa6231faf", +"databricks": "8fe65454f387031aa6231faf", +"duckdb": "8fe65454f387031aa6231faf", +"generic": "8fe65454f387031aa6231faf", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "8fe65454f387031aa6231faf", +"postgres": "8fe65454f387031aa6231faf", +"postgresql": "8fe65454f387031aa6231faf", +"snowflake": "8fe65454f387031aa6231faf", +"tsql": "8fe65454f387031aa6231faf" +} +], +[ +"type", +{ +"DuckDB": "a428302e4848ffe877284c84", +"None": "a428302e4848ffe877284c84", +"bigquery": "a428302e4848ffe877284c84", +"databricks": "a428302e4848ffe877284c84", +"duckdb": "a428302e4848ffe877284c84", +"generic": "a428302e4848ffe877284c84", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "a428302e4848ffe877284c84", +"postgres": "a428302e4848ffe877284c84", +"postgresql": "a428302e4848ffe877284c84", +"snowflake": "652ff8b21f638eac8fdc46c5", +"tsql": "a428302e4848ffe877284c84" +} +], +[ +"type", +{ +"DuckDB": "8a3f094f18fb4047f0febf59", +"None": "c844c96e1e3ffc72d5f90df9", +"bigquery": "5c28019dce48a74708c90a76", +"databricks": "c844c96e1e3ffc72d5f90df9", +"duckdb": "8a3f094f18fb4047f0febf59", +"generic": "c844c96e1e3ffc72d5f90df9", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "28eb0d6de9724959ce5ba43e", +"postgres": "c844c96e1e3ffc72d5f90df9", +"postgresql": "c844c96e1e3ffc72d5f90df9", +"snowflake": "c844c96e1e3ffc72d5f90df9", +"tsql": "a4a176ec3c56e2704a650963" +} +], +[ +"type", +{ +"DuckDB": "e8b6e0bd2ded7b9eec6209e4", +"None": "e8b6e0bd2ded7b9eec6209e4", +"bigquery": "e8b6e0bd2ded7b9eec6209e4", +"databricks": "e8b6e0bd2ded7b9eec6209e4", +"duckdb": "e8b6e0bd2ded7b9eec6209e4", +"generic": "e8b6e0bd2ded7b9eec6209e4", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "e8b6e0bd2ded7b9eec6209e4", +"postgres": "e8b6e0bd2ded7b9eec6209e4", +"postgresql": "e8b6e0bd2ded7b9eec6209e4", +"snowflake": "e8b6e0bd2ded7b9eec6209e4", +"tsql": "e8b6e0bd2ded7b9eec6209e4" +} +], +[ +"type", +{ +"DuckDB": "d41d40c68507f4d02e348833", +"None": "d41d40c68507f4d02e348833", +"bigquery": "e1c36a5cdd2427ff2b089ac9", +"databricks": "d41d40c68507f4d02e348833", +"duckdb": "d41d40c68507f4d02e348833", +"generic": "d41d40c68507f4d02e348833", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "d41d40c68507f4d02e348833", +"postgres": "d41d40c68507f4d02e348833", +"postgresql": "d41d40c68507f4d02e348833", +"snowflake": "d41d40c68507f4d02e348833", +"tsql": "d41d40c68507f4d02e348833" +} +], +[ +"type", +{ +"DuckDB": "0ca1be8f7d61ca627e620450", +"None": "0ca1be8f7d61ca627e620450", +"bigquery": "e1c36a5cdd2427ff2b089ac9", +"databricks": "0ca1be8f7d61ca627e620450", +"duckdb": "0ca1be8f7d61ca627e620450", +"generic": "0ca1be8f7d61ca627e620450", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "0ca1be8f7d61ca627e620450", +"postgres": "0ca1be8f7d61ca627e620450", +"postgresql": "0ca1be8f7d61ca627e620450", +"snowflake": "18db5afe2c1e80d1ee652b54", +"tsql": "0ca1be8f7d61ca627e620450" +} +], +[ +"type", +{ +"DuckDB": "fbb8dada51c532716b2cbf9f", +"None": "29685ad61061d232d5b44f98", +"bigquery": "29685ad61061d232d5b44f98", +"databricks": "29685ad61061d232d5b44f98", +"duckdb": "fbb8dada51c532716b2cbf9f", +"generic": "29685ad61061d232d5b44f98", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "6c03a3450ea4742ee7396e3c", +"postgres": "fbb8dada51c532716b2cbf9f", +"postgresql": "fbb8dada51c532716b2cbf9f", +"snowflake": "3d54d99fa15cb697878997d5", +"tsql": "6846d3f6d21916a4d55dc138" +} +], +[ +"type", +{ +"DuckDB": "d61c83ef8bfdf043fa672cb5", +"None": "d61c83ef8bfdf043fa672cb5", +"bigquery": "c9b810639795a7bfab91b98d", +"databricks": "d61c83ef8bfdf043fa672cb5", +"duckdb": "d61c83ef8bfdf043fa672cb5", +"generic": "d61c83ef8bfdf043fa672cb5", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "d61c83ef8bfdf043fa672cb5", +"postgres": "d61c83ef8bfdf043fa672cb5", +"postgresql": "d61c83ef8bfdf043fa672cb5", +"snowflake": "97a20344d811fb77c7690863", +"tsql": "d61c83ef8bfdf043fa672cb5" +} +], +[ +"type", +{ +"DuckDB": "1eb7fb4e8cf75773c5573562", +"None": "1eb7fb4e8cf75773c5573562", +"bigquery": "c9b810639795a7bfab91b98d", +"databricks": "1eb7fb4e8cf75773c5573562", +"duckdb": "1eb7fb4e8cf75773c5573562", +"generic": "1eb7fb4e8cf75773c5573562", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "1eb7fb4e8cf75773c5573562", +"postgres": "1eb7fb4e8cf75773c5573562", +"postgresql": "1eb7fb4e8cf75773c5573562", +"snowflake": "97a20344d811fb77c7690863", +"tsql": "1eb7fb4e8cf75773c5573562" +} +], +[ +"type", +{ +"DuckDB": "70fb4728c3adcf6dbe4975d5", +"None": "70fb4728c3adcf6dbe4975d5", +"bigquery": "70fb4728c3adcf6dbe4975d5", +"databricks": "70fb4728c3adcf6dbe4975d5", +"duckdb": "70fb4728c3adcf6dbe4975d5", +"generic": "70fb4728c3adcf6dbe4975d5", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "70fb4728c3adcf6dbe4975d5", +"postgres": "70fb4728c3adcf6dbe4975d5", +"postgresql": "70fb4728c3adcf6dbe4975d5", +"snowflake": "70fb4728c3adcf6dbe4975d5", +"tsql": "70fb4728c3adcf6dbe4975d5" +} +], +[ +"type", +{ +"DuckDB": "64fc778308b798a730b1d5c9", +"None": "64fc778308b798a730b1d5c9", +"bigquery": "64fc778308b798a730b1d5c9", +"databricks": "64fc778308b798a730b1d5c9", +"duckdb": "64fc778308b798a730b1d5c9", +"generic": "64fc778308b798a730b1d5c9", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "64fc778308b798a730b1d5c9", +"postgres": "64fc778308b798a730b1d5c9", +"postgresql": "64fc778308b798a730b1d5c9", +"snowflake": "64fc778308b798a730b1d5c9", +"tsql": "64fc778308b798a730b1d5c9" +} +], +[ +"type", +{ +"DuckDB": "ee8c9d9a91ebec8ca7defc90", +"None": "fd3b9424e28fed0134486bc7", +"bigquery": "fd3b9424e28fed0134486bc7", +"databricks": "fd3b9424e28fed0134486bc7", +"duckdb": "ee8c9d9a91ebec8ca7defc90", +"generic": "fd3b9424e28fed0134486bc7", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "6c03a3450ea4742ee7396e3c", +"postgres": "ee8c9d9a91ebec8ca7defc90", +"postgresql": "ee8c9d9a91ebec8ca7defc90", +"snowflake": "1d67c9120962e3304f0e1bcc", +"tsql": "d1dc9a140dbe2eb1874c6ad7" +} +], +[ +"type", +{ +"DuckDB": "01e3dfc024c37a8d62c7f810", +"None": "3a4d8bca5124769db23a43df", +"bigquery": "3a4d8bca5124769db23a43df", +"databricks": "3a4d8bca5124769db23a43df", +"duckdb": "01e3dfc024c37a8d62c7f810", +"generic": "3a4d8bca5124769db23a43df", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "6c03a3450ea4742ee7396e3c", +"postgres": "01e3dfc024c37a8d62c7f810", +"postgresql": "01e3dfc024c37a8d62c7f810", +"snowflake": "db03b5ccf153c75e43846a6a", +"tsql": "754720a18c6591b99840f0b6" +} +], +[ +"type", +{ +"DuckDB": "791a58207da7e61895ce33f6", +"None": "791a58207da7e61895ce33f6", +"bigquery": "791a58207da7e61895ce33f6", +"databricks": "791a58207da7e61895ce33f6", +"duckdb": "791a58207da7e61895ce33f6", +"generic": "791a58207da7e61895ce33f6", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "791a58207da7e61895ce33f6", +"postgres": "791a58207da7e61895ce33f6", +"postgresql": "791a58207da7e61895ce33f6", +"snowflake": "791a58207da7e61895ce33f6", +"tsql": "791a58207da7e61895ce33f6" +} +], +[ +"type", +{ +"DuckDB": "461923a0d34defd0c726d6e5", +"None": "461923a0d34defd0c726d6e5", +"bigquery": "b5c4d5044b2a6e70633f0d0a", +"databricks": "461923a0d34defd0c726d6e5", +"duckdb": "461923a0d34defd0c726d6e5", +"generic": "461923a0d34defd0c726d6e5", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "461923a0d34defd0c726d6e5", +"postgres": "461923a0d34defd0c726d6e5", +"postgresql": "461923a0d34defd0c726d6e5", +"snowflake": "461923a0d34defd0c726d6e5", +"tsql": "461923a0d34defd0c726d6e5" +} +], +[ +"type", +{ +"DuckDB": "d2c97d221599d038d9875873", +"None": "d2c97d221599d038d9875873", +"bigquery": "d2c97d221599d038d9875873", +"databricks": "d2c97d221599d038d9875873", +"duckdb": "d2c97d221599d038d9875873", +"generic": "d2c97d221599d038d9875873", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "d2c97d221599d038d9875873", +"postgres": "d2c97d221599d038d9875873", +"postgresql": "d2c97d221599d038d9875873", +"snowflake": "d2c97d221599d038d9875873", +"tsql": "d2c97d221599d038d9875873" +} +], +[ +"type", +{ +"DuckDB": "f7fca17b74cc50ae3de8c826", +"None": "f7fca17b74cc50ae3de8c826", +"bigquery": "f7fca17b74cc50ae3de8c826", +"databricks": "f7fca17b74cc50ae3de8c826", +"duckdb": "f7fca17b74cc50ae3de8c826", +"generic": "f7fca17b74cc50ae3de8c826", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "f7fca17b74cc50ae3de8c826", +"postgres": "f7fca17b74cc50ae3de8c826", +"postgresql": "f7fca17b74cc50ae3de8c826", +"snowflake": "55155766823b6a3a5e882fc2", +"tsql": "f7fca17b74cc50ae3de8c826" +} +], +[ +"type", +{ +"DuckDB": "ef34121d80f6c399a1a456b1", +"None": "ef34121d80f6c399a1a456b1", +"bigquery": "ef34121d80f6c399a1a456b1", +"databricks": "ef34121d80f6c399a1a456b1", +"duckdb": "ef34121d80f6c399a1a456b1", +"generic": "ef34121d80f6c399a1a456b1", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "ef34121d80f6c399a1a456b1", +"postgres": "ef34121d80f6c399a1a456b1", +"postgresql": "ef34121d80f6c399a1a456b1", +"snowflake": "ef34121d80f6c399a1a456b1", +"tsql": "ef34121d80f6c399a1a456b1" +} +], +[ +"type", +{ +"DuckDB": "79278352c17c9de0f5a28af5", +"None": "79278352c17c9de0f5a28af5", +"bigquery": "c9b810639795a7bfab91b98d", +"databricks": "79278352c17c9de0f5a28af5", +"duckdb": "79278352c17c9de0f5a28af5", +"generic": "79278352c17c9de0f5a28af5", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "79278352c17c9de0f5a28af5", +"postgres": "79278352c17c9de0f5a28af5", +"postgresql": "79278352c17c9de0f5a28af5", +"snowflake": "97a20344d811fb77c7690863", +"tsql": "79278352c17c9de0f5a28af5" +} +], +[ +"type", +{ +"DuckDB": "b4284f955ab1914d3f556d82", +"None": "b4284f955ab1914d3f556d82", +"bigquery": "b4284f955ab1914d3f556d82", +"databricks": "b4284f955ab1914d3f556d82", +"duckdb": "b4284f955ab1914d3f556d82", +"generic": "b4284f955ab1914d3f556d82", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "b4284f955ab1914d3f556d82", +"postgres": "b4284f955ab1914d3f556d82", +"postgresql": "b4284f955ab1914d3f556d82", +"snowflake": "b4284f955ab1914d3f556d82", +"tsql": "b4284f955ab1914d3f556d82" +} +], +[ +"type", +{ +"DuckDB": "c84c0b1d4d7caa6744130456", +"None": "c84c0b1d4d7caa6744130456", +"bigquery": "c84c0b1d4d7caa6744130456", +"databricks": "c84c0b1d4d7caa6744130456", +"duckdb": "c84c0b1d4d7caa6744130456", +"generic": "c84c0b1d4d7caa6744130456", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "c84c0b1d4d7caa6744130456", +"postgres": "c84c0b1d4d7caa6744130456", +"postgresql": "c84c0b1d4d7caa6744130456", +"snowflake": "c84c0b1d4d7caa6744130456", +"tsql": "c84c0b1d4d7caa6744130456" +} +], +[ +"type", +{ +"DuckDB": "62368fc15cefd5807807b209", +"None": "62368fc15cefd5807807b209", +"bigquery": "e6ffdece2977be55da73b59a", +"databricks": "62368fc15cefd5807807b209", +"duckdb": "62368fc15cefd5807807b209", +"generic": "62368fc15cefd5807807b209", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "62368fc15cefd5807807b209", +"postgres": "62368fc15cefd5807807b209", +"postgresql": "62368fc15cefd5807807b209", +"snowflake": "62368fc15cefd5807807b209", +"tsql": "62368fc15cefd5807807b209" +} +], +[ +"type", +{ +"DuckDB": "8441d00030df06ad6a5534d3", +"None": "8441d00030df06ad6a5534d3", +"bigquery": "c9b810639795a7bfab91b98d", +"databricks": "8441d00030df06ad6a5534d3", +"duckdb": "8441d00030df06ad6a5534d3", +"generic": "8441d00030df06ad6a5534d3", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "8441d00030df06ad6a5534d3", +"postgres": "8441d00030df06ad6a5534d3", +"postgresql": "8441d00030df06ad6a5534d3", +"snowflake": "97a20344d811fb77c7690863", +"tsql": "8441d00030df06ad6a5534d3" +} +], +[ +"type", +{ +"DuckDB": "70fb4728c3adcf6dbe4975d5", +"None": "70fb4728c3adcf6dbe4975d5", +"bigquery": "70fb4728c3adcf6dbe4975d5", +"databricks": "70fb4728c3adcf6dbe4975d5", +"duckdb": "70fb4728c3adcf6dbe4975d5", +"generic": "70fb4728c3adcf6dbe4975d5", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "70fb4728c3adcf6dbe4975d5", +"postgres": "70fb4728c3adcf6dbe4975d5", +"postgresql": "70fb4728c3adcf6dbe4975d5", +"snowflake": "70fb4728c3adcf6dbe4975d5", +"tsql": "70fb4728c3adcf6dbe4975d5" +} +], +[ +"type", +{ +"DuckDB": "ebc821a95b9286e22c2b26d0", +"None": "ebc821a95b9286e22c2b26d0", +"bigquery": "19a1a80ffc06169f32694de8", +"databricks": "ebc821a95b9286e22c2b26d0", +"duckdb": "ebc821a95b9286e22c2b26d0", +"generic": "ebc821a95b9286e22c2b26d0", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "ebc821a95b9286e22c2b26d0", +"postgres": "ebc821a95b9286e22c2b26d0", +"postgresql": "ebc821a95b9286e22c2b26d0", +"snowflake": "ebc821a95b9286e22c2b26d0", +"tsql": "ebc821a95b9286e22c2b26d0" +} +], +[ +"type", +{ +"DuckDB": "73151c1398b30e5c5d18f4ce", +"None": "73151c1398b30e5c5d18f4ce", +"bigquery": "73151c1398b30e5c5d18f4ce", +"databricks": "73151c1398b30e5c5d18f4ce", +"duckdb": "73151c1398b30e5c5d18f4ce", +"generic": "73151c1398b30e5c5d18f4ce", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "73151c1398b30e5c5d18f4ce", +"postgres": "73151c1398b30e5c5d18f4ce", +"postgresql": "73151c1398b30e5c5d18f4ce", +"snowflake": "73151c1398b30e5c5d18f4ce", +"tsql": "73151c1398b30e5c5d18f4ce" +} +], +[ +"type", +{ +"DuckDB": "792f7d3389f076f50c713946", +"None": "792f7d3389f076f50c713946", +"bigquery": "792f7d3389f076f50c713946", +"databricks": "4fb572024031cb7631777be1", +"duckdb": "792f7d3389f076f50c713946", +"generic": "792f7d3389f076f50c713946", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "792f7d3389f076f50c713946", +"postgres": "792f7d3389f076f50c713946", +"postgresql": "792f7d3389f076f50c713946", +"snowflake": "792f7d3389f076f50c713946", +"tsql": "792f7d3389f076f50c713946" +} +], +[ +"type", +{ +"DuckDB": "236311169ac0526becd627ac", +"None": "236311169ac0526becd627ac", +"bigquery": "236311169ac0526becd627ac", +"databricks": "236311169ac0526becd627ac", +"duckdb": "236311169ac0526becd627ac", +"generic": "236311169ac0526becd627ac", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "236311169ac0526becd627ac", +"postgres": "236311169ac0526becd627ac", +"postgresql": "236311169ac0526becd627ac", +"snowflake": "236311169ac0526becd627ac", +"tsql": "236311169ac0526becd627ac" +} +], +[ +"type", +{ +"DuckDB": "05ebf79d18b2ae4eaa41f450", +"None": "336fd1b7a1f7d8105c29280c", +"bigquery": "aa04c66b4fed5190c90308fd", +"databricks": "336fd1b7a1f7d8105c29280c", +"duckdb": "05ebf79d18b2ae4eaa41f450", +"generic": "336fd1b7a1f7d8105c29280c", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "336fd1b7a1f7d8105c29280c", +"postgres": "336fd1b7a1f7d8105c29280c", +"postgresql": "336fd1b7a1f7d8105c29280c", +"snowflake": "336fd1b7a1f7d8105c29280c", +"tsql": "336fd1b7a1f7d8105c29280c" +} +], +[ +"type", +{ +"DuckDB": "806dd59533345612c07a861b", +"None": "806dd59533345612c07a861b", +"bigquery": "806dd59533345612c07a861b", +"databricks": "806dd59533345612c07a861b", +"duckdb": "806dd59533345612c07a861b", +"generic": "806dd59533345612c07a861b", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "806dd59533345612c07a861b", +"postgres": "806dd59533345612c07a861b", +"postgresql": "806dd59533345612c07a861b", +"snowflake": "806dd59533345612c07a861b", +"tsql": "806dd59533345612c07a861b" +} +], +[ +"type", +{ +"DuckDB": "647ac9829e390656c0783aba", +"None": "1404468a845477f54df838fc", +"bigquery": "2df0f0517ee87dda5683d2bd", +"databricks": "2df0f0517ee87dda5683d2bd", +"duckdb": "647ac9829e390656c0783aba", +"generic": "1404468a845477f54df838fc", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "2df0f0517ee87dda5683d2bd", +"postgres": "ee5dc4b764837cf002345fb9", +"postgresql": "ee5dc4b764837cf002345fb9", +"snowflake": "8d1f13df6b799b7b301d2e69", +"tsql": "d1dc9a140dbe2eb1874c6ad7" +} +], +[ +"type", +{ +"DuckDB": "6226bc03436ecf8fccd39252", +"None": "5aa51d84ac5e6c7a9306f348", +"bigquery": "5aa51d84ac5e6c7a9306f348", +"databricks": "5aa51d84ac5e6c7a9306f348", +"duckdb": "6226bc03436ecf8fccd39252", +"generic": "5aa51d84ac5e6c7a9306f348", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "5aa51d84ac5e6c7a9306f348", +"postgres": "5aa51d84ac5e6c7a9306f348", +"postgresql": "5aa51d84ac5e6c7a9306f348", +"snowflake": "5aa51d84ac5e6c7a9306f348", +"tsql": "5aa51d84ac5e6c7a9306f348" +} +], +[ +"type", +{ +"DuckDB": "6247229b9f890f25e7b3f0c5", +"None": "eb8ea3778b2debde09f2afb1", +"bigquery": "135a912ea74f76a35d9d0632", +"databricks": "eb8ea3778b2debde09f2afb1", +"duckdb": "6247229b9f890f25e7b3f0c5", +"generic": "eb8ea3778b2debde09f2afb1", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "6c03a3450ea4742ee7396e3c", +"postgres": "6247229b9f890f25e7b3f0c5", +"postgresql": "6247229b9f890f25e7b3f0c5", +"snowflake": "8f60ea843371b982d069e65b", +"tsql": "3fd7037beaaa396764e49e8b" +} +], +[ +"type", +{ +"DuckDB": "077cc38442b3b9eae7bb07d0", +"None": "a57535ee64678e69d1acd48a", +"bigquery": "a57535ee64678e69d1acd48a", +"databricks": "a57535ee64678e69d1acd48a", +"duckdb": "077cc38442b3b9eae7bb07d0", +"generic": "a57535ee64678e69d1acd48a", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "6c03a3450ea4742ee7396e3c", +"postgres": "077cc38442b3b9eae7bb07d0", +"postgresql": "077cc38442b3b9eae7bb07d0", +"snowflake": "befa13a14d1144835e866a4d", +"tsql": "2102201dfd2a182bcf503f40" +} +], +[ +"type", +{ +"DuckDB": "d61c83ef8bfdf043fa672cb5", +"None": "d61c83ef8bfdf043fa672cb5", +"bigquery": "c9b810639795a7bfab91b98d", +"databricks": "d61c83ef8bfdf043fa672cb5", +"duckdb": "d61c83ef8bfdf043fa672cb5", +"generic": "d61c83ef8bfdf043fa672cb5", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "d61c83ef8bfdf043fa672cb5", +"postgres": "d61c83ef8bfdf043fa672cb5", +"postgresql": "d61c83ef8bfdf043fa672cb5", +"snowflake": "97a20344d811fb77c7690863", +"tsql": "d61c83ef8bfdf043fa672cb5" +} +], +[ +"type", +{ +"DuckDB": "ff8f9d6dbbdd5b3cf2e7c198", +"None": "ff8f9d6dbbdd5b3cf2e7c198", +"bigquery": "ff8f9d6dbbdd5b3cf2e7c198", +"databricks": "ff8f9d6dbbdd5b3cf2e7c198", +"duckdb": "ff8f9d6dbbdd5b3cf2e7c198", +"generic": "ff8f9d6dbbdd5b3cf2e7c198", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "ff8f9d6dbbdd5b3cf2e7c198", +"postgres": "ff8f9d6dbbdd5b3cf2e7c198", +"postgresql": "ff8f9d6dbbdd5b3cf2e7c198", +"snowflake": "ff8f9d6dbbdd5b3cf2e7c198", +"tsql": "ff8f9d6dbbdd5b3cf2e7c198" +} +], +[ +"type", +{ +"DuckDB": "4928771fd9e503a30457d160", +"None": "4928771fd9e503a30457d160", +"bigquery": "4928771fd9e503a30457d160", +"databricks": "4928771fd9e503a30457d160", +"duckdb": "4928771fd9e503a30457d160", +"generic": "4928771fd9e503a30457d160", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "4928771fd9e503a30457d160", +"postgres": "4928771fd9e503a30457d160", +"postgresql": "4928771fd9e503a30457d160", +"snowflake": "4928771fd9e503a30457d160", +"tsql": "4928771fd9e503a30457d160" +} +], +[ +"type", +{ +"DuckDB": "19bdd92ea0cc5fb028657510", +"None": "b8321619b794db091c9e96a1", +"bigquery": "b8321619b794db091c9e96a1", +"databricks": "1e75e5227bea0ae294ac7af1", +"duckdb": "19bdd92ea0cc5fb028657510", +"generic": "b8321619b794db091c9e96a1", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "b8321619b794db091c9e96a1", +"postgres": "b8321619b794db091c9e96a1", +"postgresql": "b8321619b794db091c9e96a1", +"snowflake": "b8321619b794db091c9e96a1", +"tsql": "b8321619b794db091c9e96a1" +} +], +[ +"type", +{ +"DuckDB": "a0e5b4ce93e9317c3cea1cbf", +"None": "a0e5b4ce93e9317c3cea1cbf", +"bigquery": "a0e5b4ce93e9317c3cea1cbf", +"databricks": "c9d23fd01aedfa8b27cf08a6", +"duckdb": "a0e5b4ce93e9317c3cea1cbf", +"generic": "a0e5b4ce93e9317c3cea1cbf", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "c8a1fc1b91adcea5a885afe3", +"postgres": "a0e5b4ce93e9317c3cea1cbf", +"postgresql": "a0e5b4ce93e9317c3cea1cbf", +"snowflake": "a0e5b4ce93e9317c3cea1cbf", +"tsql": "a0e5b4ce93e9317c3cea1cbf" +} +], +[ +"type", +{ +"DuckDB": "78de20f17ea5d66780a9f32e", +"None": "78de20f17ea5d66780a9f32e", +"bigquery": "78de20f17ea5d66780a9f32e", +"databricks": "78de20f17ea5d66780a9f32e", +"duckdb": "78de20f17ea5d66780a9f32e", +"generic": "78de20f17ea5d66780a9f32e", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "78de20f17ea5d66780a9f32e", +"postgres": "78de20f17ea5d66780a9f32e", +"postgresql": "78de20f17ea5d66780a9f32e", +"snowflake": "78de20f17ea5d66780a9f32e", +"tsql": "78de20f17ea5d66780a9f32e" +} +], +[ +"type", +{ +"DuckDB": "8bb8eb3ad4ee794b787a664d", +"None": "8bb8eb3ad4ee794b787a664d", +"bigquery": "01d1b160c1768fa1cd4b2e45", +"databricks": "40f264d27364684659f815eb", +"duckdb": "8bb8eb3ad4ee794b787a664d", +"generic": "8bb8eb3ad4ee794b787a664d", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "8bb8eb3ad4ee794b787a664d", +"postgres": "8bb8eb3ad4ee794b787a664d", +"postgresql": "8bb8eb3ad4ee794b787a664d", +"snowflake": "469cddcff389dac525f4efdf", +"tsql": "5efacb746122082701b02343" +} +], +[ +"type", +{ +"DuckDB": "e46d4be44ab9e500e9190d26", +"None": "e46d4be44ab9e500e9190d26", +"bigquery": "e6ffdece2977be55da73b59a", +"databricks": "e46d4be44ab9e500e9190d26", +"duckdb": "e46d4be44ab9e500e9190d26", +"generic": "e46d4be44ab9e500e9190d26", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "e46d4be44ab9e500e9190d26", +"postgres": "e46d4be44ab9e500e9190d26", +"postgresql": "e46d4be44ab9e500e9190d26", +"snowflake": "e46d4be44ab9e500e9190d26", +"tsql": "e46d4be44ab9e500e9190d26" +} +], +[ +"type", +{ +"DuckDB": "3673b4fbbd8a7fed7120ec2b", +"None": "3673b4fbbd8a7fed7120ec2b", +"bigquery": "3673b4fbbd8a7fed7120ec2b", +"databricks": "3673b4fbbd8a7fed7120ec2b", +"duckdb": "3673b4fbbd8a7fed7120ec2b", +"generic": "3673b4fbbd8a7fed7120ec2b", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "3673b4fbbd8a7fed7120ec2b", +"postgres": "3673b4fbbd8a7fed7120ec2b", +"postgresql": "3673b4fbbd8a7fed7120ec2b", +"snowflake": "3673b4fbbd8a7fed7120ec2b", +"tsql": "3673b4fbbd8a7fed7120ec2b" +} +], +[ +"type", +{ +"DuckDB": "a3b6b25265be330ec52a3322", +"None": "a3b6b25265be330ec52a3322", +"bigquery": "204206d1d1eecf007966cc5b", +"databricks": "e3bc1b8bad22d8104417b00f", +"duckdb": "a3b6b25265be330ec52a3322", +"generic": "a3b6b25265be330ec52a3322", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "919b7ec6a7b49d8527b784cd", +"postgres": "a3b6b25265be330ec52a3322", +"postgresql": "a3b6b25265be330ec52a3322", +"snowflake": "919b7ec6a7b49d8527b784cd", +"tsql": "a3b6b25265be330ec52a3322" +} +], +[ +"type", +{ +"DuckDB": "fe23594c781e79cbb0c8927a", +"None": "fe23594c781e79cbb0c8927a", +"bigquery": "fe23594c781e79cbb0c8927a", +"databricks": "fe23594c781e79cbb0c8927a", +"duckdb": "fe23594c781e79cbb0c8927a", +"generic": "fe23594c781e79cbb0c8927a", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "fe23594c781e79cbb0c8927a", +"postgres": "fe23594c781e79cbb0c8927a", +"postgresql": "fe23594c781e79cbb0c8927a", +"snowflake": "38b2ec94bf02be40007ce525", +"tsql": "fe23594c781e79cbb0c8927a" +} +], +[ +"type", +{ +"DuckDB": "1eb7fb4e8cf75773c5573562", +"None": "1eb7fb4e8cf75773c5573562", +"bigquery": "c9b810639795a7bfab91b98d", +"databricks": "1eb7fb4e8cf75773c5573562", +"duckdb": "1eb7fb4e8cf75773c5573562", +"generic": "1eb7fb4e8cf75773c5573562", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "1eb7fb4e8cf75773c5573562", +"postgres": "1eb7fb4e8cf75773c5573562", +"postgresql": "1eb7fb4e8cf75773c5573562", +"snowflake": "97a20344d811fb77c7690863", +"tsql": "1eb7fb4e8cf75773c5573562" +} +], +[ +"type", +{ +"DuckDB": "0b8ad171901cc2b7725617da", +"None": "0b8ad171901cc2b7725617da", +"bigquery": "0b8ad171901cc2b7725617da", +"databricks": "0b8ad171901cc2b7725617da", +"duckdb": "0b8ad171901cc2b7725617da", +"generic": "0b8ad171901cc2b7725617da", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "0b8ad171901cc2b7725617da", +"postgres": "0b8ad171901cc2b7725617da", +"postgresql": "0b8ad171901cc2b7725617da", +"snowflake": "0b8ad171901cc2b7725617da", +"tsql": "0b8ad171901cc2b7725617da" +} +], +[ +"type", +{ +"DuckDB": "208eafc9a5aab337867bb773", +"None": "97dfbcc6528a197a87add69e", +"bigquery": "cd7b6238af592579916341e8", +"databricks": "97dfbcc6528a197a87add69e", +"duckdb": "208eafc9a5aab337867bb773", +"generic": "97dfbcc6528a197a87add69e", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "6c03a3450ea4742ee7396e3c", +"postgres": "ca3d3fa7d8eb1608bd8752de", +"postgresql": "ca3d3fa7d8eb1608bd8752de", +"snowflake": "46250b305f6ac5a95e4d3083", +"tsql": "4a596251860d8d497d59f1a7" +} +], +[ +"type", +{ +"DuckDB": "c4d601bdc1b1f357b3e9bbdf", +"None": "c4d601bdc1b1f357b3e9bbdf", +"bigquery": "c4d601bdc1b1f357b3e9bbdf", +"databricks": "c4d601bdc1b1f357b3e9bbdf", +"duckdb": "c4d601bdc1b1f357b3e9bbdf", +"generic": "c4d601bdc1b1f357b3e9bbdf", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "c4d601bdc1b1f357b3e9bbdf", +"postgres": "c4d601bdc1b1f357b3e9bbdf", +"postgresql": "c4d601bdc1b1f357b3e9bbdf", +"snowflake": "c4d601bdc1b1f357b3e9bbdf", +"tsql": "c4d601bdc1b1f357b3e9bbdf" +} +], +[ +"type", +{ +"DuckDB": "669084d1ea704ae5b8ee05c2", +"None": "669084d1ea704ae5b8ee05c2", +"bigquery": "669084d1ea704ae5b8ee05c2", +"databricks": "669084d1ea704ae5b8ee05c2", +"duckdb": "669084d1ea704ae5b8ee05c2", +"generic": "669084d1ea704ae5b8ee05c2", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "669084d1ea704ae5b8ee05c2", +"postgres": "669084d1ea704ae5b8ee05c2", +"postgresql": "669084d1ea704ae5b8ee05c2", +"snowflake": "669084d1ea704ae5b8ee05c2", +"tsql": "669084d1ea704ae5b8ee05c2" +} +], +[ +"type", +{ +"DuckDB": "e7c121d9cbaf6e6b91cfdf74", +"None": "e7c121d9cbaf6e6b91cfdf74", +"bigquery": "e7c121d9cbaf6e6b91cfdf74", +"databricks": "e7c121d9cbaf6e6b91cfdf74", +"duckdb": "e7c121d9cbaf6e6b91cfdf74", +"generic": "e7c121d9cbaf6e6b91cfdf74", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "e7c121d9cbaf6e6b91cfdf74", +"postgres": "e7c121d9cbaf6e6b91cfdf74", +"postgresql": "e7c121d9cbaf6e6b91cfdf74", +"snowflake": "e7c121d9cbaf6e6b91cfdf74", +"tsql": "e7c121d9cbaf6e6b91cfdf74" +} +], +[ +"type", +{ +"DuckDB": "962ea05bab624c1f8c259a65", +"None": "962ea05bab624c1f8c259a65", +"bigquery": "962ea05bab624c1f8c259a65", +"databricks": "962ea05bab624c1f8c259a65", +"duckdb": "962ea05bab624c1f8c259a65", +"generic": "962ea05bab624c1f8c259a65", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "962ea05bab624c1f8c259a65", +"postgres": "962ea05bab624c1f8c259a65", +"postgresql": "962ea05bab624c1f8c259a65", +"snowflake": "962ea05bab624c1f8c259a65", +"tsql": "962ea05bab624c1f8c259a65" +} +], +[ +"type", +{ +"DuckDB": "3e888d249494102b9ba328b2", +"None": "3e888d249494102b9ba328b2", +"bigquery": "3e888d249494102b9ba328b2", +"databricks": "3e888d249494102b9ba328b2", +"duckdb": "3e888d249494102b9ba328b2", +"generic": "3e888d249494102b9ba328b2", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "3e888d249494102b9ba328b2", +"postgres": "3e888d249494102b9ba328b2", +"postgresql": "3e888d249494102b9ba328b2", +"snowflake": "3e888d249494102b9ba328b2", +"tsql": "3e888d249494102b9ba328b2" +} +], +[ +"type", +{ +"DuckDB": "1eb7fb4e8cf75773c5573562", +"None": "1eb7fb4e8cf75773c5573562", +"bigquery": "c9b810639795a7bfab91b98d", +"databricks": "1eb7fb4e8cf75773c5573562", +"duckdb": "1eb7fb4e8cf75773c5573562", +"generic": "1eb7fb4e8cf75773c5573562", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "1eb7fb4e8cf75773c5573562", +"postgres": "1eb7fb4e8cf75773c5573562", +"postgresql": "1eb7fb4e8cf75773c5573562", +"snowflake": "97a20344d811fb77c7690863", +"tsql": "1eb7fb4e8cf75773c5573562" +} +], +[ +"type", +{ +"DuckDB": "652ff8b21f638eac8fdc46c5", +"None": "652ff8b21f638eac8fdc46c5", +"bigquery": "316ab5126bbd68359eedc4d9", +"databricks": "652ff8b21f638eac8fdc46c5", +"duckdb": "652ff8b21f638eac8fdc46c5", +"generic": "652ff8b21f638eac8fdc46c5", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "652ff8b21f638eac8fdc46c5", +"postgres": "652ff8b21f638eac8fdc46c5", +"postgresql": "652ff8b21f638eac8fdc46c5", +"snowflake": "652ff8b21f638eac8fdc46c5", +"tsql": "652ff8b21f638eac8fdc46c5" +} +], +[ +"type", +{ +"DuckDB": "0989b67047ee9c0a1d9f2cf4", +"None": "0989b67047ee9c0a1d9f2cf4", +"bigquery": "0989b67047ee9c0a1d9f2cf4", +"databricks": "0989b67047ee9c0a1d9f2cf4", +"duckdb": "0989b67047ee9c0a1d9f2cf4", +"generic": "0989b67047ee9c0a1d9f2cf4", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "0989b67047ee9c0a1d9f2cf4", +"postgres": "0989b67047ee9c0a1d9f2cf4", +"postgresql": "0989b67047ee9c0a1d9f2cf4", +"snowflake": "0989b67047ee9c0a1d9f2cf4", +"tsql": "0989b67047ee9c0a1d9f2cf4" +} +], +[ +"type", +{ +"DuckDB": "1275b5b0c52f69cf592c004b", +"None": "1275b5b0c52f69cf592c004b", +"bigquery": "1275b5b0c52f69cf592c004b", +"databricks": "1275b5b0c52f69cf592c004b", +"duckdb": "1275b5b0c52f69cf592c004b", +"generic": "1275b5b0c52f69cf592c004b", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "1275b5b0c52f69cf592c004b", +"postgres": "1275b5b0c52f69cf592c004b", +"postgresql": "1275b5b0c52f69cf592c004b", +"snowflake": "1275b5b0c52f69cf592c004b", +"tsql": "1275b5b0c52f69cf592c004b" +} +], +[ +"type", +{ +"DuckDB": "35d19e3415493d51f36f89b1", +"None": "35d19e3415493d51f36f89b1", +"bigquery": "2a0918be53051fe629d9ff8f", +"databricks": "35d19e3415493d51f36f89b1", +"duckdb": "35d19e3415493d51f36f89b1", +"generic": "35d19e3415493d51f36f89b1", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "35d19e3415493d51f36f89b1", +"postgres": "35d19e3415493d51f36f89b1", +"postgresql": "35d19e3415493d51f36f89b1", +"snowflake": "3e611643f0beab4953c4e09b", +"tsql": "35d19e3415493d51f36f89b1" +} +], +[ +"type", +{ +"DuckDB": "e46d4be44ab9e500e9190d26", +"None": "e46d4be44ab9e500e9190d26", +"bigquery": "e6ffdece2977be55da73b59a", +"databricks": "e46d4be44ab9e500e9190d26", +"duckdb": "e46d4be44ab9e500e9190d26", +"generic": "e46d4be44ab9e500e9190d26", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "e46d4be44ab9e500e9190d26", +"postgres": "e46d4be44ab9e500e9190d26", +"postgresql": "e46d4be44ab9e500e9190d26", +"snowflake": "e46d4be44ab9e500e9190d26", +"tsql": "e46d4be44ab9e500e9190d26" +} +], +[ +"type", +{ +"DuckDB": "70fb4728c3adcf6dbe4975d5", +"None": "70fb4728c3adcf6dbe4975d5", +"bigquery": "70fb4728c3adcf6dbe4975d5", +"databricks": "70fb4728c3adcf6dbe4975d5", +"duckdb": "70fb4728c3adcf6dbe4975d5", +"generic": "70fb4728c3adcf6dbe4975d5", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "70fb4728c3adcf6dbe4975d5", +"postgres": "70fb4728c3adcf6dbe4975d5", +"postgresql": "70fb4728c3adcf6dbe4975d5", +"snowflake": "70fb4728c3adcf6dbe4975d5", +"tsql": "70fb4728c3adcf6dbe4975d5" +} +], +[ +"type", +{ +"DuckDB": "e2879cf4770e7f48d2dd704a", +"None": "e2879cf4770e7f48d2dd704a", +"bigquery": "c9b810639795a7bfab91b98d", +"databricks": "e2879cf4770e7f48d2dd704a", +"duckdb": "e2879cf4770e7f48d2dd704a", +"generic": "e2879cf4770e7f48d2dd704a", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "e2879cf4770e7f48d2dd704a", +"postgres": "e2879cf4770e7f48d2dd704a", +"postgresql": "e2879cf4770e7f48d2dd704a", +"snowflake": "97a20344d811fb77c7690863", +"tsql": "e2879cf4770e7f48d2dd704a" +} +], +[ +"type", +{ +"DuckDB": "b6b82efd03def9465e4f97b2", +"None": "b6b82efd03def9465e4f97b2", +"bigquery": "b6b82efd03def9465e4f97b2", +"databricks": "b6b82efd03def9465e4f97b2", +"duckdb": "b6b82efd03def9465e4f97b2", +"generic": "b6b82efd03def9465e4f97b2", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "b6b82efd03def9465e4f97b2", +"postgres": "b6b82efd03def9465e4f97b2", +"postgresql": "b6b82efd03def9465e4f97b2", +"snowflake": "b6b82efd03def9465e4f97b2", +"tsql": "b6b82efd03def9465e4f97b2" +} +], +[ +"type", +{ +"DuckDB": "e2879cf4770e7f48d2dd704a", +"None": "e2879cf4770e7f48d2dd704a", +"bigquery": "c9b810639795a7bfab91b98d", +"databricks": "e2879cf4770e7f48d2dd704a", +"duckdb": "e2879cf4770e7f48d2dd704a", +"generic": "e2879cf4770e7f48d2dd704a", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "e2879cf4770e7f48d2dd704a", +"postgres": "e2879cf4770e7f48d2dd704a", +"postgresql": "e2879cf4770e7f48d2dd704a", +"snowflake": "97a20344d811fb77c7690863", +"tsql": "e2879cf4770e7f48d2dd704a" +} +], +[ +"type", +{ +"DuckDB": "80c23e10e486925cf3b33f9d", +"None": "80c23e10e486925cf3b33f9d", +"bigquery": "80c23e10e486925cf3b33f9d", +"databricks": "80c23e10e486925cf3b33f9d", +"duckdb": "80c23e10e486925cf3b33f9d", +"generic": "80c23e10e486925cf3b33f9d", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "80c23e10e486925cf3b33f9d", +"postgres": "80c23e10e486925cf3b33f9d", +"postgresql": "80c23e10e486925cf3b33f9d", +"snowflake": "80c23e10e486925cf3b33f9d", +"tsql": "80c23e10e486925cf3b33f9d" +} +], +[ +"type", +{ +"DuckDB": "60a23b7dcae6c79f4de83068", +"None": "60a23b7dcae6c79f4de83068", +"bigquery": "60a23b7dcae6c79f4de83068", +"databricks": "60a23b7dcae6c79f4de83068", +"duckdb": "60a23b7dcae6c79f4de83068", +"generic": "60a23b7dcae6c79f4de83068", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "60a23b7dcae6c79f4de83068", +"postgres": "60a23b7dcae6c79f4de83068", +"postgresql": "60a23b7dcae6c79f4de83068", +"snowflake": "60a23b7dcae6c79f4de83068", +"tsql": "60a23b7dcae6c79f4de83068" +} +], +[ +"type", +{ +"DuckDB": "f4c43a87a78970bca1f88b09", +"None": "f4c43a87a78970bca1f88b09", +"bigquery": "f4c43a87a78970bca1f88b09", +"databricks": "f4c43a87a78970bca1f88b09", +"duckdb": "f4c43a87a78970bca1f88b09", +"generic": "f4c43a87a78970bca1f88b09", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "f4c43a87a78970bca1f88b09", +"postgres": "f4c43a87a78970bca1f88b09", +"postgresql": "f4c43a87a78970bca1f88b09", +"snowflake": "652ff8b21f638eac8fdc46c5", +"tsql": "f4c43a87a78970bca1f88b09" +} +], +[ +"type", +{ +"DuckDB": "3f71ab5f3c1c040da96f2cec", +"None": "3f71ab5f3c1c040da96f2cec", +"bigquery": "3f71ab5f3c1c040da96f2cec", +"databricks": "3f71ab5f3c1c040da96f2cec", +"duckdb": "3f71ab5f3c1c040da96f2cec", +"generic": "3f71ab5f3c1c040da96f2cec", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "3f71ab5f3c1c040da96f2cec", +"postgres": "3f71ab5f3c1c040da96f2cec", +"postgresql": "3f71ab5f3c1c040da96f2cec", +"snowflake": "3f71ab5f3c1c040da96f2cec", +"tsql": "3f71ab5f3c1c040da96f2cec" +} +], +[ +"type", +{ +"DuckDB": "c4346d0257336219f1d26890", +"None": "c4346d0257336219f1d26890", +"bigquery": "b5c4d5044b2a6e70633f0d0a", +"databricks": "c4346d0257336219f1d26890", +"duckdb": "c4346d0257336219f1d26890", +"generic": "c4346d0257336219f1d26890", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "c4346d0257336219f1d26890", +"postgres": "c4346d0257336219f1d26890", +"postgresql": "c4346d0257336219f1d26890", +"snowflake": "4e24a80b20b9dee0cbbfac17", +"tsql": "c4346d0257336219f1d26890" +} +], +[ +"type", +{ +"DuckDB": "bcc4b2c4a8f93d406cf00bc8", +"None": "cabeb00c4bc6c9e3d88a79ed", +"bigquery": "135a912ea74f76a35d9d0632", +"databricks": "cabeb00c4bc6c9e3d88a79ed", +"duckdb": "bcc4b2c4a8f93d406cf00bc8", +"generic": "cabeb00c4bc6c9e3d88a79ed", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "6c03a3450ea4742ee7396e3c", +"postgres": "bcc4b2c4a8f93d406cf00bc8", +"postgresql": "bcc4b2c4a8f93d406cf00bc8", +"snowflake": "c4046288c6fec9a1344b0faa", +"tsql": "c523f494d181f495aec369d3" +} +], +[ +"type", +{ +"DuckDB": "d61c83ef8bfdf043fa672cb5", +"None": "d61c83ef8bfdf043fa672cb5", +"bigquery": "c9b810639795a7bfab91b98d", +"databricks": "d61c83ef8bfdf043fa672cb5", +"duckdb": "d61c83ef8bfdf043fa672cb5", +"generic": "d61c83ef8bfdf043fa672cb5", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "d61c83ef8bfdf043fa672cb5", +"postgres": "d61c83ef8bfdf043fa672cb5", +"postgresql": "d61c83ef8bfdf043fa672cb5", +"snowflake": "97a20344d811fb77c7690863", +"tsql": "d61c83ef8bfdf043fa672cb5" +} +], +[ +"type", +{ +"DuckDB": "d2c97d221599d038d9875873", +"None": "d2c97d221599d038d9875873", +"bigquery": "d2c97d221599d038d9875873", +"databricks": "d2c97d221599d038d9875873", +"duckdb": "d2c97d221599d038d9875873", +"generic": "d2c97d221599d038d9875873", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "d2c97d221599d038d9875873", +"postgres": "d2c97d221599d038d9875873", +"postgresql": "d2c97d221599d038d9875873", +"snowflake": "d2c97d221599d038d9875873", +"tsql": "d2c97d221599d038d9875873" +} +], +[ +"type", +{ +"DuckDB": "63c80b5d8e861216f0c45bfd", +"None": "aa04c66b4fed5190c90308fd", +"bigquery": "aa04c66b4fed5190c90308fd", +"databricks": "aa04c66b4fed5190c90308fd", +"duckdb": "63c80b5d8e861216f0c45bfd", +"generic": "aa04c66b4fed5190c90308fd", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "aa04c66b4fed5190c90308fd", +"postgres": "aa04c66b4fed5190c90308fd", +"postgresql": "aa04c66b4fed5190c90308fd", +"snowflake": "d227b99a82e505d599c2ed8a", +"tsql": "aa04c66b4fed5190c90308fd" +} +], +[ +"type", +{ +"DuckDB": "fa07c8ec6ebf3228010ebd9a", +"None": "fa07c8ec6ebf3228010ebd9a", +"bigquery": "fa07c8ec6ebf3228010ebd9a", +"databricks": "fa07c8ec6ebf3228010ebd9a", +"duckdb": "fa07c8ec6ebf3228010ebd9a", +"generic": "fa07c8ec6ebf3228010ebd9a", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "fa07c8ec6ebf3228010ebd9a", +"postgres": "fa07c8ec6ebf3228010ebd9a", +"postgresql": "fa07c8ec6ebf3228010ebd9a", +"snowflake": "fa07c8ec6ebf3228010ebd9a", +"tsql": "fa07c8ec6ebf3228010ebd9a" +} +], +[ +"type", +{ +"DuckDB": "ab5ad6180652b3b00d1f5b01", +"None": "ab5ad6180652b3b00d1f5b01", +"bigquery": "946d5ee30ab7469c57d850df", +"databricks": "ab5ad6180652b3b00d1f5b01", +"duckdb": "ab5ad6180652b3b00d1f5b01", +"generic": "ab5ad6180652b3b00d1f5b01", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "ab5ad6180652b3b00d1f5b01", +"postgres": "ab5ad6180652b3b00d1f5b01", +"postgresql": "ab5ad6180652b3b00d1f5b01", +"snowflake": "226beccc1d430773f4e67b70", +"tsql": "ab5ad6180652b3b00d1f5b01" +} +], +[ +"type", +{ +"DuckDB": "70fb4728c3adcf6dbe4975d5", +"None": "70fb4728c3adcf6dbe4975d5", +"bigquery": "70fb4728c3adcf6dbe4975d5", +"databricks": "70fb4728c3adcf6dbe4975d5", +"duckdb": "70fb4728c3adcf6dbe4975d5", +"generic": "70fb4728c3adcf6dbe4975d5", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "70fb4728c3adcf6dbe4975d5", +"postgres": "70fb4728c3adcf6dbe4975d5", +"postgresql": "70fb4728c3adcf6dbe4975d5", +"snowflake": "70fb4728c3adcf6dbe4975d5", +"tsql": "70fb4728c3adcf6dbe4975d5" +} +], +[ +"type", +{ +"DuckDB": "35e216b6921bf843994f2eea", +"None": "e46d4be44ab9e500e9190d26", +"bigquery": "e6ffdece2977be55da73b59a", +"databricks": "e46d4be44ab9e500e9190d26", +"duckdb": "35e216b6921bf843994f2eea", +"generic": "e46d4be44ab9e500e9190d26", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "e46d4be44ab9e500e9190d26", +"postgres": "e46d4be44ab9e500e9190d26", +"postgresql": "e46d4be44ab9e500e9190d26", +"snowflake": "e46d4be44ab9e500e9190d26", +"tsql": "e46d4be44ab9e500e9190d26" +} +], +[ +"type", +{ +"DuckDB": "c2700ca3573352821e09af03", +"None": "c2700ca3573352821e09af03", +"bigquery": "a428302e4848ffe877284c84", +"databricks": "c2700ca3573352821e09af03", +"duckdb": "c2700ca3573352821e09af03", +"generic": "c2700ca3573352821e09af03", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "c2700ca3573352821e09af03", +"postgres": "c2700ca3573352821e09af03", +"postgresql": "c2700ca3573352821e09af03", +"snowflake": "652ff8b21f638eac8fdc46c5", +"tsql": "e80839f7b11a9775b7596b50" +} +], +[ +"type", +{ +"DuckDB": "a428302e4848ffe877284c84", +"None": "a428302e4848ffe877284c84", +"bigquery": "a428302e4848ffe877284c84", +"databricks": "a428302e4848ffe877284c84", +"duckdb": "a428302e4848ffe877284c84", +"generic": "a428302e4848ffe877284c84", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "a428302e4848ffe877284c84", +"postgres": "a428302e4848ffe877284c84", +"postgresql": "a428302e4848ffe877284c84", +"snowflake": "652ff8b21f638eac8fdc46c5", +"tsql": "a428302e4848ffe877284c84" +} +], +[ +"type", +{ +"DuckDB": "4b27937f44f966ff9f3a7c76", +"None": "4b27937f44f966ff9f3a7c76", +"bigquery": "4b27937f44f966ff9f3a7c76", +"databricks": "4b27937f44f966ff9f3a7c76", +"duckdb": "4b27937f44f966ff9f3a7c76", +"generic": "4b27937f44f966ff9f3a7c76", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "4b27937f44f966ff9f3a7c76", +"postgres": "4b27937f44f966ff9f3a7c76", +"postgresql": "4b27937f44f966ff9f3a7c76", +"snowflake": "4b27937f44f966ff9f3a7c76", +"tsql": "4b27937f44f966ff9f3a7c76" +} +], +[ +"type", +{ +"DuckDB": "d63e1b6839b94c8b42376477", +"None": "d63e1b6839b94c8b42376477", +"bigquery": "d63e1b6839b94c8b42376477", +"databricks": "d63e1b6839b94c8b42376477", +"duckdb": "d63e1b6839b94c8b42376477", +"generic": "d63e1b6839b94c8b42376477", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "d63e1b6839b94c8b42376477", +"postgres": "d63e1b6839b94c8b42376477", +"postgresql": "d63e1b6839b94c8b42376477", +"snowflake": "d63e1b6839b94c8b42376477", +"tsql": "d63e1b6839b94c8b42376477" +} +], +[ +"type", +{ +"DuckDB": "c752fd9fe2ad3b86b8b899da", +"None": "c752fd9fe2ad3b86b8b899da", +"bigquery": "c752fd9fe2ad3b86b8b899da", +"databricks": "c752fd9fe2ad3b86b8b899da", +"duckdb": "c752fd9fe2ad3b86b8b899da", +"generic": "c752fd9fe2ad3b86b8b899da", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "c752fd9fe2ad3b86b8b899da", +"postgres": "e998cd8f0f74af0526b75ff0", +"postgresql": "e998cd8f0f74af0526b75ff0", +"snowflake": "652ff8b21f638eac8fdc46c5", +"tsql": "c752fd9fe2ad3b86b8b899da" +} +], +[ +"type", +{ +"DuckDB": "19bdd92ea0cc5fb028657510", +"None": "1e75e5227bea0ae294ac7af1", +"bigquery": "1e75e5227bea0ae294ac7af1", +"databricks": "1e75e5227bea0ae294ac7af1", +"duckdb": "19bdd92ea0cc5fb028657510", +"generic": "1e75e5227bea0ae294ac7af1", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "19bdd92ea0cc5fb028657510", +"postgres": "19bdd92ea0cc5fb028657510", +"postgresql": "19bdd92ea0cc5fb028657510", +"snowflake": "8ff614b7306c0edbe36ce00b", +"tsql": "901e8c830028411846541f65" +} +], +[ +"type", +{ +"DuckDB": "57922064a7dc546cbb50e42b", +"None": "57922064a7dc546cbb50e42b", +"bigquery": "57922064a7dc546cbb50e42b", +"databricks": "57922064a7dc546cbb50e42b", +"duckdb": "57922064a7dc546cbb50e42b", +"generic": "57922064a7dc546cbb50e42b", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "57922064a7dc546cbb50e42b", +"postgres": "57922064a7dc546cbb50e42b", +"postgresql": "57922064a7dc546cbb50e42b", +"snowflake": "57922064a7dc546cbb50e42b", +"tsql": "57922064a7dc546cbb50e42b" +} +], +[ +"type", +{ +"DuckDB": "d4a375fcf7c3190951992469", +"None": "d4a375fcf7c3190951992469", +"bigquery": "5226d7e2a62c7650a87d6e84", +"databricks": "d4a375fcf7c3190951992469", +"duckdb": "d4a375fcf7c3190951992469", +"generic": "d4a375fcf7c3190951992469", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "d4a375fcf7c3190951992469", +"postgres": "d4a375fcf7c3190951992469", +"postgresql": "d4a375fcf7c3190951992469", +"snowflake": "6306b9e88f7b13dbb6a32c00", +"tsql": "d4a375fcf7c3190951992469" +} +], +[ +"type", +{ +"DuckDB": "8698d724534891869075175e", +"None": "0017a88bb60ec3403c786ed8", +"bigquery": "47e0816fecdd9e015d7aeb79", +"databricks": "0017a88bb60ec3403c786ed8", +"duckdb": "8698d724534891869075175e", +"generic": "0017a88bb60ec3403c786ed8", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "6c03a3450ea4742ee7396e3c", +"postgres": "8698d724534891869075175e", +"postgresql": "8698d724534891869075175e", +"snowflake": "e6f36041b1d9fb8fe3a18cbb", +"tsql": "364031fff119e6530478e415" +} +], +[ +"type", +{ +"DuckDB": "14c32cfb5e5135338d015f42", +"None": "14c32cfb5e5135338d015f42", +"bigquery": "14c32cfb5e5135338d015f42", +"databricks": "14c32cfb5e5135338d015f42", +"duckdb": "14c32cfb5e5135338d015f42", +"generic": "14c32cfb5e5135338d015f42", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "14c32cfb5e5135338d015f42", +"postgres": "14c32cfb5e5135338d015f42", +"postgresql": "14c32cfb5e5135338d015f42", +"snowflake": "14c32cfb5e5135338d015f42", +"tsql": "14c32cfb5e5135338d015f42" +} +], +[ +"type", +{ +"DuckDB": "73d31c6e78cdc3b595b9c4e9", +"None": "73d31c6e78cdc3b595b9c4e9", +"bigquery": "73d31c6e78cdc3b595b9c4e9", +"databricks": "73d31c6e78cdc3b595b9c4e9", +"duckdb": "73d31c6e78cdc3b595b9c4e9", +"generic": "73d31c6e78cdc3b595b9c4e9", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "73d31c6e78cdc3b595b9c4e9", +"postgres": "73d31c6e78cdc3b595b9c4e9", +"postgresql": "73d31c6e78cdc3b595b9c4e9", +"snowflake": "73d31c6e78cdc3b595b9c4e9", +"tsql": "73d31c6e78cdc3b595b9c4e9" +} +], +[ +"type", +{ +"DuckDB": "6f763a99e9c69109526b40c0", +"None": "6f763a99e9c69109526b40c0", +"bigquery": "6f763a99e9c69109526b40c0", +"databricks": "6f763a99e9c69109526b40c0", +"duckdb": "6f763a99e9c69109526b40c0", +"generic": "6f763a99e9c69109526b40c0", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "6f763a99e9c69109526b40c0", +"postgres": "6f763a99e9c69109526b40c0", +"postgresql": "6f763a99e9c69109526b40c0", +"snowflake": "2705f19942a4194a72576911", +"tsql": "6f763a99e9c69109526b40c0" +} +], +[ +"type", +{ +"DuckDB": "78b2cf275c640af54feeca31", +"None": "78b2cf275c640af54feeca31", +"bigquery": "1e75e5227bea0ae294ac7af1", +"databricks": "78b2cf275c640af54feeca31", +"duckdb": "78b2cf275c640af54feeca31", +"generic": "78b2cf275c640af54feeca31", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "78b2cf275c640af54feeca31", +"postgres": "78b2cf275c640af54feeca31", +"postgresql": "78b2cf275c640af54feeca31", +"snowflake": "8ff614b7306c0edbe36ce00b", +"tsql": "78b2cf275c640af54feeca31" +} +], +[ +"type", +{ +"DuckDB": "f78e07518606fbc42e0f28fe", +"None": "f78e07518606fbc42e0f28fe", +"bigquery": "f78e07518606fbc42e0f28fe", +"databricks": "f78e07518606fbc42e0f28fe", +"duckdb": "f78e07518606fbc42e0f28fe", +"generic": "f78e07518606fbc42e0f28fe", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "f78e07518606fbc42e0f28fe", +"postgres": "f78e07518606fbc42e0f28fe", +"postgresql": "f78e07518606fbc42e0f28fe", +"snowflake": "f78e07518606fbc42e0f28fe", +"tsql": "f78e07518606fbc42e0f28fe" +} +], +[ +"type", +{ +"DuckDB": "11f5a5e0f332f3a87c8ff396", +"None": "11f5a5e0f332f3a87c8ff396", +"bigquery": "11f5a5e0f332f3a87c8ff396", +"databricks": "11f5a5e0f332f3a87c8ff396", +"duckdb": "11f5a5e0f332f3a87c8ff396", +"generic": "11f5a5e0f332f3a87c8ff396", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "11f5a5e0f332f3a87c8ff396", +"postgres": "11f5a5e0f332f3a87c8ff396", +"postgresql": "11f5a5e0f332f3a87c8ff396", +"snowflake": "11f5a5e0f332f3a87c8ff396", +"tsql": "11f5a5e0f332f3a87c8ff396" +} +], +[ +"type", +{ +"DuckDB": "ebc821a95b9286e22c2b26d0", +"None": "ebc821a95b9286e22c2b26d0", +"bigquery": "19a1a80ffc06169f32694de8", +"databricks": "ebc821a95b9286e22c2b26d0", +"duckdb": "ebc821a95b9286e22c2b26d0", +"generic": "ebc821a95b9286e22c2b26d0", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "ebc821a95b9286e22c2b26d0", +"postgres": "ebc821a95b9286e22c2b26d0", +"postgresql": "ebc821a95b9286e22c2b26d0", +"snowflake": "ebc821a95b9286e22c2b26d0", +"tsql": "ebc821a95b9286e22c2b26d0" +} +], +[ +"type", +{ +"DuckDB": "f20ec02865769c13aa2d2b67", +"None": "f20ec02865769c13aa2d2b67", +"bigquery": "8575088c2f44d4349e1307a4", +"databricks": "e40ec5056d50c25089ee3934", +"duckdb": "f20ec02865769c13aa2d2b67", +"generic": "f20ec02865769c13aa2d2b67", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "f20ec02865769c13aa2d2b67", +"postgres": "f20ec02865769c13aa2d2b67", +"postgresql": "f20ec02865769c13aa2d2b67", +"snowflake": "e5502f3bf9aad4d98960c7b4", +"tsql": "f20ec02865769c13aa2d2b67" +} +], +[ +"type", +{ +"DuckDB": "d22967425ad0e5a048596ac6", +"None": "d22967425ad0e5a048596ac6", +"bigquery": "d22967425ad0e5a048596ac6", +"databricks": "d22967425ad0e5a048596ac6", +"duckdb": "d22967425ad0e5a048596ac6", +"generic": "d22967425ad0e5a048596ac6", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "d22967425ad0e5a048596ac6", +"postgres": "d22967425ad0e5a048596ac6", +"postgresql": "d22967425ad0e5a048596ac6", +"snowflake": "d22967425ad0e5a048596ac6", +"tsql": "d22967425ad0e5a048596ac6" +} +], +[ +"type", +{ +"DuckDB": "1eb7fb4e8cf75773c5573562", +"None": "1eb7fb4e8cf75773c5573562", +"bigquery": "c9b810639795a7bfab91b98d", +"databricks": "1eb7fb4e8cf75773c5573562", +"duckdb": "1eb7fb4e8cf75773c5573562", +"generic": "1eb7fb4e8cf75773c5573562", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "1eb7fb4e8cf75773c5573562", +"postgres": "1eb7fb4e8cf75773c5573562", +"postgresql": "1eb7fb4e8cf75773c5573562", +"snowflake": "97a20344d811fb77c7690863", +"tsql": "1eb7fb4e8cf75773c5573562" +} +], +[ +"type", +{ +"DuckDB": "eded69a48ff8476dbf73ff05", +"None": "eded69a48ff8476dbf73ff05", +"bigquery": "eded69a48ff8476dbf73ff05", +"databricks": "eded69a48ff8476dbf73ff05", +"duckdb": "eded69a48ff8476dbf73ff05", +"generic": "eded69a48ff8476dbf73ff05", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "eded69a48ff8476dbf73ff05", +"postgres": "eded69a48ff8476dbf73ff05", +"postgresql": "eded69a48ff8476dbf73ff05", +"snowflake": "eded69a48ff8476dbf73ff05", +"tsql": "eded69a48ff8476dbf73ff05" +} +], +[ +"type", +{ +"DuckDB": "d7bedd3c7663f140f4d10bd4", +"None": "d7bedd3c7663f140f4d10bd4", +"bigquery": "d7bedd3c7663f140f4d10bd4", +"databricks": "d7bedd3c7663f140f4d10bd4", +"duckdb": "d7bedd3c7663f140f4d10bd4", +"generic": "d7bedd3c7663f140f4d10bd4", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "d7bedd3c7663f140f4d10bd4", +"postgres": "d7bedd3c7663f140f4d10bd4", +"postgresql": "d7bedd3c7663f140f4d10bd4", +"snowflake": "d7bedd3c7663f140f4d10bd4", +"tsql": "d7bedd3c7663f140f4d10bd4" +} +], +[ +"type", +{ +"DuckDB": "d2c97d221599d038d9875873", +"None": "d2c97d221599d038d9875873", +"bigquery": "d2c97d221599d038d9875873", +"databricks": "d2c97d221599d038d9875873", +"duckdb": "d2c97d221599d038d9875873", +"generic": "d2c97d221599d038d9875873", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "d2c97d221599d038d9875873", +"postgres": "d2c97d221599d038d9875873", +"postgresql": "d2c97d221599d038d9875873", +"snowflake": "d2c97d221599d038d9875873", +"tsql": "d2c97d221599d038d9875873" +} +], +[ +"type", +{ +"DuckDB": "c82815abe30b3d099903f838", +"None": "c82815abe30b3d099903f838", +"bigquery": "c82815abe30b3d099903f838", +"databricks": "c82815abe30b3d099903f838", +"duckdb": "c82815abe30b3d099903f838", +"generic": "c82815abe30b3d099903f838", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "c82815abe30b3d099903f838", +"postgres": "c82815abe30b3d099903f838", +"postgresql": "c82815abe30b3d099903f838", +"snowflake": "c82815abe30b3d099903f838", +"tsql": "07ca53fdc57a22a78ad75787" +} +], +[ +"type", +{ +"DuckDB": "3739567e772c71d3b587ca23", +"None": "3739567e772c71d3b587ca23", +"bigquery": "3739567e772c71d3b587ca23", +"databricks": "3739567e772c71d3b587ca23", +"duckdb": "3739567e772c71d3b587ca23", +"generic": "3739567e772c71d3b587ca23", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "3739567e772c71d3b587ca23", +"postgres": "3739567e772c71d3b587ca23", +"postgresql": "3739567e772c71d3b587ca23", +"snowflake": "3739567e772c71d3b587ca23", +"tsql": "3739567e772c71d3b587ca23" +} +], +[ +"type", +{ +"DuckDB": "83fdbd1f0a6ee4e72faa4d94", +"None": "83fdbd1f0a6ee4e72faa4d94", +"bigquery": "83fdbd1f0a6ee4e72faa4d94", +"databricks": "83fdbd1f0a6ee4e72faa4d94", +"duckdb": "83fdbd1f0a6ee4e72faa4d94", +"generic": "83fdbd1f0a6ee4e72faa4d94", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "83fdbd1f0a6ee4e72faa4d94", +"postgres": "83fdbd1f0a6ee4e72faa4d94", +"postgresql": "83fdbd1f0a6ee4e72faa4d94", +"snowflake": "83fdbd1f0a6ee4e72faa4d94", +"tsql": "83fdbd1f0a6ee4e72faa4d94" +} +], +[ +"type", +{ +"DuckDB": "af57dd2575fa5a01917ec9cf", +"None": "af57dd2575fa5a01917ec9cf", +"bigquery": "af57dd2575fa5a01917ec9cf", +"databricks": "af57dd2575fa5a01917ec9cf", +"duckdb": "af57dd2575fa5a01917ec9cf", +"generic": "af57dd2575fa5a01917ec9cf", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "af57dd2575fa5a01917ec9cf", +"postgres": "af57dd2575fa5a01917ec9cf", +"postgresql": "af57dd2575fa5a01917ec9cf", +"snowflake": "af57dd2575fa5a01917ec9cf", +"tsql": "af57dd2575fa5a01917ec9cf" +} +], +[ +"type", +{ +"DuckDB": "c50a316d091c821866e4bfba", +"None": "c50a316d091c821866e4bfba", +"bigquery": "c50a316d091c821866e4bfba", +"databricks": "c50a316d091c821866e4bfba", +"duckdb": "c50a316d091c821866e4bfba", +"generic": "c50a316d091c821866e4bfba", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "c50a316d091c821866e4bfba", +"postgres": "c50a316d091c821866e4bfba", +"postgresql": "c50a316d091c821866e4bfba", +"snowflake": "c50a316d091c821866e4bfba", +"tsql": "c50a316d091c821866e4bfba" +} +], +[ +"type", +{ +"DuckDB": "c0eec31620dfc2ac0028173d", +"None": "d3bcf10e00645b12a802c7d0", +"bigquery": "02e0b2ed25f32a8d09350a23", +"databricks": "d3bcf10e00645b12a802c7d0", +"duckdb": "c0eec31620dfc2ac0028173d", +"generic": "d3bcf10e00645b12a802c7d0", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "6c03a3450ea4742ee7396e3c", +"postgres": "c0eec31620dfc2ac0028173d", +"postgresql": "c0eec31620dfc2ac0028173d", +"snowflake": "d379c0ee4dad89e570b7329e", +"tsql": "d1dc9a140dbe2eb1874c6ad7" +} +], +[ +"type", +{ +"DuckDB": "39257e40f37cf05c780a4e22", +"None": "39257e40f37cf05c780a4e22", +"bigquery": "39257e40f37cf05c780a4e22", +"databricks": "39257e40f37cf05c780a4e22", +"duckdb": "39257e40f37cf05c780a4e22", +"generic": "39257e40f37cf05c780a4e22", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "39257e40f37cf05c780a4e22", +"postgres": "39257e40f37cf05c780a4e22", +"postgresql": "39257e40f37cf05c780a4e22", +"snowflake": "39257e40f37cf05c780a4e22", +"tsql": "39257e40f37cf05c780a4e22" +} +], +[ +"type", +{ +"DuckDB": "aab0389e2b5470136660bf8a", +"None": "aab0389e2b5470136660bf8a", +"bigquery": "c9b810639795a7bfab91b98d", +"databricks": "aab0389e2b5470136660bf8a", +"duckdb": "aab0389e2b5470136660bf8a", +"generic": "aab0389e2b5470136660bf8a", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "aab0389e2b5470136660bf8a", +"postgres": "aab0389e2b5470136660bf8a", +"postgresql": "aab0389e2b5470136660bf8a", +"snowflake": "97a20344d811fb77c7690863", +"tsql": "aab0389e2b5470136660bf8a" +} +], +[ +"type", +{ +"DuckDB": "251aba3fef503ce64556c701", +"None": "251aba3fef503ce64556c701", +"bigquery": "c50a316d091c821866e4bfba", +"databricks": "251aba3fef503ce64556c701", +"duckdb": "251aba3fef503ce64556c701", +"generic": "251aba3fef503ce64556c701", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "251aba3fef503ce64556c701", +"postgres": "251aba3fef503ce64556c701", +"postgresql": "251aba3fef503ce64556c701", +"snowflake": "c50a316d091c821866e4bfba", +"tsql": "251aba3fef503ce64556c701" +} +], +[ +"type", +{ +"DuckDB": "aae2b1fe6f2d9807ecde412b", +"None": "aae2b1fe6f2d9807ecde412b", +"bigquery": "e1c36a5cdd2427ff2b089ac9", +"databricks": "aae2b1fe6f2d9807ecde412b", +"duckdb": "aae2b1fe6f2d9807ecde412b", +"generic": "aae2b1fe6f2d9807ecde412b", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "aae2b1fe6f2d9807ecde412b", +"postgres": "aae2b1fe6f2d9807ecde412b", +"postgresql": "aae2b1fe6f2d9807ecde412b", +"snowflake": "aae2b1fe6f2d9807ecde412b", +"tsql": "aae2b1fe6f2d9807ecde412b" +} +], +[ +"type", +{ +"DuckDB": "ebc821a95b9286e22c2b26d0", +"None": "ebc821a95b9286e22c2b26d0", +"bigquery": "19a1a80ffc06169f32694de8", +"databricks": "ebc821a95b9286e22c2b26d0", +"duckdb": "ebc821a95b9286e22c2b26d0", +"generic": "ebc821a95b9286e22c2b26d0", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "ebc821a95b9286e22c2b26d0", +"postgres": "ebc821a95b9286e22c2b26d0", +"postgresql": "ebc821a95b9286e22c2b26d0", +"snowflake": "ebc821a95b9286e22c2b26d0", +"tsql": "ebc821a95b9286e22c2b26d0" +} +], +[ +"type", +{ +"DuckDB": "251aba3fef503ce64556c701", +"None": "251aba3fef503ce64556c701", +"bigquery": "c50a316d091c821866e4bfba", +"databricks": "251aba3fef503ce64556c701", +"duckdb": "251aba3fef503ce64556c701", +"generic": "251aba3fef503ce64556c701", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "251aba3fef503ce64556c701", +"postgres": "251aba3fef503ce64556c701", +"postgresql": "251aba3fef503ce64556c701", +"snowflake": "c50a316d091c821866e4bfba", +"tsql": "251aba3fef503ce64556c701" +} +], +[ +"type", +{ +"DuckDB": "bfce65957f9ed1017daedf21", +"None": "bfce65957f9ed1017daedf21", +"bigquery": "a82a2bde913bf78a8d3f9332", +"databricks": "2d20c9c50b78d6e633cf256a", +"duckdb": "bfce65957f9ed1017daedf21", +"generic": "bfce65957f9ed1017daedf21", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "bfce65957f9ed1017daedf21", +"postgres": "bfce65957f9ed1017daedf21", +"postgresql": "bfce65957f9ed1017daedf21", +"snowflake": "2d20c9c50b78d6e633cf256a", +"tsql": "2d20c9c50b78d6e633cf256a" +} +], +[ +"type", +{ +"DuckDB": "3f71ab5f3c1c040da96f2cec", +"None": "3f71ab5f3c1c040da96f2cec", +"bigquery": "3f71ab5f3c1c040da96f2cec", +"databricks": "3f71ab5f3c1c040da96f2cec", +"duckdb": "3f71ab5f3c1c040da96f2cec", +"generic": "3f71ab5f3c1c040da96f2cec", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "3f71ab5f3c1c040da96f2cec", +"postgres": "3f71ab5f3c1c040da96f2cec", +"postgresql": "3f71ab5f3c1c040da96f2cec", +"snowflake": "3f71ab5f3c1c040da96f2cec", +"tsql": "3f71ab5f3c1c040da96f2cec" +} +], +[ +"type", +{ +"DuckDB": "53ec6db7b2c81e2ceee285a3", +"None": "53ec6db7b2c81e2ceee285a3", +"bigquery": "53ec6db7b2c81e2ceee285a3", +"databricks": "53ec6db7b2c81e2ceee285a3", +"duckdb": "53ec6db7b2c81e2ceee285a3", +"generic": "53ec6db7b2c81e2ceee285a3", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "53ec6db7b2c81e2ceee285a3", +"postgres": "53ec6db7b2c81e2ceee285a3", +"postgresql": "53ec6db7b2c81e2ceee285a3", +"snowflake": "53ec6db7b2c81e2ceee285a3", +"tsql": "53ec6db7b2c81e2ceee285a3" +} +], +[ +"type", +{ +"DuckDB": "5abf4ec799a2ec32fb10da7e", +"None": "5abf4ec799a2ec32fb10da7e", +"bigquery": "5abf4ec799a2ec32fb10da7e", +"databricks": "5abf4ec799a2ec32fb10da7e", +"duckdb": "5abf4ec799a2ec32fb10da7e", +"generic": "5abf4ec799a2ec32fb10da7e", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "5abf4ec799a2ec32fb10da7e", +"postgres": "5abf4ec799a2ec32fb10da7e", +"postgresql": "5abf4ec799a2ec32fb10da7e", +"snowflake": "a5656d70e208254d1d3e9b4f", +"tsql": "5abf4ec799a2ec32fb10da7e" +} +], +[ +"type", +{ +"DuckDB": "461923a0d34defd0c726d6e5", +"None": "461923a0d34defd0c726d6e5", +"bigquery": "b5c4d5044b2a6e70633f0d0a", +"databricks": "461923a0d34defd0c726d6e5", +"duckdb": "461923a0d34defd0c726d6e5", +"generic": "461923a0d34defd0c726d6e5", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "461923a0d34defd0c726d6e5", +"postgres": "461923a0d34defd0c726d6e5", +"postgresql": "461923a0d34defd0c726d6e5", +"snowflake": "461923a0d34defd0c726d6e5", +"tsql": "461923a0d34defd0c726d6e5" +} +], +[ +"type", +{ +"DuckDB": "2427f5522575cdc3d6a74e4c", +"None": "2427f5522575cdc3d6a74e4c", +"bigquery": "2427f5522575cdc3d6a74e4c", +"databricks": "2427f5522575cdc3d6a74e4c", +"duckdb": "2427f5522575cdc3d6a74e4c", +"generic": "2427f5522575cdc3d6a74e4c", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "2427f5522575cdc3d6a74e4c", +"postgres": "2427f5522575cdc3d6a74e4c", +"postgresql": "2427f5522575cdc3d6a74e4c", +"snowflake": "2427f5522575cdc3d6a74e4c", +"tsql": "2427f5522575cdc3d6a74e4c" +} +], +[ +"type", +{ +"DuckDB": "158229f1c3f1085b80d3190e", +"None": "158229f1c3f1085b80d3190e", +"bigquery": "158229f1c3f1085b80d3190e", +"databricks": "158229f1c3f1085b80d3190e", +"duckdb": "158229f1c3f1085b80d3190e", +"generic": "158229f1c3f1085b80d3190e", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "158229f1c3f1085b80d3190e", +"postgres": "158229f1c3f1085b80d3190e", +"postgresql": "158229f1c3f1085b80d3190e", +"snowflake": "158229f1c3f1085b80d3190e", +"tsql": "158229f1c3f1085b80d3190e" +} +], +[ +"type", +{ +"DuckDB": "e3bc1b8bad22d8104417b00f", +"None": "e3bc1b8bad22d8104417b00f", +"bigquery": "c50a316d091c821866e4bfba", +"databricks": "e3bc1b8bad22d8104417b00f", +"duckdb": "e3bc1b8bad22d8104417b00f", +"generic": "e3bc1b8bad22d8104417b00f", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "e3bc1b8bad22d8104417b00f", +"postgres": "111af35848fe500ec2ae54b2", +"postgresql": "111af35848fe500ec2ae54b2", +"snowflake": "e3bc1b8bad22d8104417b00f", +"tsql": "e3bc1b8bad22d8104417b00f" +} +], +[ +"type", +{ +"DuckDB": "70fb4728c3adcf6dbe4975d5", +"None": "70fb4728c3adcf6dbe4975d5", +"bigquery": "70fb4728c3adcf6dbe4975d5", +"databricks": "70fb4728c3adcf6dbe4975d5", +"duckdb": "70fb4728c3adcf6dbe4975d5", +"generic": "70fb4728c3adcf6dbe4975d5", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "70fb4728c3adcf6dbe4975d5", +"postgres": "70fb4728c3adcf6dbe4975d5", +"postgresql": "70fb4728c3adcf6dbe4975d5", +"snowflake": "70fb4728c3adcf6dbe4975d5", +"tsql": "70fb4728c3adcf6dbe4975d5" +} +], +[ +"type", +{ +"DuckDB": "9bb8e9bdc03c6262fc0b887e", +"None": "9bb8e9bdc03c6262fc0b887e", +"bigquery": "9bb8e9bdc03c6262fc0b887e", +"databricks": "9bb8e9bdc03c6262fc0b887e", +"duckdb": "9bb8e9bdc03c6262fc0b887e", +"generic": "9bb8e9bdc03c6262fc0b887e", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "9bb8e9bdc03c6262fc0b887e", +"postgres": "9bb8e9bdc03c6262fc0b887e", +"postgresql": "9bb8e9bdc03c6262fc0b887e", +"snowflake": "9bb8e9bdc03c6262fc0b887e", +"tsql": "9bb8e9bdc03c6262fc0b887e" +} +], +[ +"type", +{ +"DuckDB": "70fb4728c3adcf6dbe4975d5", +"None": "70fb4728c3adcf6dbe4975d5", +"bigquery": "70fb4728c3adcf6dbe4975d5", +"databricks": "70fb4728c3adcf6dbe4975d5", +"duckdb": "70fb4728c3adcf6dbe4975d5", +"generic": "70fb4728c3adcf6dbe4975d5", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "70fb4728c3adcf6dbe4975d5", +"postgres": "70fb4728c3adcf6dbe4975d5", +"postgresql": "70fb4728c3adcf6dbe4975d5", +"snowflake": "70fb4728c3adcf6dbe4975d5", +"tsql": "70fb4728c3adcf6dbe4975d5" +} +], +[ +"type", +{ +"DuckDB": "b69a57be16780e0a5e4acadb", +"None": "b69a57be16780e0a5e4acadb", +"bigquery": "b69a57be16780e0a5e4acadb", +"databricks": "b69a57be16780e0a5e4acadb", +"duckdb": "b69a57be16780e0a5e4acadb", +"generic": "b69a57be16780e0a5e4acadb", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "b69a57be16780e0a5e4acadb", +"postgres": "b69a57be16780e0a5e4acadb", +"postgresql": "b69a57be16780e0a5e4acadb", +"snowflake": "b69a57be16780e0a5e4acadb", +"tsql": "b69a57be16780e0a5e4acadb" +} +], +[ +"type", +{ +"DuckDB": "c703e456945a8f06d005c98b", +"None": "c703e456945a8f06d005c98b", +"bigquery": "c703e456945a8f06d005c98b", +"databricks": "c703e456945a8f06d005c98b", +"duckdb": "c703e456945a8f06d005c98b", +"generic": "c703e456945a8f06d005c98b", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "c703e456945a8f06d005c98b", +"postgres": "c703e456945a8f06d005c98b", +"postgresql": "c703e456945a8f06d005c98b", +"snowflake": "c703e456945a8f06d005c98b", +"tsql": "c703e456945a8f06d005c98b" +} +], +[ +"type", +{ +"DuckDB": "8371f7fd8d5afa0c7c86482b", +"None": "8371f7fd8d5afa0c7c86482b", +"bigquery": "8371f7fd8d5afa0c7c86482b", +"databricks": "8371f7fd8d5afa0c7c86482b", +"duckdb": "8371f7fd8d5afa0c7c86482b", +"generic": "8371f7fd8d5afa0c7c86482b", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "8371f7fd8d5afa0c7c86482b", +"postgres": "8371f7fd8d5afa0c7c86482b", +"postgresql": "8371f7fd8d5afa0c7c86482b", +"snowflake": "8371f7fd8d5afa0c7c86482b", +"tsql": "8371f7fd8d5afa0c7c86482b" +} +], +[ +"type", +{ +"DuckDB": "f4fc387af06ec14d0ed37c37", +"None": "f4fc387af06ec14d0ed37c37", +"bigquery": "f4fc387af06ec14d0ed37c37", +"databricks": "f4fc387af06ec14d0ed37c37", +"duckdb": "f4fc387af06ec14d0ed37c37", +"generic": "f4fc387af06ec14d0ed37c37", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "f4fc387af06ec14d0ed37c37", +"postgres": "f4fc387af06ec14d0ed37c37", +"postgresql": "f4fc387af06ec14d0ed37c37", +"snowflake": "f4fc387af06ec14d0ed37c37", +"tsql": "f4fc387af06ec14d0ed37c37" +} +], +[ +"type", +{ +"DuckDB": "97a92f4a47efe38678dac07f", +"None": "97a92f4a47efe38678dac07f", +"bigquery": "97a92f4a47efe38678dac07f", +"databricks": "97a92f4a47efe38678dac07f", +"duckdb": "97a92f4a47efe38678dac07f", +"generic": "97a92f4a47efe38678dac07f", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "97a92f4a47efe38678dac07f", +"postgres": "97a92f4a47efe38678dac07f", +"postgresql": "97a92f4a47efe38678dac07f", +"snowflake": "97a92f4a47efe38678dac07f", +"tsql": "97a92f4a47efe38678dac07f" +} +], +[ +"type", +{ +"DuckDB": "d61c83ef8bfdf043fa672cb5", +"None": "d61c83ef8bfdf043fa672cb5", +"bigquery": "c9b810639795a7bfab91b98d", +"databricks": "d61c83ef8bfdf043fa672cb5", +"duckdb": "d61c83ef8bfdf043fa672cb5", +"generic": "d61c83ef8bfdf043fa672cb5", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "d61c83ef8bfdf043fa672cb5", +"postgres": "d61c83ef8bfdf043fa672cb5", +"postgresql": "d61c83ef8bfdf043fa672cb5", +"snowflake": "97a20344d811fb77c7690863", +"tsql": "d61c83ef8bfdf043fa672cb5" +} +], +[ +"type", +{ +"DuckDB": "c6889f2965db73017be6f6e7", +"None": "c6889f2965db73017be6f6e7", +"bigquery": "a428302e4848ffe877284c84", +"databricks": "c6889f2965db73017be6f6e7", +"duckdb": "c6889f2965db73017be6f6e7", +"generic": "c6889f2965db73017be6f6e7", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "c6889f2965db73017be6f6e7", +"postgres": "c6889f2965db73017be6f6e7", +"postgresql": "c6889f2965db73017be6f6e7", +"snowflake": "652ff8b21f638eac8fdc46c5", +"tsql": "c6889f2965db73017be6f6e7" +} +], +[ +"type", +{ +"DuckDB": "279ea7f6f6a3910de04b795b", +"None": "279ea7f6f6a3910de04b795b", +"bigquery": "279ea7f6f6a3910de04b795b", +"databricks": "279ea7f6f6a3910de04b795b", +"duckdb": "279ea7f6f6a3910de04b795b", +"generic": "279ea7f6f6a3910de04b795b", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "279ea7f6f6a3910de04b795b", +"postgres": "279ea7f6f6a3910de04b795b", +"postgresql": "279ea7f6f6a3910de04b795b", +"snowflake": "279ea7f6f6a3910de04b795b", +"tsql": "279ea7f6f6a3910de04b795b" +} +], +[ +"type", +{ +"DuckDB": "04f0b885283ff5fc129874ad", +"None": "04f0b885283ff5fc129874ad", +"bigquery": "04f0b885283ff5fc129874ad", +"databricks": "04f0b885283ff5fc129874ad", +"duckdb": "04f0b885283ff5fc129874ad", +"generic": "04f0b885283ff5fc129874ad", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "04f0b885283ff5fc129874ad", +"postgres": "04f0b885283ff5fc129874ad", +"postgresql": "04f0b885283ff5fc129874ad", +"snowflake": "04f0b885283ff5fc129874ad", +"tsql": "04f0b885283ff5fc129874ad" +} +], +[ +"type", +{ +"DuckDB": "c6654395c62d21b415299f72", +"None": "c6654395c62d21b415299f72", +"bigquery": "0712c33a016f7dd6a37ee011", +"databricks": "c6654395c62d21b415299f72", +"duckdb": "c6654395c62d21b415299f72", +"generic": "c6654395c62d21b415299f72", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "2978a8fe925c7f93c6e9fcfb", +"postgres": "c6654395c62d21b415299f72", +"postgresql": "c6654395c62d21b415299f72", +"snowflake": "0712c33a016f7dd6a37ee011", +"tsql": "c6654395c62d21b415299f72" +} +], +[ +"type", +{ +"DuckDB": "70fb4728c3adcf6dbe4975d5", +"None": "70fb4728c3adcf6dbe4975d5", +"bigquery": "70fb4728c3adcf6dbe4975d5", +"databricks": "70fb4728c3adcf6dbe4975d5", +"duckdb": "70fb4728c3adcf6dbe4975d5", +"generic": "70fb4728c3adcf6dbe4975d5", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "70fb4728c3adcf6dbe4975d5", +"postgres": "70fb4728c3adcf6dbe4975d5", +"postgresql": "70fb4728c3adcf6dbe4975d5", +"snowflake": "70fb4728c3adcf6dbe4975d5", +"tsql": "70fb4728c3adcf6dbe4975d5" +} +], +[ +"type", +{ +"DuckDB": "93c1b5b5960e26479baf88d0", +"None": "93c1b5b5960e26479baf88d0", +"bigquery": "93c1b5b5960e26479baf88d0", +"databricks": "93c1b5b5960e26479baf88d0", +"duckdb": "93c1b5b5960e26479baf88d0", +"generic": "93c1b5b5960e26479baf88d0", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "93c1b5b5960e26479baf88d0", +"postgres": "93c1b5b5960e26479baf88d0", +"postgresql": "93c1b5b5960e26479baf88d0", +"snowflake": "93c1b5b5960e26479baf88d0", +"tsql": "93c1b5b5960e26479baf88d0" +} +], +[ +"type", +{ +"DuckDB": "6a912271e85e6d85c1238bc0", +"None": "6a912271e85e6d85c1238bc0", +"bigquery": "6a912271e85e6d85c1238bc0", +"databricks": "6a912271e85e6d85c1238bc0", +"duckdb": "6a912271e85e6d85c1238bc0", +"generic": "6a912271e85e6d85c1238bc0", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "6a912271e85e6d85c1238bc0", +"postgres": "6a912271e85e6d85c1238bc0", +"postgresql": "6a912271e85e6d85c1238bc0", +"snowflake": "6a912271e85e6d85c1238bc0", +"tsql": "6a912271e85e6d85c1238bc0" +} +], +[ +"type", +{ +"DuckDB": "5abf4ec799a2ec32fb10da7e", +"None": "5abf4ec799a2ec32fb10da7e", +"bigquery": "5abf4ec799a2ec32fb10da7e", +"databricks": "5abf4ec799a2ec32fb10da7e", +"duckdb": "5abf4ec799a2ec32fb10da7e", +"generic": "5abf4ec799a2ec32fb10da7e", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "5abf4ec799a2ec32fb10da7e", +"postgres": "5abf4ec799a2ec32fb10da7e", +"postgresql": "5abf4ec799a2ec32fb10da7e", +"snowflake": "a5656d70e208254d1d3e9b4f", +"tsql": "5abf4ec799a2ec32fb10da7e" +} +], +[ +"type", +{ +"DuckDB": "eea9a25a6fbf8e049a445513", +"None": "eea9a25a6fbf8e049a445513", +"bigquery": "eea9a25a6fbf8e049a445513", +"databricks": "eea9a25a6fbf8e049a445513", +"duckdb": "eea9a25a6fbf8e049a445513", +"generic": "eea9a25a6fbf8e049a445513", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "eea9a25a6fbf8e049a445513", +"postgres": "eea9a25a6fbf8e049a445513", +"postgresql": "eea9a25a6fbf8e049a445513", +"snowflake": "eea9a25a6fbf8e049a445513", +"tsql": "eea9a25a6fbf8e049a445513" +} +], +[ +"type", +{ +"DuckDB": "304be1d51ad99bfab3750f57", +"None": "304be1d51ad99bfab3750f57", +"bigquery": "304be1d51ad99bfab3750f57", +"databricks": "304be1d51ad99bfab3750f57", +"duckdb": "304be1d51ad99bfab3750f57", +"generic": "304be1d51ad99bfab3750f57", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "304be1d51ad99bfab3750f57", +"postgres": "304be1d51ad99bfab3750f57", +"postgresql": "304be1d51ad99bfab3750f57", +"snowflake": "304be1d51ad99bfab3750f57", +"tsql": "304be1d51ad99bfab3750f57" +} +], +[ +"type", +{ +"DuckDB": "2bfa352725f9d8a91250f75e", +"None": "2bfa352725f9d8a91250f75e", +"bigquery": "2bfa352725f9d8a91250f75e", +"databricks": "2bfa352725f9d8a91250f75e", +"duckdb": "2bfa352725f9d8a91250f75e", +"generic": "2bfa352725f9d8a91250f75e", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "2bfa352725f9d8a91250f75e", +"postgres": "2bfa352725f9d8a91250f75e", +"postgresql": "2bfa352725f9d8a91250f75e", +"snowflake": "2bfa352725f9d8a91250f75e", +"tsql": "2bfa352725f9d8a91250f75e" +} +], +[ +"type", +{ +"DuckDB": "ebc821a95b9286e22c2b26d0", +"None": "ebc821a95b9286e22c2b26d0", +"bigquery": "19a1a80ffc06169f32694de8", +"databricks": "ebc821a95b9286e22c2b26d0", +"duckdb": "ebc821a95b9286e22c2b26d0", +"generic": "ebc821a95b9286e22c2b26d0", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "ebc821a95b9286e22c2b26d0", +"postgres": "ebc821a95b9286e22c2b26d0", +"postgresql": "ebc821a95b9286e22c2b26d0", +"snowflake": "ebc821a95b9286e22c2b26d0", +"tsql": "ebc821a95b9286e22c2b26d0" +} +], +[ +"type", +{ +"DuckDB": "5d0a19a893dbf0c1e6e9f15c", +"None": "5d0a19a893dbf0c1e6e9f15c", +"bigquery": "5d0a19a893dbf0c1e6e9f15c", +"databricks": "5d0a19a893dbf0c1e6e9f15c", +"duckdb": "5d0a19a893dbf0c1e6e9f15c", +"generic": "5d0a19a893dbf0c1e6e9f15c", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "5d0a19a893dbf0c1e6e9f15c", +"postgres": "5d0a19a893dbf0c1e6e9f15c", +"postgresql": "5d0a19a893dbf0c1e6e9f15c", +"snowflake": "5d0a19a893dbf0c1e6e9f15c", +"tsql": "5d0a19a893dbf0c1e6e9f15c" +} +], +[ +"type", +{ +"DuckDB": "9bb8e9bdc03c6262fc0b887e", +"None": "9bb8e9bdc03c6262fc0b887e", +"bigquery": "9bb8e9bdc03c6262fc0b887e", +"databricks": "9bb8e9bdc03c6262fc0b887e", +"duckdb": "9bb8e9bdc03c6262fc0b887e", +"generic": "9bb8e9bdc03c6262fc0b887e", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "9bb8e9bdc03c6262fc0b887e", +"postgres": "9bb8e9bdc03c6262fc0b887e", +"postgresql": "9bb8e9bdc03c6262fc0b887e", +"snowflake": "9bb8e9bdc03c6262fc0b887e", +"tsql": "9bb8e9bdc03c6262fc0b887e" +} +], +[ +"type", +{ +"DuckDB": "15f0b4e032d5524678c61cae", +"None": "15f0b4e032d5524678c61cae", +"bigquery": "15f0b4e032d5524678c61cae", +"databricks": "15f0b4e032d5524678c61cae", +"duckdb": "15f0b4e032d5524678c61cae", +"generic": "15f0b4e032d5524678c61cae", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "15f0b4e032d5524678c61cae", +"postgres": "15f0b4e032d5524678c61cae", +"postgresql": "15f0b4e032d5524678c61cae", +"snowflake": "15f0b4e032d5524678c61cae", +"tsql": "15f0b4e032d5524678c61cae" +} +], +[ +"type", +{ +"DuckDB": "cafb5cff5526dd419baad0ed", +"None": "cafb5cff5526dd419baad0ed", +"bigquery": "cafb5cff5526dd419baad0ed", +"databricks": "cafb5cff5526dd419baad0ed", +"duckdb": "cafb5cff5526dd419baad0ed", +"generic": "cafb5cff5526dd419baad0ed", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "cafb5cff5526dd419baad0ed", +"postgres": "cafb5cff5526dd419baad0ed", +"postgresql": "cafb5cff5526dd419baad0ed", +"snowflake": "cafb5cff5526dd419baad0ed", +"tsql": "cafb5cff5526dd419baad0ed" +} +], +[ +"type", +{ +"DuckDB": "8a3f094f18fb4047f0febf59", +"None": "8a3f094f18fb4047f0febf59", +"bigquery": "5c28019dce48a74708c90a76", +"databricks": "8a3f094f18fb4047f0febf59", +"duckdb": "8a3f094f18fb4047f0febf59", +"generic": "8a3f094f18fb4047f0febf59", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "5c28019dce48a74708c90a76", +"postgres": "8a3f094f18fb4047f0febf59", +"postgresql": "8a3f094f18fb4047f0febf59", +"snowflake": "850deea990b52b82b36a9848", +"tsql": "cc8534b198fe0c225bbffd8d" +} +], +[ +"type", +{ +"DuckDB": "bf5a83d0c02f8890941c7ec8", +"None": "bf5a83d0c02f8890941c7ec8", +"bigquery": "bf5a83d0c02f8890941c7ec8", +"databricks": "bf5a83d0c02f8890941c7ec8", +"duckdb": "bf5a83d0c02f8890941c7ec8", +"generic": "bf5a83d0c02f8890941c7ec8", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "bf5a83d0c02f8890941c7ec8", +"postgres": "bf5a83d0c02f8890941c7ec8", +"postgresql": "bf5a83d0c02f8890941c7ec8", +"snowflake": "bf5a83d0c02f8890941c7ec8", +"tsql": "bf5a83d0c02f8890941c7ec8" +} +], +[ +"type", +{ +"DuckDB": "4c16382f7ad617ac3cbfa833", +"None": "0f63c150afc0bb5bbf7763ba", +"bigquery": "a4d165ed06d0b1b815192ef4", +"databricks": "0f63c150afc0bb5bbf7763ba", +"duckdb": "4c16382f7ad617ac3cbfa833", +"generic": "0f63c150afc0bb5bbf7763ba", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "6c03a3450ea4742ee7396e3c", +"postgres": "4c16382f7ad617ac3cbfa833", +"postgresql": "4c16382f7ad617ac3cbfa833", +"snowflake": "303d6e0feaedc557ea64e414", +"tsql": "accf46359aa8c74483b9a197" +} +], +[ +"type", +{ +"DuckDB": "d9315b336b73c3d8d4b6e9a3", +"None": "f2ed52f6bf46b4db9343551c", +"bigquery": "f2ed52f6bf46b4db9343551c", +"databricks": "f2ed52f6bf46b4db9343551c", +"duckdb": "d9315b336b73c3d8d4b6e9a3", +"generic": "f2ed52f6bf46b4db9343551c", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "f2ed52f6bf46b4db9343551c", +"postgres": "f2ed52f6bf46b4db9343551c", +"postgresql": "f2ed52f6bf46b4db9343551c", +"snowflake": "f2ed52f6bf46b4db9343551c", +"tsql": "f2ed52f6bf46b4db9343551c" +} +], +[ +"type", +{ +"DuckDB": "c84c0b1d4d7caa6744130456", +"None": "c84c0b1d4d7caa6744130456", +"bigquery": "c84c0b1d4d7caa6744130456", +"databricks": "c84c0b1d4d7caa6744130456", +"duckdb": "c84c0b1d4d7caa6744130456", +"generic": "c84c0b1d4d7caa6744130456", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "c84c0b1d4d7caa6744130456", +"postgres": "c84c0b1d4d7caa6744130456", +"postgresql": "c84c0b1d4d7caa6744130456", +"snowflake": "c84c0b1d4d7caa6744130456", +"tsql": "c84c0b1d4d7caa6744130456" +} +], +[ +"type", +{ +"DuckDB": "aea8a680fa18770e56bf6220", +"None": "aea8a680fa18770e56bf6220", +"bigquery": "aea8a680fa18770e56bf6220", +"databricks": "aea8a680fa18770e56bf6220", +"duckdb": "aea8a680fa18770e56bf6220", +"generic": "aea8a680fa18770e56bf6220", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "aea8a680fa18770e56bf6220", +"postgres": "aea8a680fa18770e56bf6220", +"postgresql": "aea8a680fa18770e56bf6220", +"snowflake": "aea8a680fa18770e56bf6220", +"tsql": "aea8a680fa18770e56bf6220" +} +], +[ +"type", +{ +"DuckDB": "19a1a80ffc06169f32694de8", +"None": "19a1a80ffc06169f32694de8", +"bigquery": "19a1a80ffc06169f32694de8", +"databricks": "19a1a80ffc06169f32694de8", +"duckdb": "19a1a80ffc06169f32694de8", +"generic": "19a1a80ffc06169f32694de8", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "19a1a80ffc06169f32694de8", +"postgres": "19a1a80ffc06169f32694de8", +"postgresql": "19a1a80ffc06169f32694de8", +"snowflake": "19a1a80ffc06169f32694de8", +"tsql": "19a1a80ffc06169f32694de8" +} +], +[ +"type", +{ +"DuckDB": "a428302e4848ffe877284c84", +"None": "a428302e4848ffe877284c84", +"bigquery": "a428302e4848ffe877284c84", +"databricks": "a428302e4848ffe877284c84", +"duckdb": "a428302e4848ffe877284c84", +"generic": "a428302e4848ffe877284c84", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "a428302e4848ffe877284c84", +"postgres": "a428302e4848ffe877284c84", +"postgresql": "a428302e4848ffe877284c84", +"snowflake": "652ff8b21f638eac8fdc46c5", +"tsql": "a428302e4848ffe877284c84" +} +], +[ +"type", +{ +"DuckDB": "6226bc03436ecf8fccd39252", +"None": "5aa51d84ac5e6c7a9306f348", +"bigquery": "5aa51d84ac5e6c7a9306f348", +"databricks": "5aa51d84ac5e6c7a9306f348", +"duckdb": "6226bc03436ecf8fccd39252", +"generic": "5aa51d84ac5e6c7a9306f348", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "5aa51d84ac5e6c7a9306f348", +"postgres": "5aa51d84ac5e6c7a9306f348", +"postgresql": "5aa51d84ac5e6c7a9306f348", +"snowflake": "5aa51d84ac5e6c7a9306f348", +"tsql": "5aa51d84ac5e6c7a9306f348" +} +], +[ +"type", +{ +"DuckDB": "70fb4728c3adcf6dbe4975d5", +"None": "70fb4728c3adcf6dbe4975d5", +"bigquery": "70fb4728c3adcf6dbe4975d5", +"databricks": "70fb4728c3adcf6dbe4975d5", +"duckdb": "70fb4728c3adcf6dbe4975d5", +"generic": "70fb4728c3adcf6dbe4975d5", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "70fb4728c3adcf6dbe4975d5", +"postgres": "70fb4728c3adcf6dbe4975d5", +"postgresql": "70fb4728c3adcf6dbe4975d5", +"snowflake": "70fb4728c3adcf6dbe4975d5", +"tsql": "70fb4728c3adcf6dbe4975d5" +} +], +[ +"type", +{ +"DuckDB": "c7b697bbfa82dd2821ad64e9", +"None": "c7b697bbfa82dd2821ad64e9", +"bigquery": "dcb00b7053ffe69fe3ce99cd", +"databricks": "dcb00b7053ffe69fe3ce99cd", +"duckdb": "c7b697bbfa82dd2821ad64e9", +"generic": "c7b697bbfa82dd2821ad64e9", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "dcb00b7053ffe69fe3ce99cd", +"postgres": "c7b697bbfa82dd2821ad64e9", +"postgresql": "c7b697bbfa82dd2821ad64e9", +"snowflake": "c7b697bbfa82dd2821ad64e9", +"tsql": "c7b697bbfa82dd2821ad64e9" +} +], +[ +"type", +{ +"DuckDB": "c0b12bfc586282ce5ea85c45", +"None": "c0b12bfc586282ce5ea85c45", +"bigquery": "c0b12bfc586282ce5ea85c45", +"databricks": "c0b12bfc586282ce5ea85c45", +"duckdb": "c0b12bfc586282ce5ea85c45", +"generic": "c0b12bfc586282ce5ea85c45", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "c0b12bfc586282ce5ea85c45", +"postgres": "c0b12bfc586282ce5ea85c45", +"postgresql": "c0b12bfc586282ce5ea85c45", +"snowflake": "c0b12bfc586282ce5ea85c45", +"tsql": "c0b12bfc586282ce5ea85c45" +} +], +[ +"type", +{ +"DuckDB": "806bf4b6d83b5dc9948e2054", +"None": "806bf4b6d83b5dc9948e2054", +"bigquery": "806bf4b6d83b5dc9948e2054", +"databricks": "806bf4b6d83b5dc9948e2054", +"duckdb": "806bf4b6d83b5dc9948e2054", +"generic": "806bf4b6d83b5dc9948e2054", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "806bf4b6d83b5dc9948e2054", +"postgres": "806bf4b6d83b5dc9948e2054", +"postgresql": "806bf4b6d83b5dc9948e2054", +"snowflake": "806bf4b6d83b5dc9948e2054", +"tsql": "806bf4b6d83b5dc9948e2054" +} +], +[ +"type", +{ +"DuckDB": "871969531da28b86361e65d2", +"None": "871969531da28b86361e65d2", +"bigquery": "871969531da28b86361e65d2", +"databricks": "871969531da28b86361e65d2", +"duckdb": "871969531da28b86361e65d2", +"generic": "871969531da28b86361e65d2", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "871969531da28b86361e65d2", +"postgres": "871969531da28b86361e65d2", +"postgresql": "871969531da28b86361e65d2", +"snowflake": "871969531da28b86361e65d2", +"tsql": "871969531da28b86361e65d2" +} +], +[ +"type", +{ +"DuckDB": "4129901e0f313b38452e22af", +"None": "4129901e0f313b38452e22af", +"bigquery": "4129901e0f313b38452e22af", +"databricks": "4129901e0f313b38452e22af", +"duckdb": "4129901e0f313b38452e22af", +"generic": "4129901e0f313b38452e22af", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "4129901e0f313b38452e22af", +"postgres": "4129901e0f313b38452e22af", +"postgresql": "4129901e0f313b38452e22af", +"snowflake": "4129901e0f313b38452e22af", +"tsql": "4129901e0f313b38452e22af" +} +], +[ +"type", +{ +"DuckDB": "0c290c40483b9651ff557830", +"None": "0c290c40483b9651ff557830", +"bigquery": "0c290c40483b9651ff557830", +"databricks": "0c290c40483b9651ff557830", +"duckdb": "0c290c40483b9651ff557830", +"generic": "0c290c40483b9651ff557830", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "0c290c40483b9651ff557830", +"postgres": "0c290c40483b9651ff557830", +"postgresql": "0c290c40483b9651ff557830", +"snowflake": "0c290c40483b9651ff557830", +"tsql": "0c290c40483b9651ff557830" +} +], +[ +"type", +{ +"DuckDB": "b0505024b3f15f191c70a470", +"None": "b1603277660bbe23982ff72a", +"bigquery": "b1603277660bbe23982ff72a", +"databricks": "b1603277660bbe23982ff72a", +"duckdb": "b0505024b3f15f191c70a470", +"generic": "b1603277660bbe23982ff72a", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "6c03a3450ea4742ee7396e3c", +"postgres": "fa1a8787c8f69b9f9be89526", +"postgresql": "fa1a8787c8f69b9f9be89526", +"snowflake": "50404426183626ce7b686f80", +"tsql": "23410065fbf92eb4099b13de" +} +], +[ +"type", +{ +"DuckDB": "b63494be71c6c8936f6824a6", +"None": "b63494be71c6c8936f6824a6", +"bigquery": "b63494be71c6c8936f6824a6", +"databricks": "b63494be71c6c8936f6824a6", +"duckdb": "b63494be71c6c8936f6824a6", +"generic": "b63494be71c6c8936f6824a6", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "b63494be71c6c8936f6824a6", +"postgres": "b63494be71c6c8936f6824a6", +"postgresql": "b63494be71c6c8936f6824a6", +"snowflake": "b63494be71c6c8936f6824a6", +"tsql": "b63494be71c6c8936f6824a6" +} +], +[ +"type", +{ +"DuckDB": "016c25f8f0c58947f8da9152", +"None": "016c25f8f0c58947f8da9152", +"bigquery": "016c25f8f0c58947f8da9152", +"databricks": "016c25f8f0c58947f8da9152", +"duckdb": "016c25f8f0c58947f8da9152", +"generic": "016c25f8f0c58947f8da9152", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "016c25f8f0c58947f8da9152", +"postgres": "016c25f8f0c58947f8da9152", +"postgresql": "016c25f8f0c58947f8da9152", +"snowflake": "016c25f8f0c58947f8da9152", +"tsql": "016c25f8f0c58947f8da9152" +} +], +[ +"type", +{ +"DuckDB": "e02779be57c0fcfa69ee7746", +"None": "e02779be57c0fcfa69ee7746", +"bigquery": "e02779be57c0fcfa69ee7746", +"databricks": "e02779be57c0fcfa69ee7746", +"duckdb": "e02779be57c0fcfa69ee7746", +"generic": "e02779be57c0fcfa69ee7746", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "e02779be57c0fcfa69ee7746", +"postgres": "e02779be57c0fcfa69ee7746", +"postgresql": "e02779be57c0fcfa69ee7746", +"snowflake": "e02779be57c0fcfa69ee7746", +"tsql": "e02779be57c0fcfa69ee7746" +} +], +[ +"type", +{ +"DuckDB": "ace891b6844cb59efad42031", +"None": "1eb7fb4e8cf75773c5573562", +"bigquery": "c9b810639795a7bfab91b98d", +"databricks": "1eb7fb4e8cf75773c5573562", +"duckdb": "ace891b6844cb59efad42031", +"generic": "1eb7fb4e8cf75773c5573562", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "1eb7fb4e8cf75773c5573562", +"postgres": "1eb7fb4e8cf75773c5573562", +"postgresql": "1eb7fb4e8cf75773c5573562", +"snowflake": "97a20344d811fb77c7690863", +"tsql": "1eb7fb4e8cf75773c5573562" +} +], +[ +"type", +{ +"DuckDB": "b7507b03866507106687a313", +"None": "b7507b03866507106687a313", +"bigquery": "b7507b03866507106687a313", +"databricks": "b7507b03866507106687a313", +"duckdb": "b7507b03866507106687a313", +"generic": "b7507b03866507106687a313", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "b7507b03866507106687a313", +"postgres": "b7507b03866507106687a313", +"postgresql": "b7507b03866507106687a313", +"snowflake": "b7507b03866507106687a313", +"tsql": "b7507b03866507106687a313" +} +], +[ +"type", +{ +"DuckDB": "fdc9a2fc03f4b67d24982d0a", +"None": "fdc9a2fc03f4b67d24982d0a", +"bigquery": "fdc9a2fc03f4b67d24982d0a", +"databricks": "fdc9a2fc03f4b67d24982d0a", +"duckdb": "fdc9a2fc03f4b67d24982d0a", +"generic": "fdc9a2fc03f4b67d24982d0a", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "fdc9a2fc03f4b67d24982d0a", +"postgres": "fdc9a2fc03f4b67d24982d0a", +"postgresql": "fdc9a2fc03f4b67d24982d0a", +"snowflake": "fdc9a2fc03f4b67d24982d0a", +"tsql": "fdc9a2fc03f4b67d24982d0a" +} +], +[ +"type", +{ +"DuckDB": "5c8b98f516cedefc237fa721", +"None": "5c8b98f516cedefc237fa721", +"bigquery": "5c8b98f516cedefc237fa721", +"databricks": "5c8b98f516cedefc237fa721", +"duckdb": "5c8b98f516cedefc237fa721", +"generic": "5c8b98f516cedefc237fa721", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "5c8b98f516cedefc237fa721", +"postgres": "5c8b98f516cedefc237fa721", +"postgresql": "5c8b98f516cedefc237fa721", +"snowflake": "5c8b98f516cedefc237fa721", +"tsql": "5c8b98f516cedefc237fa721" +} +], +[ +"type", +{ +"DuckDB": "27d7e27586eab431e308413f", +"None": "8d26a44bbe0d29bdb1509369", +"bigquery": "8d26a44bbe0d29bdb1509369", +"databricks": "8d26a44bbe0d29bdb1509369", +"duckdb": "27d7e27586eab431e308413f", +"generic": "8d26a44bbe0d29bdb1509369", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "8d26a44bbe0d29bdb1509369", +"postgres": "8d26a44bbe0d29bdb1509369", +"postgresql": "8d26a44bbe0d29bdb1509369", +"snowflake": "8d26a44bbe0d29bdb1509369", +"tsql": "8d26a44bbe0d29bdb1509369" +} +], +[ +"type", +{ +"DuckDB": "3f71ab5f3c1c040da96f2cec", +"None": "3f71ab5f3c1c040da96f2cec", +"bigquery": "3f71ab5f3c1c040da96f2cec", +"databricks": "3f71ab5f3c1c040da96f2cec", +"duckdb": "3f71ab5f3c1c040da96f2cec", +"generic": "3f71ab5f3c1c040da96f2cec", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "3f71ab5f3c1c040da96f2cec", +"postgres": "3f71ab5f3c1c040da96f2cec", +"postgresql": "3f71ab5f3c1c040da96f2cec", +"snowflake": "3f71ab5f3c1c040da96f2cec", +"tsql": "3f71ab5f3c1c040da96f2cec" +} +], +[ +"type", +{ +"DuckDB": "ab5ad6180652b3b00d1f5b01", +"None": "ab5ad6180652b3b00d1f5b01", +"bigquery": "946d5ee30ab7469c57d850df", +"databricks": "ab5ad6180652b3b00d1f5b01", +"duckdb": "ab5ad6180652b3b00d1f5b01", +"generic": "ab5ad6180652b3b00d1f5b01", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "ab5ad6180652b3b00d1f5b01", +"postgres": "ab5ad6180652b3b00d1f5b01", +"postgresql": "ab5ad6180652b3b00d1f5b01", +"snowflake": "f43dac38f34a1c0618a3f812", +"tsql": "ab5ad6180652b3b00d1f5b01" +} +], +[ +"type", +{ +"DuckDB": "4662a1758442ce44b830269f", +"None": "4662a1758442ce44b830269f", +"bigquery": "4662a1758442ce44b830269f", +"databricks": "4662a1758442ce44b830269f", +"duckdb": "4662a1758442ce44b830269f", +"generic": "4662a1758442ce44b830269f", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "4662a1758442ce44b830269f", +"postgres": "4662a1758442ce44b830269f", +"postgresql": "4662a1758442ce44b830269f", +"snowflake": "4662a1758442ce44b830269f", +"tsql": "4662a1758442ce44b830269f" +} +], +[ +"type", +{ +"DuckDB": "34af912a178427fc6e8bdee3", +"None": "34af912a178427fc6e8bdee3", +"bigquery": "34af912a178427fc6e8bdee3", +"databricks": "34af912a178427fc6e8bdee3", +"duckdb": "34af912a178427fc6e8bdee3", +"generic": "34af912a178427fc6e8bdee3", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "34af912a178427fc6e8bdee3", +"postgres": "34af912a178427fc6e8bdee3", +"postgresql": "34af912a178427fc6e8bdee3", +"snowflake": "34af912a178427fc6e8bdee3", +"tsql": "34af912a178427fc6e8bdee3" +} +], +[ +"type", +{ +"DuckDB": "27d7e27586eab431e308413f", +"None": "29e896ae6f2844ec3744aad6", +"bigquery": "29e896ae6f2844ec3744aad6", +"databricks": "29e896ae6f2844ec3744aad6", +"duckdb": "27d7e27586eab431e308413f", +"generic": "29e896ae6f2844ec3744aad6", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "29e896ae6f2844ec3744aad6", +"postgres": "29e896ae6f2844ec3744aad6", +"postgresql": "29e896ae6f2844ec3744aad6", +"snowflake": "29e896ae6f2844ec3744aad6", +"tsql": "29e896ae6f2844ec3744aad6" +} +], +[ +"type", +{ +"DuckDB": "e8605878c6fffc044556a858", +"None": "e8605878c6fffc044556a858", +"bigquery": "e8605878c6fffc044556a858", +"databricks": "e8605878c6fffc044556a858", +"duckdb": "e8605878c6fffc044556a858", +"generic": "e8605878c6fffc044556a858", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "e8605878c6fffc044556a858", +"postgres": "e8605878c6fffc044556a858", +"postgresql": "e8605878c6fffc044556a858", +"snowflake": "e8605878c6fffc044556a858", +"tsql": "e8605878c6fffc044556a858" +} +], +[ +"type", +{ +"DuckDB": "787213ce6b6e210ded1d752c", +"None": "787213ce6b6e210ded1d752c", +"bigquery": "b1b23029bedaa16e2a6f8516", +"databricks": "787213ce6b6e210ded1d752c", +"duckdb": "787213ce6b6e210ded1d752c", +"generic": "787213ce6b6e210ded1d752c", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "787213ce6b6e210ded1d752c", +"postgres": "787213ce6b6e210ded1d752c", +"postgresql": "787213ce6b6e210ded1d752c", +"snowflake": "b561884132dbe7e42b719110", +"tsql": "787213ce6b6e210ded1d752c" +} +], +[ +"type", +{ +"DuckDB": "c6106f30f23f392e17eadef4", +"None": "c6106f30f23f392e17eadef4", +"bigquery": "c6106f30f23f392e17eadef4", +"databricks": "c6106f30f23f392e17eadef4", +"duckdb": "c6106f30f23f392e17eadef4", +"generic": "c6106f30f23f392e17eadef4", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "c6106f30f23f392e17eadef4", +"postgres": "c6106f30f23f392e17eadef4", +"postgresql": "c6106f30f23f392e17eadef4", +"snowflake": "c6106f30f23f392e17eadef4", +"tsql": "c6106f30f23f392e17eadef4" +} +], +[ +"type", +{ +"DuckDB": "e7aec8198ab628519324444a", +"None": "e7aec8198ab628519324444a", +"bigquery": "e7aec8198ab628519324444a", +"databricks": "e7aec8198ab628519324444a", +"duckdb": "e7aec8198ab628519324444a", +"generic": "e7aec8198ab628519324444a", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "e7aec8198ab628519324444a", +"postgres": "e7aec8198ab628519324444a", +"postgresql": "e7aec8198ab628519324444a", +"snowflake": "e7aec8198ab628519324444a", +"tsql": "e7aec8198ab628519324444a" +} +], +[ +"type", +{ +"DuckDB": "881106a4a0d2de0ff7c56373", +"None": "881106a4a0d2de0ff7c56373", +"bigquery": "881106a4a0d2de0ff7c56373", +"databricks": "881106a4a0d2de0ff7c56373", +"duckdb": "881106a4a0d2de0ff7c56373", +"generic": "881106a4a0d2de0ff7c56373", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "881106a4a0d2de0ff7c56373", +"postgres": "881106a4a0d2de0ff7c56373", +"postgresql": "881106a4a0d2de0ff7c56373", +"snowflake": "881106a4a0d2de0ff7c56373", +"tsql": "881106a4a0d2de0ff7c56373" +} +], +[ +"type", +{ +"DuckDB": "2c6b371b030464f525066893", +"None": "2c6b371b030464f525066893", +"bigquery": "2c6b371b030464f525066893", +"databricks": "2c6b371b030464f525066893", +"duckdb": "2c6b371b030464f525066893", +"generic": "2c6b371b030464f525066893", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "2c6b371b030464f525066893", +"postgres": "2c6b371b030464f525066893", +"postgresql": "2c6b371b030464f525066893", +"snowflake": "2c6b371b030464f525066893", +"tsql": "2c6b371b030464f525066893" +} +], +[ +"type", +{ +"DuckDB": "e3d9a113277b9c69432b32d1", +"None": "e3d9a113277b9c69432b32d1", +"bigquery": "e3d9a113277b9c69432b32d1", +"databricks": "4cda99191af9adfbe91e70f6", +"duckdb": "e3d9a113277b9c69432b32d1", +"generic": "e3d9a113277b9c69432b32d1", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "4cda99191af9adfbe91e70f6", +"postgres": "e3d9a113277b9c69432b32d1", +"postgresql": "e3d9a113277b9c69432b32d1", +"snowflake": "e3d9a113277b9c69432b32d1", +"tsql": "e3d9a113277b9c69432b32d1" +} +], +[ +"type", +{ +"DuckDB": "ba0da7ef018b990fcc83cba1", +"None": "ba0da7ef018b990fcc83cba1", +"bigquery": "ba0da7ef018b990fcc83cba1", +"databricks": "ba0da7ef018b990fcc83cba1", +"duckdb": "ba0da7ef018b990fcc83cba1", +"generic": "ba0da7ef018b990fcc83cba1", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "ba0da7ef018b990fcc83cba1", +"postgres": "ba0da7ef018b990fcc83cba1", +"postgresql": "ba0da7ef018b990fcc83cba1", +"snowflake": "ba0da7ef018b990fcc83cba1", +"tsql": "ba0da7ef018b990fcc83cba1" +} +], +[ +"type", +{ +"DuckDB": "396b2ce32efb5365b393c230", +"None": "e57ac1541fb51b362cd5b470", +"bigquery": "e57ac1541fb51b362cd5b470", +"databricks": "e57ac1541fb51b362cd5b470", +"duckdb": "396b2ce32efb5365b393c230", +"generic": "e57ac1541fb51b362cd5b470", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "e57ac1541fb51b362cd5b470", +"postgres": "e57ac1541fb51b362cd5b470", +"postgresql": "e57ac1541fb51b362cd5b470", +"snowflake": "4b356542044f1267fcfc487a", +"tsql": "e57ac1541fb51b362cd5b470" +} +], +[ +"type", +{ +"DuckDB": "5abf4ec799a2ec32fb10da7e", +"None": "5abf4ec799a2ec32fb10da7e", +"bigquery": "5abf4ec799a2ec32fb10da7e", +"databricks": "5abf4ec799a2ec32fb10da7e", +"duckdb": "5abf4ec799a2ec32fb10da7e", +"generic": "5abf4ec799a2ec32fb10da7e", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "5abf4ec799a2ec32fb10da7e", +"postgres": "5abf4ec799a2ec32fb10da7e", +"postgresql": "5abf4ec799a2ec32fb10da7e", +"snowflake": "a5656d70e208254d1d3e9b4f", +"tsql": "5abf4ec799a2ec32fb10da7e" +} +], +[ +"type", +{ +"DuckDB": "e060b5a5a8e9774b580d58d3", +"None": "e060b5a5a8e9774b580d58d3", +"bigquery": "319a9fbb02ed503eb114164b", +"databricks": "319a9fbb02ed503eb114164b", +"duckdb": "e060b5a5a8e9774b580d58d3", +"generic": "e060b5a5a8e9774b580d58d3", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "319a9fbb02ed503eb114164b", +"postgres": "e060b5a5a8e9774b580d58d3", +"postgresql": "e060b5a5a8e9774b580d58d3", +"snowflake": "e060b5a5a8e9774b580d58d3", +"tsql": "e060b5a5a8e9774b580d58d3" +} +], +[ +"type", +{ +"DuckDB": "67d251c042daee0bb2bf7351", +"None": "67d251c042daee0bb2bf7351", +"bigquery": "67d251c042daee0bb2bf7351", +"databricks": "67d251c042daee0bb2bf7351", +"duckdb": "67d251c042daee0bb2bf7351", +"generic": "67d251c042daee0bb2bf7351", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "67d251c042daee0bb2bf7351", +"postgres": "67d251c042daee0bb2bf7351", +"postgresql": "67d251c042daee0bb2bf7351", +"snowflake": "67d251c042daee0bb2bf7351", +"tsql": "67d251c042daee0bb2bf7351" +} +], +[ +"type", +{ +"DuckDB": "919b7ec6a7b49d8527b784cd", +"None": "919b7ec6a7b49d8527b784cd", +"bigquery": "204206d1d1eecf007966cc5b", +"databricks": "e3bc1b8bad22d8104417b00f", +"duckdb": "919b7ec6a7b49d8527b784cd", +"generic": "919b7ec6a7b49d8527b784cd", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "919b7ec6a7b49d8527b784cd", +"postgres": "a3b6b25265be330ec52a3322", +"postgresql": "a3b6b25265be330ec52a3322", +"snowflake": "919b7ec6a7b49d8527b784cd", +"tsql": "919b7ec6a7b49d8527b784cd" +} +], +[ +"type", +{ +"DuckDB": "66ee8490513ef7b131cb4824", +"None": "66ee8490513ef7b131cb4824", +"bigquery": "66ee8490513ef7b131cb4824", +"databricks": "66ee8490513ef7b131cb4824", +"duckdb": "66ee8490513ef7b131cb4824", +"generic": "66ee8490513ef7b131cb4824", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "66ee8490513ef7b131cb4824", +"postgres": "66ee8490513ef7b131cb4824", +"postgresql": "66ee8490513ef7b131cb4824", +"snowflake": "66ee8490513ef7b131cb4824", +"tsql": "66ee8490513ef7b131cb4824" +} +], +[ +"type", +{ +"DuckDB": "8f552eefca3955a73672f686", +"None": "8f552eefca3955a73672f686", +"bigquery": "8f552eefca3955a73672f686", +"databricks": "8f552eefca3955a73672f686", +"duckdb": "8f552eefca3955a73672f686", +"generic": "8f552eefca3955a73672f686", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "8f552eefca3955a73672f686", +"postgres": "8f552eefca3955a73672f686", +"postgresql": "8f552eefca3955a73672f686", +"snowflake": "8f552eefca3955a73672f686", +"tsql": "8f552eefca3955a73672f686" +} +], +[ +"type", +{ +"DuckDB": "e2879cf4770e7f48d2dd704a", +"None": "e2879cf4770e7f48d2dd704a", +"bigquery": "c9b810639795a7bfab91b98d", +"databricks": "e2879cf4770e7f48d2dd704a", +"duckdb": "e2879cf4770e7f48d2dd704a", +"generic": "e2879cf4770e7f48d2dd704a", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "e2879cf4770e7f48d2dd704a", +"postgres": "e2879cf4770e7f48d2dd704a", +"postgresql": "e2879cf4770e7f48d2dd704a", +"snowflake": "97a20344d811fb77c7690863", +"tsql": "e2879cf4770e7f48d2dd704a" +} +], +[ +"type", +{ +"DuckDB": "5abf4ec799a2ec32fb10da7e", +"None": "5abf4ec799a2ec32fb10da7e", +"bigquery": "5abf4ec799a2ec32fb10da7e", +"databricks": "5abf4ec799a2ec32fb10da7e", +"duckdb": "5abf4ec799a2ec32fb10da7e", +"generic": "5abf4ec799a2ec32fb10da7e", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "5abf4ec799a2ec32fb10da7e", +"postgres": "5abf4ec799a2ec32fb10da7e", +"postgresql": "5abf4ec799a2ec32fb10da7e", +"snowflake": "a5656d70e208254d1d3e9b4f", +"tsql": "5abf4ec799a2ec32fb10da7e" +} +], +[ +"type", +{ +"DuckDB": "19a1a80ffc06169f32694de8", +"None": "19a1a80ffc06169f32694de8", +"bigquery": "19a1a80ffc06169f32694de8", +"databricks": "19a1a80ffc06169f32694de8", +"duckdb": "19a1a80ffc06169f32694de8", +"generic": "19a1a80ffc06169f32694de8", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "19a1a80ffc06169f32694de8", +"postgres": "19a1a80ffc06169f32694de8", +"postgresql": "19a1a80ffc06169f32694de8", +"snowflake": "19a1a80ffc06169f32694de8", +"tsql": "19a1a80ffc06169f32694de8" +} +], +[ +"type", +{ +"DuckDB": "f4c37736a388a1d793d4de1a", +"None": "853d4786e4edb4f90284765b", +"bigquery": "853d4786e4edb4f90284765b", +"databricks": "853d4786e4edb4f90284765b", +"duckdb": "f4c37736a388a1d793d4de1a", +"generic": "853d4786e4edb4f90284765b", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "6c03a3450ea4742ee7396e3c", +"postgres": "f4c37736a388a1d793d4de1a", +"postgresql": "f4c37736a388a1d793d4de1a", +"snowflake": "a640dde3e800eb6ea27813e3", +"tsql": "640c6d24f5ef62763025ea43" +} +], +[ +"type", +{ +"DuckDB": "e57ac1541fb51b362cd5b470", +"None": "e57ac1541fb51b362cd5b470", +"bigquery": "e57ac1541fb51b362cd5b470", +"databricks": "e57ac1541fb51b362cd5b470", +"duckdb": "e57ac1541fb51b362cd5b470", +"generic": "e57ac1541fb51b362cd5b470", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "e57ac1541fb51b362cd5b470", +"postgres": "e57ac1541fb51b362cd5b470", +"postgresql": "e57ac1541fb51b362cd5b470", +"snowflake": "4b356542044f1267fcfc487a", +"tsql": "e57ac1541fb51b362cd5b470" +} +], +[ +"type", +{ +"DuckDB": "70fb4728c3adcf6dbe4975d5", +"None": "70fb4728c3adcf6dbe4975d5", +"bigquery": "70fb4728c3adcf6dbe4975d5", +"databricks": "70fb4728c3adcf6dbe4975d5", +"duckdb": "70fb4728c3adcf6dbe4975d5", +"generic": "70fb4728c3adcf6dbe4975d5", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "70fb4728c3adcf6dbe4975d5", +"postgres": "70fb4728c3adcf6dbe4975d5", +"postgresql": "70fb4728c3adcf6dbe4975d5", +"snowflake": "70fb4728c3adcf6dbe4975d5", +"tsql": "70fb4728c3adcf6dbe4975d5" +} +], +[ +"type", +{ +"DuckDB": "aab0389e2b5470136660bf8a", +"None": "aab0389e2b5470136660bf8a", +"bigquery": "c9b810639795a7bfab91b98d", +"databricks": "aab0389e2b5470136660bf8a", +"duckdb": "aab0389e2b5470136660bf8a", +"generic": "aab0389e2b5470136660bf8a", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "aab0389e2b5470136660bf8a", +"postgres": "aab0389e2b5470136660bf8a", +"postgresql": "aab0389e2b5470136660bf8a", +"snowflake": "97a20344d811fb77c7690863", +"tsql": "aab0389e2b5470136660bf8a" +} +], +[ +"type", +{ +"DuckDB": "19a1a80ffc06169f32694de8", +"None": "19a1a80ffc06169f32694de8", +"bigquery": "19a1a80ffc06169f32694de8", +"databricks": "19a1a80ffc06169f32694de8", +"duckdb": "19a1a80ffc06169f32694de8", +"generic": "19a1a80ffc06169f32694de8", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "19a1a80ffc06169f32694de8", +"postgres": "19a1a80ffc06169f32694de8", +"postgresql": "19a1a80ffc06169f32694de8", +"snowflake": "19a1a80ffc06169f32694de8", +"tsql": "19a1a80ffc06169f32694de8" +} +], +[ +"type", +{ +"DuckDB": "776e4bf23c8ef10ffaceade2", +"None": "776e4bf23c8ef10ffaceade2", +"bigquery": "776e4bf23c8ef10ffaceade2", +"databricks": "776e4bf23c8ef10ffaceade2", +"duckdb": "776e4bf23c8ef10ffaceade2", +"generic": "776e4bf23c8ef10ffaceade2", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "776e4bf23c8ef10ffaceade2", +"postgres": "776e4bf23c8ef10ffaceade2", +"postgresql": "776e4bf23c8ef10ffaceade2", +"snowflake": "776e4bf23c8ef10ffaceade2", +"tsql": "776e4bf23c8ef10ffaceade2" +} +], +[ +"type", +{ +"DuckDB": "c50a316d091c821866e4bfba", +"None": "c50a316d091c821866e4bfba", +"bigquery": "c50a316d091c821866e4bfba", +"databricks": "c50a316d091c821866e4bfba", +"duckdb": "c50a316d091c821866e4bfba", +"generic": "c50a316d091c821866e4bfba", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "c50a316d091c821866e4bfba", +"postgres": "c50a316d091c821866e4bfba", +"postgresql": "c50a316d091c821866e4bfba", +"snowflake": "c50a316d091c821866e4bfba", +"tsql": "c50a316d091c821866e4bfba" +} +], +[ +"type", +{ +"DuckDB": "42d4a23d9a52e79d0c3458d3", +"None": "a3acd7ba35e81a800f967bd3", +"bigquery": "3c0719ca5c83e0a20d0b0b42", +"databricks": "a3acd7ba35e81a800f967bd3", +"duckdb": "42d4a23d9a52e79d0c3458d3", +"generic": "a3acd7ba35e81a800f967bd3", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "a3acd7ba35e81a800f967bd3", +"postgres": "a3acd7ba35e81a800f967bd3", +"postgresql": "a3acd7ba35e81a800f967bd3", +"snowflake": "a3acd7ba35e81a800f967bd3", +"tsql": "a3acd7ba35e81a800f967bd3" +} +], +[ +"type", +{ +"DuckDB": "95050a5e73c2bff179a785b7", +"None": "95050a5e73c2bff179a785b7", +"bigquery": "95050a5e73c2bff179a785b7", +"databricks": "95050a5e73c2bff179a785b7", +"duckdb": "95050a5e73c2bff179a785b7", +"generic": "95050a5e73c2bff179a785b7", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "95050a5e73c2bff179a785b7", +"postgres": "95050a5e73c2bff179a785b7", +"postgresql": "95050a5e73c2bff179a785b7", +"snowflake": "95050a5e73c2bff179a785b7", +"tsql": "95050a5e73c2bff179a785b7" +} +], +[ +"type", +{ +"DuckDB": "0703bf71a54942bdaa28406e", +"None": "0703bf71a54942bdaa28406e", +"bigquery": "a428302e4848ffe877284c84", +"databricks": "0703bf71a54942bdaa28406e", +"duckdb": "0703bf71a54942bdaa28406e", +"generic": "0703bf71a54942bdaa28406e", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "0703bf71a54942bdaa28406e", +"postgres": "0703bf71a54942bdaa28406e", +"postgresql": "0703bf71a54942bdaa28406e", +"snowflake": "652ff8b21f638eac8fdc46c5", +"tsql": "441f377c46ddc162ec0a5976" +} +], +[ +"type", +{ +"DuckDB": "89cc3662f602a13aef39eb80", +"None": "f2bbf59a9c02f59ca89e66b6", +"bigquery": "f2bbf59a9c02f59ca89e66b6", +"databricks": "f2bbf59a9c02f59ca89e66b6", +"duckdb": "89cc3662f602a13aef39eb80", +"generic": "f2bbf59a9c02f59ca89e66b6", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "6c03a3450ea4742ee7396e3c", +"postgres": "89cc3662f602a13aef39eb80", +"postgresql": "89cc3662f602a13aef39eb80", +"snowflake": "6f88ef12d95c26bf8f0bd9e5", +"tsql": "ffadc5a4dbb5d511f5cde8d7" +} +], +[ +"type", +{ +"DuckDB": "aab0389e2b5470136660bf8a", +"None": "aab0389e2b5470136660bf8a", +"bigquery": "c9b810639795a7bfab91b98d", +"databricks": "aab0389e2b5470136660bf8a", +"duckdb": "aab0389e2b5470136660bf8a", +"generic": "aab0389e2b5470136660bf8a", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "aab0389e2b5470136660bf8a", +"postgres": "aab0389e2b5470136660bf8a", +"postgresql": "aab0389e2b5470136660bf8a", +"snowflake": "97a20344d811fb77c7690863", +"tsql": "aab0389e2b5470136660bf8a" +} +], +[ +"type", +{ +"DuckDB": "2bfa352725f9d8a91250f75e", +"None": "2bfa352725f9d8a91250f75e", +"bigquery": "2bfa352725f9d8a91250f75e", +"databricks": "2bfa352725f9d8a91250f75e", +"duckdb": "2bfa352725f9d8a91250f75e", +"generic": "2bfa352725f9d8a91250f75e", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "2bfa352725f9d8a91250f75e", +"postgres": "2bfa352725f9d8a91250f75e", +"postgresql": "2bfa352725f9d8a91250f75e", +"snowflake": "2bfa352725f9d8a91250f75e", +"tsql": "2bfa352725f9d8a91250f75e" +} +], +[ +"type", +{ +"DuckDB": "50a940812c6ed2e6dd842e74", +"None": "50a940812c6ed2e6dd842e74", +"bigquery": "50a940812c6ed2e6dd842e74", +"databricks": "50a940812c6ed2e6dd842e74", +"duckdb": "50a940812c6ed2e6dd842e74", +"generic": "50a940812c6ed2e6dd842e74", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "50a940812c6ed2e6dd842e74", +"postgres": "50a940812c6ed2e6dd842e74", +"postgresql": "50a940812c6ed2e6dd842e74", +"snowflake": "50a940812c6ed2e6dd842e74", +"tsql": "50a940812c6ed2e6dd842e74" +} +], +[ +"type", +{ +"DuckDB": "e57ac1541fb51b362cd5b470", +"None": "e57ac1541fb51b362cd5b470", +"bigquery": "e57ac1541fb51b362cd5b470", +"databricks": "e57ac1541fb51b362cd5b470", +"duckdb": "e57ac1541fb51b362cd5b470", +"generic": "e57ac1541fb51b362cd5b470", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "e57ac1541fb51b362cd5b470", +"postgres": "e57ac1541fb51b362cd5b470", +"postgresql": "e57ac1541fb51b362cd5b470", +"snowflake": "4b356542044f1267fcfc487a", +"tsql": "e57ac1541fb51b362cd5b470" +} +], +[ +"type", +{ +"DuckDB": "279ea7f6f6a3910de04b795b", +"None": "279ea7f6f6a3910de04b795b", +"bigquery": "279ea7f6f6a3910de04b795b", +"databricks": "279ea7f6f6a3910de04b795b", +"duckdb": "279ea7f6f6a3910de04b795b", +"generic": "279ea7f6f6a3910de04b795b", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "279ea7f6f6a3910de04b795b", +"postgres": "279ea7f6f6a3910de04b795b", +"postgresql": "279ea7f6f6a3910de04b795b", +"snowflake": "279ea7f6f6a3910de04b795b", +"tsql": "279ea7f6f6a3910de04b795b" +} +], +[ +"type", +{ +"DuckDB": "461923a0d34defd0c726d6e5", +"None": "461923a0d34defd0c726d6e5", +"bigquery": "b5c4d5044b2a6e70633f0d0a", +"databricks": "461923a0d34defd0c726d6e5", +"duckdb": "461923a0d34defd0c726d6e5", +"generic": "461923a0d34defd0c726d6e5", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "461923a0d34defd0c726d6e5", +"postgres": "461923a0d34defd0c726d6e5", +"postgresql": "461923a0d34defd0c726d6e5", +"snowflake": "461923a0d34defd0c726d6e5", +"tsql": "461923a0d34defd0c726d6e5" +} +], +[ +"type", +{ +"DuckDB": "84fca9ac893777959cfd715c", +"None": "84fca9ac893777959cfd715c", +"bigquery": "f28a96f0eb38ad8874f6ec5d", +"databricks": "84fca9ac893777959cfd715c", +"duckdb": "84fca9ac893777959cfd715c", +"generic": "84fca9ac893777959cfd715c", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "84fca9ac893777959cfd715c", +"postgres": "84fca9ac893777959cfd715c", +"postgresql": "84fca9ac893777959cfd715c", +"snowflake": "84fca9ac893777959cfd715c", +"tsql": "6349bc82604b762638e35788" +} +], +[ +"type", +{ +"DuckDB": "e57ac1541fb51b362cd5b470", +"None": "e57ac1541fb51b362cd5b470", +"bigquery": "e57ac1541fb51b362cd5b470", +"databricks": "e57ac1541fb51b362cd5b470", +"duckdb": "e57ac1541fb51b362cd5b470", +"generic": "e57ac1541fb51b362cd5b470", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "e57ac1541fb51b362cd5b470", +"postgres": "e57ac1541fb51b362cd5b470", +"postgresql": "e57ac1541fb51b362cd5b470", +"snowflake": "4b356542044f1267fcfc487a", +"tsql": "e57ac1541fb51b362cd5b470" +} +], +[ +"type", +{ +"DuckDB": "2cc8493833d5ac6046bfbfc2", +"None": "2cc8493833d5ac6046bfbfc2", +"bigquery": "c6c57a853058ab1ee17a75f6", +"databricks": "75a99436882f66b2fdc219e5", +"duckdb": "2cc8493833d5ac6046bfbfc2", +"generic": "2cc8493833d5ac6046bfbfc2", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "2cc8493833d5ac6046bfbfc2", +"postgres": "2cc8493833d5ac6046bfbfc2", +"postgresql": "2cc8493833d5ac6046bfbfc2", +"snowflake": "70fb65041d155a676d8443d4", +"tsql": "c17d7423230bbb223a42e69f" +} +], +[ +"type", +{ +"DuckDB": "8305d75697b54f509bbc0f53", +"None": "80723d96ed6ed21034faa9bd", +"bigquery": "f80980deec760e5b50e05376", +"databricks": "f80980deec760e5b50e05376", +"duckdb": "8305d75697b54f509bbc0f53", +"generic": "80723d96ed6ed21034faa9bd", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "f80980deec760e5b50e05376", +"postgres": "8305d75697b54f509bbc0f53", +"postgresql": "8305d75697b54f509bbc0f53", +"snowflake": "240e7de80b095b23fdb1fd92", +"tsql": "d1dc9a140dbe2eb1874c6ad7" +} +], +[ +"type", +{ +"DuckDB": "d41d40c68507f4d02e348833", +"None": "d41d40c68507f4d02e348833", +"bigquery": "e1c36a5cdd2427ff2b089ac9", +"databricks": "d41d40c68507f4d02e348833", +"duckdb": "d41d40c68507f4d02e348833", +"generic": "d41d40c68507f4d02e348833", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "d41d40c68507f4d02e348833", +"postgres": "d41d40c68507f4d02e348833", +"postgresql": "d41d40c68507f4d02e348833", +"snowflake": "d41d40c68507f4d02e348833", +"tsql": "d41d40c68507f4d02e348833" +} +], +[ +"type", +{ +"DuckDB": "2c44dc35fd1ef8701101802e", +"None": "2c44dc35fd1ef8701101802e", +"bigquery": "a428302e4848ffe877284c84", +"databricks": "2c44dc35fd1ef8701101802e", +"duckdb": "2c44dc35fd1ef8701101802e", +"generic": "2c44dc35fd1ef8701101802e", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "2c44dc35fd1ef8701101802e", +"postgres": "2c44dc35fd1ef8701101802e", +"postgresql": "2c44dc35fd1ef8701101802e", +"snowflake": "652ff8b21f638eac8fdc46c5", +"tsql": "2c44dc35fd1ef8701101802e" +} +], +[ +"type", +{ +"DuckDB": "599b3293ed620803ce2401b5", +"None": "599b3293ed620803ce2401b5", +"bigquery": "599b3293ed620803ce2401b5", +"databricks": "599b3293ed620803ce2401b5", +"duckdb": "599b3293ed620803ce2401b5", +"generic": "599b3293ed620803ce2401b5", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "599b3293ed620803ce2401b5", +"postgres": "599b3293ed620803ce2401b5", +"postgresql": "599b3293ed620803ce2401b5", +"snowflake": "599b3293ed620803ce2401b5", +"tsql": "599b3293ed620803ce2401b5" +} +], +[ +"type", +{ +"DuckDB": "669084d1ea704ae5b8ee05c2", +"None": "669084d1ea704ae5b8ee05c2", +"bigquery": "669084d1ea704ae5b8ee05c2", +"databricks": "669084d1ea704ae5b8ee05c2", +"duckdb": "669084d1ea704ae5b8ee05c2", +"generic": "669084d1ea704ae5b8ee05c2", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "669084d1ea704ae5b8ee05c2", +"postgres": "669084d1ea704ae5b8ee05c2", +"postgresql": "669084d1ea704ae5b8ee05c2", +"snowflake": "669084d1ea704ae5b8ee05c2", +"tsql": "669084d1ea704ae5b8ee05c2" +} +], +[ +"type", +{ +"DuckDB": "9e4a50a8aab648a9737f7d0c", +"None": "9e4a50a8aab648a9737f7d0c", +"bigquery": "d9a4e245156e760303573500", +"databricks": "9e4a50a8aab648a9737f7d0c", +"duckdb": "9e4a50a8aab648a9737f7d0c", +"generic": "9e4a50a8aab648a9737f7d0c", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "9e4a50a8aab648a9737f7d0c", +"postgres": "36d29258901a4d8c296baa68", +"postgresql": "36d29258901a4d8c296baa68", +"snowflake": "9e4a50a8aab648a9737f7d0c", +"tsql": "355e032cc5c0f24695836b3d" +} +], +[ +"type", +{ +"DuckDB": "ebc821a95b9286e22c2b26d0", +"None": "ebc821a95b9286e22c2b26d0", +"bigquery": "19a1a80ffc06169f32694de8", +"databricks": "ebc821a95b9286e22c2b26d0", +"duckdb": "ebc821a95b9286e22c2b26d0", +"generic": "ebc821a95b9286e22c2b26d0", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "ebc821a95b9286e22c2b26d0", +"postgres": "ebc821a95b9286e22c2b26d0", +"postgresql": "ebc821a95b9286e22c2b26d0", +"snowflake": "ebc821a95b9286e22c2b26d0", +"tsql": "ebc821a95b9286e22c2b26d0" +} +], +[ +"type", +{ +"DuckDB": "9c4e957c3856f1159283313a", +"None": "8731ee5ed03816bf6b4a8464", +"bigquery": "657a69dabb6a9b2c7b834d41", +"databricks": "606d813c3f1dfcf4921045c8", +"duckdb": "9c4e957c3856f1159283313a", +"generic": "8731ee5ed03816bf6b4a8464", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "b9f1a78bcda3bc968346cc10", +"postgres": "9c4e957c3856f1159283313a", +"postgresql": "9c4e957c3856f1159283313a", +"snowflake": "cd2eb5ae8b54388fde5d5737", +"tsql": "8619573249fac6f54d0bc771" +} +], +[ +"type", +{ +"DuckDB": "70fb4728c3adcf6dbe4975d5", +"None": "70fb4728c3adcf6dbe4975d5", +"bigquery": "70fb4728c3adcf6dbe4975d5", +"databricks": "70fb4728c3adcf6dbe4975d5", +"duckdb": "70fb4728c3adcf6dbe4975d5", +"generic": "70fb4728c3adcf6dbe4975d5", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "70fb4728c3adcf6dbe4975d5", +"postgres": "70fb4728c3adcf6dbe4975d5", +"postgresql": "70fb4728c3adcf6dbe4975d5", +"snowflake": "70fb4728c3adcf6dbe4975d5", +"tsql": "70fb4728c3adcf6dbe4975d5" +} +], +[ +"type", +{ +"DuckDB": "19a1a80ffc06169f32694de8", +"None": "19a1a80ffc06169f32694de8", +"bigquery": "19a1a80ffc06169f32694de8", +"databricks": "19a1a80ffc06169f32694de8", +"duckdb": "19a1a80ffc06169f32694de8", +"generic": "19a1a80ffc06169f32694de8", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "19a1a80ffc06169f32694de8", +"postgres": "19a1a80ffc06169f32694de8", +"postgresql": "19a1a80ffc06169f32694de8", +"snowflake": "19a1a80ffc06169f32694de8", +"tsql": "19a1a80ffc06169f32694de8" +} +], +[ +"type", +{ +"DuckDB": "1eb7fb4e8cf75773c5573562", +"None": "1eb7fb4e8cf75773c5573562", +"bigquery": "c9b810639795a7bfab91b98d", +"databricks": "1eb7fb4e8cf75773c5573562", +"duckdb": "1eb7fb4e8cf75773c5573562", +"generic": "1eb7fb4e8cf75773c5573562", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "1eb7fb4e8cf75773c5573562", +"postgres": "1eb7fb4e8cf75773c5573562", +"postgresql": "1eb7fb4e8cf75773c5573562", +"snowflake": "97a20344d811fb77c7690863", +"tsql": "1eb7fb4e8cf75773c5573562" +} +], +[ +"type", +{ +"DuckDB": "9ebaaf01ad47894d796ac621", +"None": "00caaa5ad0660c8df2165071", +"bigquery": "18cb3eafdbb91b315055426b", +"databricks": "7321b96df327a001959868b6", +"duckdb": "9ebaaf01ad47894d796ac621", +"generic": "00caaa5ad0660c8df2165071", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "00caaa5ad0660c8df2165071", +"postgres": "00caaa5ad0660c8df2165071", +"postgresql": "00caaa5ad0660c8df2165071", +"snowflake": "d5bfcc48faca639b47d37309", +"tsql": "00caaa5ad0660c8df2165071" +} +], +[ +"type", +{ +"DuckDB": "1eb7fb4e8cf75773c5573562", +"None": "1eb7fb4e8cf75773c5573562", +"bigquery": "c9b810639795a7bfab91b98d", +"databricks": "1eb7fb4e8cf75773c5573562", +"duckdb": "1eb7fb4e8cf75773c5573562", +"generic": "1eb7fb4e8cf75773c5573562", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "1eb7fb4e8cf75773c5573562", +"postgres": "1eb7fb4e8cf75773c5573562", +"postgresql": "1eb7fb4e8cf75773c5573562", +"snowflake": "97a20344d811fb77c7690863", +"tsql": "1eb7fb4e8cf75773c5573562" +} +], +[ +"type", +{ +"DuckDB": "7a79790250ede37cbc407ce6", +"None": "4425df9f96e51bc0984eab91", +"bigquery": "135a912ea74f76a35d9d0632", +"databricks": "4425df9f96e51bc0984eab91", +"duckdb": "7a79790250ede37cbc407ce6", +"generic": "4425df9f96e51bc0984eab91", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "6c03a3450ea4742ee7396e3c", +"postgres": "7a79790250ede37cbc407ce6", +"postgresql": "7a79790250ede37cbc407ce6", +"snowflake": "061ecb71b8d0a25345bb4dc5", +"tsql": "d1dc9a140dbe2eb1874c6ad7" +} +], +[ +"type", +{ +"DuckDB": "c50a316d091c821866e4bfba", +"None": "c50a316d091c821866e4bfba", +"bigquery": "c50a316d091c821866e4bfba", +"databricks": "c50a316d091c821866e4bfba", +"duckdb": "c50a316d091c821866e4bfba", +"generic": "c50a316d091c821866e4bfba", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "c50a316d091c821866e4bfba", +"postgres": "c50a316d091c821866e4bfba", +"postgresql": "c50a316d091c821866e4bfba", +"snowflake": "c50a316d091c821866e4bfba", +"tsql": "c50a316d091c821866e4bfba" +} +], +[ +"type", +{ +"DuckDB": "63c80b5d8e861216f0c45bfd", +"None": "d227b99a82e505d599c2ed8a", +"bigquery": "aa04c66b4fed5190c90308fd", +"databricks": "d227b99a82e505d599c2ed8a", +"duckdb": "63c80b5d8e861216f0c45bfd", +"generic": "d227b99a82e505d599c2ed8a", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "d227b99a82e505d599c2ed8a", +"postgres": "d227b99a82e505d599c2ed8a", +"postgresql": "d227b99a82e505d599c2ed8a", +"snowflake": "d227b99a82e505d599c2ed8a", +"tsql": "d227b99a82e505d599c2ed8a" +} +], +[ +"type", +{ +"DuckDB": "4ed568ea1adb2c8a7141be20", +"None": "b981394a3f4d961a44e73868", +"bigquery": "b981394a3f4d961a44e73868", +"databricks": "b981394a3f4d961a44e73868", +"duckdb": "4ed568ea1adb2c8a7141be20", +"generic": "b981394a3f4d961a44e73868", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "6c03a3450ea4742ee7396e3c", +"postgres": "4ed568ea1adb2c8a7141be20", +"postgresql": "4ed568ea1adb2c8a7141be20", +"snowflake": "b63ef04215d2dd65ccf32905", +"tsql": "c963e03af3ddb9731cbb40e3" +} +], +[ +"type", +{ +"DuckDB": "c50a316d091c821866e4bfba", +"None": "c50a316d091c821866e4bfba", +"bigquery": "c50a316d091c821866e4bfba", +"databricks": "c50a316d091c821866e4bfba", +"duckdb": "c50a316d091c821866e4bfba", +"generic": "c50a316d091c821866e4bfba", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "c50a316d091c821866e4bfba", +"postgres": "c50a316d091c821866e4bfba", +"postgresql": "c50a316d091c821866e4bfba", +"snowflake": "c50a316d091c821866e4bfba", +"tsql": "c50a316d091c821866e4bfba" +} +], +[ +"type", +{ +"DuckDB": "79278352c17c9de0f5a28af5", +"None": "79278352c17c9de0f5a28af5", +"bigquery": "c9b810639795a7bfab91b98d", +"databricks": "79278352c17c9de0f5a28af5", +"duckdb": "79278352c17c9de0f5a28af5", +"generic": "79278352c17c9de0f5a28af5", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "79278352c17c9de0f5a28af5", +"postgres": "79278352c17c9de0f5a28af5", +"postgresql": "79278352c17c9de0f5a28af5", +"snowflake": "97a20344d811fb77c7690863", +"tsql": "79278352c17c9de0f5a28af5" +} +], +[ +"type", +{ +"DuckDB": "f46cf4b4e131aa122b5b33d6", +"None": "f46cf4b4e131aa122b5b33d6", +"bigquery": "f46cf4b4e131aa122b5b33d6", +"databricks": "f46cf4b4e131aa122b5b33d6", +"duckdb": "f46cf4b4e131aa122b5b33d6", +"generic": "f46cf4b4e131aa122b5b33d6", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "f46cf4b4e131aa122b5b33d6", +"postgres": "f46cf4b4e131aa122b5b33d6", +"postgresql": "f46cf4b4e131aa122b5b33d6", +"snowflake": "f46cf4b4e131aa122b5b33d6", +"tsql": "f46cf4b4e131aa122b5b33d6" +} +], +[ +"type", +{ +"DuckDB": "0da0fad3107f7a26744c9411", +"None": "4172129e8d84a0da597bc612", +"bigquery": "d138b3b3355094a33a14355a", +"databricks": "4172129e8d84a0da597bc612", +"duckdb": "0da0fad3107f7a26744c9411", +"generic": "4172129e8d84a0da597bc612", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "6c03a3450ea4742ee7396e3c", +"postgres": "0da0fad3107f7a26744c9411", +"postgresql": "0da0fad3107f7a26744c9411", +"snowflake": "e21aafb74f6e5c5e181abd5e", +"tsql": "2e261f2f5a01e0e0f4a34a7a" +} +], +[ +"type", +{ +"DuckDB": "5c528c7b4329aeb692ec6e94", +"None": "5c528c7b4329aeb692ec6e94", +"bigquery": "5c528c7b4329aeb692ec6e94", +"databricks": "5c528c7b4329aeb692ec6e94", +"duckdb": "5c528c7b4329aeb692ec6e94", +"generic": "5c528c7b4329aeb692ec6e94", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "5c528c7b4329aeb692ec6e94", +"postgres": "5c528c7b4329aeb692ec6e94", +"postgresql": "5c528c7b4329aeb692ec6e94", +"snowflake": "5c528c7b4329aeb692ec6e94", +"tsql": "5c528c7b4329aeb692ec6e94" +} +], +[ +"type", +{ +"DuckDB": "b66ef401bfc62ea5f67697f0", +"None": "b66ef401bfc62ea5f67697f0", +"bigquery": "b66ef401bfc62ea5f67697f0", +"databricks": "b66ef401bfc62ea5f67697f0", +"duckdb": "b66ef401bfc62ea5f67697f0", +"generic": "b66ef401bfc62ea5f67697f0", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "b66ef401bfc62ea5f67697f0", +"postgres": "b66ef401bfc62ea5f67697f0", +"postgresql": "b66ef401bfc62ea5f67697f0", +"snowflake": "b66ef401bfc62ea5f67697f0", +"tsql": "b66ef401bfc62ea5f67697f0" +} +], +[ +"type", +{ +"DuckDB": "67b955e24db58c73ccf37441", +"None": "7390a6531648a24d91197039", +"bigquery": "41beda08d4df864cb9dd8402", +"databricks": "41beda08d4df864cb9dd8402", +"duckdb": "67b955e24db58c73ccf37441", +"generic": "7390a6531648a24d91197039", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "41beda08d4df864cb9dd8402", +"postgres": "4d6c7e32aac20e9e4fb2369e", +"postgresql": "4d6c7e32aac20e9e4fb2369e", +"snowflake": "bae18d740565e7e0e416c8f3", +"tsql": "762b596d819e7050cff38fb8" +} +], +[ +"type", +{ +"DuckDB": "c4346d0257336219f1d26890", +"None": "c4346d0257336219f1d26890", +"bigquery": "b5c4d5044b2a6e70633f0d0a", +"databricks": "c4346d0257336219f1d26890", +"duckdb": "c4346d0257336219f1d26890", +"generic": "c4346d0257336219f1d26890", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "c4346d0257336219f1d26890", +"postgres": "c4346d0257336219f1d26890", +"postgresql": "c4346d0257336219f1d26890", +"snowflake": "4e24a80b20b9dee0cbbfac17", +"tsql": "c4346d0257336219f1d26890" +} +], +[ +"type", +{ +"DuckDB": "e57ac1541fb51b362cd5b470", +"None": "e57ac1541fb51b362cd5b470", +"bigquery": "e57ac1541fb51b362cd5b470", +"databricks": "e57ac1541fb51b362cd5b470", +"duckdb": "e57ac1541fb51b362cd5b470", +"generic": "e57ac1541fb51b362cd5b470", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "e57ac1541fb51b362cd5b470", +"postgres": "e57ac1541fb51b362cd5b470", +"postgresql": "e57ac1541fb51b362cd5b470", +"snowflake": "4b356542044f1267fcfc487a", +"tsql": "e57ac1541fb51b362cd5b470" +} +], +[ +"type", +{ +"DuckDB": "f6c3d80bfee0ec0b286b82b5", +"None": "b137c998bdaa2555d912e8fa", +"bigquery": "b137c998bdaa2555d912e8fa", +"databricks": "b137c998bdaa2555d912e8fa", +"duckdb": "f6c3d80bfee0ec0b286b82b5", +"generic": "b137c998bdaa2555d912e8fa", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "b137c998bdaa2555d912e8fa", +"postgres": "b137c998bdaa2555d912e8fa", +"postgresql": "b137c998bdaa2555d912e8fa", +"snowflake": "b137c998bdaa2555d912e8fa", +"tsql": "b137c998bdaa2555d912e8fa" +} +], +[ +"type", +{ +"DuckDB": "ab5ad6180652b3b00d1f5b01", +"None": "ab5ad6180652b3b00d1f5b01", +"bigquery": "946d5ee30ab7469c57d850df", +"databricks": "ab5ad6180652b3b00d1f5b01", +"duckdb": "ab5ad6180652b3b00d1f5b01", +"generic": "ab5ad6180652b3b00d1f5b01", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "ab5ad6180652b3b00d1f5b01", +"postgres": "ab5ad6180652b3b00d1f5b01", +"postgresql": "ab5ad6180652b3b00d1f5b01", +"snowflake": "f43dac38f34a1c0618a3f812", +"tsql": "ab5ad6180652b3b00d1f5b01" +} +], +[ +"type", +{ +"DuckDB": "05ebf79d18b2ae4eaa41f450", +"None": "336fd1b7a1f7d8105c29280c", +"bigquery": "aa04c66b4fed5190c90308fd", +"databricks": "336fd1b7a1f7d8105c29280c", +"duckdb": "05ebf79d18b2ae4eaa41f450", +"generic": "336fd1b7a1f7d8105c29280c", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "336fd1b7a1f7d8105c29280c", +"postgres": "336fd1b7a1f7d8105c29280c", +"postgresql": "336fd1b7a1f7d8105c29280c", +"snowflake": "336fd1b7a1f7d8105c29280c", +"tsql": "336fd1b7a1f7d8105c29280c" +} +], +[ +"type", +{ +"DuckDB": "0960c90223e1eca15361360f", +"None": "0960c90223e1eca15361360f", +"bigquery": "0960c90223e1eca15361360f", +"databricks": "0960c90223e1eca15361360f", +"duckdb": "0960c90223e1eca15361360f", +"generic": "0960c90223e1eca15361360f", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "0960c90223e1eca15361360f", +"postgres": "0960c90223e1eca15361360f", +"postgresql": "0960c90223e1eca15361360f", +"snowflake": "0960c90223e1eca15361360f", +"tsql": "0960c90223e1eca15361360f" +} +], +[ +"type", +{ +"DuckDB": "b46dfa976d5ba04f95bea32b", +"None": "b46dfa976d5ba04f95bea32b", +"bigquery": "68d2179839f17f0eb289d1aa", +"databricks": "b46dfa976d5ba04f95bea32b", +"duckdb": "b46dfa976d5ba04f95bea32b", +"generic": "b46dfa976d5ba04f95bea32b", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "b46dfa976d5ba04f95bea32b", +"postgres": "34dcdfe3e3afe6140e1353e0", +"postgresql": "34dcdfe3e3afe6140e1353e0", +"snowflake": "b46dfa976d5ba04f95bea32b", +"tsql": "1d8b945fd793ecdcacb90c21" +} +], +[ +"type", +{ +"DuckDB": "b66ef401bfc62ea5f67697f0", +"None": "b66ef401bfc62ea5f67697f0", +"bigquery": "b66ef401bfc62ea5f67697f0", +"databricks": "b66ef401bfc62ea5f67697f0", +"duckdb": "b66ef401bfc62ea5f67697f0", +"generic": "b66ef401bfc62ea5f67697f0", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "b66ef401bfc62ea5f67697f0", +"postgres": "b66ef401bfc62ea5f67697f0", +"postgresql": "b66ef401bfc62ea5f67697f0", +"snowflake": "b66ef401bfc62ea5f67697f0", +"tsql": "b66ef401bfc62ea5f67697f0" +} +], +[ +"type", +{ +"DuckDB": "fe23594c781e79cbb0c8927a", +"None": "fe23594c781e79cbb0c8927a", +"bigquery": "fe23594c781e79cbb0c8927a", +"databricks": "fe23594c781e79cbb0c8927a", +"duckdb": "fe23594c781e79cbb0c8927a", +"generic": "fe23594c781e79cbb0c8927a", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "fe23594c781e79cbb0c8927a", +"postgres": "fe23594c781e79cbb0c8927a", +"postgresql": "fe23594c781e79cbb0c8927a", +"snowflake": "38b2ec94bf02be40007ce525", +"tsql": "fe23594c781e79cbb0c8927a" +} +], +[ +"type", +{ +"DuckDB": "66f7ca02161349d637fa7d4e", +"None": "66f7ca02161349d637fa7d4e", +"bigquery": "d90a78129f7050a540984f6f", +"databricks": "d90a78129f7050a540984f6f", +"duckdb": "66f7ca02161349d637fa7d4e", +"generic": "66f7ca02161349d637fa7d4e", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "d90a78129f7050a540984f6f", +"postgres": "66f7ca02161349d637fa7d4e", +"postgresql": "66f7ca02161349d637fa7d4e", +"snowflake": "66f7ca02161349d637fa7d4e", +"tsql": "66f7ca02161349d637fa7d4e" +} +], +[ +"type", +{ +"DuckDB": "6b7315cdb8da9cc8682fe582", +"None": "5db36cde08c21101926533c6", +"bigquery": "be1298bd832c06e2fbed16cc", +"databricks": "68c9a65b028d0f4e1e431d2b", +"duckdb": "6b7315cdb8da9cc8682fe582", +"generic": "5db36cde08c21101926533c6", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "3a28322a1d9fe5f73ddf21a6", +"postgres": "627a2125b73642795b93f3ec", +"postgresql": "627a2125b73642795b93f3ec", +"snowflake": "c990ce1e11ec35da455f1547", +"tsql": "5db36cde08c21101926533c6" +} +], +[ +"type", +{ +"DuckDB": "26e466cea9d3c66c226e9bbb", +"None": "26e466cea9d3c66c226e9bbb", +"bigquery": "26e466cea9d3c66c226e9bbb", +"databricks": "26e466cea9d3c66c226e9bbb", +"duckdb": "26e466cea9d3c66c226e9bbb", +"generic": "26e466cea9d3c66c226e9bbb", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "26e466cea9d3c66c226e9bbb", +"postgres": "26e466cea9d3c66c226e9bbb", +"postgresql": "26e466cea9d3c66c226e9bbb", +"snowflake": "26e466cea9d3c66c226e9bbb", +"tsql": "26e466cea9d3c66c226e9bbb" +} +], +[ +"type", +{ +"DuckDB": "31efc7b307bffec917380e8e", +"None": "31efc7b307bffec917380e8e", +"bigquery": "31efc7b307bffec917380e8e", +"databricks": "31efc7b307bffec917380e8e", +"duckdb": "31efc7b307bffec917380e8e", +"generic": "31efc7b307bffec917380e8e", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "31efc7b307bffec917380e8e", +"postgres": "31efc7b307bffec917380e8e", +"postgresql": "31efc7b307bffec917380e8e", +"snowflake": "42d4a23d9a52e79d0c3458d3", +"tsql": "31efc7b307bffec917380e8e" +} +], +[ +"type", +{ +"DuckDB": "2f9ac8bd6831b78665301f10", +"None": "2f9ac8bd6831b78665301f10", +"bigquery": "2f9ac8bd6831b78665301f10", +"databricks": "2f9ac8bd6831b78665301f10", +"duckdb": "2f9ac8bd6831b78665301f10", +"generic": "2f9ac8bd6831b78665301f10", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "2f9ac8bd6831b78665301f10", +"postgres": "2f9ac8bd6831b78665301f10", +"postgresql": "2f9ac8bd6831b78665301f10", +"snowflake": "2f9ac8bd6831b78665301f10", +"tsql": "2f9ac8bd6831b78665301f10" +} +], +[ +"type", +{ +"DuckDB": "1eb7fb4e8cf75773c5573562", +"None": "1eb7fb4e8cf75773c5573562", +"bigquery": "c9b810639795a7bfab91b98d", +"databricks": "1eb7fb4e8cf75773c5573562", +"duckdb": "1eb7fb4e8cf75773c5573562", +"generic": "1eb7fb4e8cf75773c5573562", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "1eb7fb4e8cf75773c5573562", +"postgres": "1eb7fb4e8cf75773c5573562", +"postgresql": "1eb7fb4e8cf75773c5573562", +"snowflake": "97a20344d811fb77c7690863", +"tsql": "1eb7fb4e8cf75773c5573562" +} +], +[ +"type", +{ +"DuckDB": "7102b9514dfef58f8673a6bf", +"None": "7102b9514dfef58f8673a6bf", +"bigquery": "7102b9514dfef58f8673a6bf", +"databricks": "7102b9514dfef58f8673a6bf", +"duckdb": "7102b9514dfef58f8673a6bf", +"generic": "7102b9514dfef58f8673a6bf", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "7102b9514dfef58f8673a6bf", +"postgres": "7102b9514dfef58f8673a6bf", +"postgresql": "7102b9514dfef58f8673a6bf", +"snowflake": "7102b9514dfef58f8673a6bf", +"tsql": "7102b9514dfef58f8673a6bf" +} +], +[ +"type", +{ +"DuckDB": "6d7ab232e65fe8d85c7169ae", +"None": "6d7ab232e65fe8d85c7169ae", +"bigquery": "6f6198e2d2c8a8d6444ef5af", +"databricks": "6d7ab232e65fe8d85c7169ae", +"duckdb": "6d7ab232e65fe8d85c7169ae", +"generic": "6d7ab232e65fe8d85c7169ae", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "6d7ab232e65fe8d85c7169ae", +"postgres": "a6659d96bbfa5da75e69e22d", +"postgresql": "a6659d96bbfa5da75e69e22d", +"snowflake": "6d7ab232e65fe8d85c7169ae", +"tsql": "aed0419e7f2ce7c0a8892248" +} +], +[ +"type", +{ +"DuckDB": "e7683084f9cefaf3748cf526", +"None": "e7683084f9cefaf3748cf526", +"bigquery": "e7683084f9cefaf3748cf526", +"databricks": "e7683084f9cefaf3748cf526", +"duckdb": "e7683084f9cefaf3748cf526", +"generic": "e7683084f9cefaf3748cf526", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "e7683084f9cefaf3748cf526", +"postgres": "e7683084f9cefaf3748cf526", +"postgresql": "e7683084f9cefaf3748cf526", +"snowflake": "e7683084f9cefaf3748cf526", +"tsql": "e7683084f9cefaf3748cf526" +} +], +[ +"type", +{ +"DuckDB": "2bfa352725f9d8a91250f75e", +"None": "2bfa352725f9d8a91250f75e", +"bigquery": "2bfa352725f9d8a91250f75e", +"databricks": "2bfa352725f9d8a91250f75e", +"duckdb": "2bfa352725f9d8a91250f75e", +"generic": "2bfa352725f9d8a91250f75e", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "2bfa352725f9d8a91250f75e", +"postgres": "2bfa352725f9d8a91250f75e", +"postgresql": "2bfa352725f9d8a91250f75e", +"snowflake": "2bfa352725f9d8a91250f75e", +"tsql": "2bfa352725f9d8a91250f75e" +} +], +[ +"type", +{ +"DuckDB": "50a940812c6ed2e6dd842e74", +"None": "50a940812c6ed2e6dd842e74", +"bigquery": "50a940812c6ed2e6dd842e74", +"databricks": "50a940812c6ed2e6dd842e74", +"duckdb": "50a940812c6ed2e6dd842e74", +"generic": "50a940812c6ed2e6dd842e74", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "50a940812c6ed2e6dd842e74", +"postgres": "50a940812c6ed2e6dd842e74", +"postgresql": "50a940812c6ed2e6dd842e74", +"snowflake": "50a940812c6ed2e6dd842e74", +"tsql": "50a940812c6ed2e6dd842e74" +} +], +[ +"type", +{ +"DuckDB": "e1c74d96ac578f9323bf1bbd", +"None": "e1c74d96ac578f9323bf1bbd", +"bigquery": "e1c74d96ac578f9323bf1bbd", +"databricks": "e1c74d96ac578f9323bf1bbd", +"duckdb": "e1c74d96ac578f9323bf1bbd", +"generic": "e1c74d96ac578f9323bf1bbd", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "e1c74d96ac578f9323bf1bbd", +"postgres": "e1c74d96ac578f9323bf1bbd", +"postgresql": "e1c74d96ac578f9323bf1bbd", +"snowflake": "e1c74d96ac578f9323bf1bbd", +"tsql": "e1c74d96ac578f9323bf1bbd" +} +], +[ +"type", +{ +"DuckDB": "d6e37cd37419bfb26e09b080", +"None": "d6e37cd37419bfb26e09b080", +"bigquery": "d6e37cd37419bfb26e09b080", +"databricks": "d6e37cd37419bfb26e09b080", +"duckdb": "d6e37cd37419bfb26e09b080", +"generic": "d6e37cd37419bfb26e09b080", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "d6e37cd37419bfb26e09b080", +"postgres": "d6e37cd37419bfb26e09b080", +"postgresql": "d6e37cd37419bfb26e09b080", +"snowflake": "d6e37cd37419bfb26e09b080", +"tsql": "d6e37cd37419bfb26e09b080" +} +], +[ +"type", +{ +"DuckDB": "5abf4ec799a2ec32fb10da7e", +"None": "de89632e277dbc8c97115419", +"bigquery": "de89632e277dbc8c97115419", +"databricks": "de89632e277dbc8c97115419", +"duckdb": "5abf4ec799a2ec32fb10da7e", +"generic": "de89632e277dbc8c97115419", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "de89632e277dbc8c97115419", +"postgres": "de89632e277dbc8c97115419", +"postgresql": "de89632e277dbc8c97115419", +"snowflake": "4b356542044f1267fcfc487a", +"tsql": "de89632e277dbc8c97115419" +} +], +[ +"type", +{ +"DuckDB": "7a79790250ede37cbc407ce6", +"None": "4425df9f96e51bc0984eab91", +"bigquery": "135a912ea74f76a35d9d0632", +"databricks": "4425df9f96e51bc0984eab91", +"duckdb": "7a79790250ede37cbc407ce6", +"generic": "4425df9f96e51bc0984eab91", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "6c03a3450ea4742ee7396e3c", +"postgres": "7a79790250ede37cbc407ce6", +"postgresql": "7a79790250ede37cbc407ce6", +"snowflake": "061ecb71b8d0a25345bb4dc5", +"tsql": "45809055304b61252670382f" +} +], +[ +"type", +{ +"DuckDB": "c7b697bbfa82dd2821ad64e9", +"None": "c7b697bbfa82dd2821ad64e9", +"bigquery": "dcb00b7053ffe69fe3ce99cd", +"databricks": "dcb00b7053ffe69fe3ce99cd", +"duckdb": "c7b697bbfa82dd2821ad64e9", +"generic": "c7b697bbfa82dd2821ad64e9", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "dcb00b7053ffe69fe3ce99cd", +"postgres": "c7b697bbfa82dd2821ad64e9", +"postgresql": "c7b697bbfa82dd2821ad64e9", +"snowflake": "c7b697bbfa82dd2821ad64e9", +"tsql": "c7b697bbfa82dd2821ad64e9" +} +], +[ +"type", +{ +"DuckDB": "66acfa34471e60551c71ca8a", +"None": "66acfa34471e60551c71ca8a", +"bigquery": "66acfa34471e60551c71ca8a", +"databricks": "66acfa34471e60551c71ca8a", +"duckdb": "66acfa34471e60551c71ca8a", +"generic": "66acfa34471e60551c71ca8a", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "66acfa34471e60551c71ca8a", +"postgres": "66acfa34471e60551c71ca8a", +"postgresql": "66acfa34471e60551c71ca8a", +"snowflake": "6306b9e88f7b13dbb6a32c00", +"tsql": "66acfa34471e60551c71ca8a" +} +], +[ +"type", +{ +"DuckDB": "793afe64018cd40f2abf8cd7", +"None": "793afe64018cd40f2abf8cd7", +"bigquery": "293fbfa51e5b07f0e2aee3d3", +"databricks": "bca4e355ae48af6503cb15b3", +"duckdb": "793afe64018cd40f2abf8cd7", +"generic": "793afe64018cd40f2abf8cd7", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "793afe64018cd40f2abf8cd7", +"postgres": "793afe64018cd40f2abf8cd7", +"postgresql": "793afe64018cd40f2abf8cd7", +"snowflake": "c0351067a884fbee21c680b3", +"tsql": "793afe64018cd40f2abf8cd7" +} +], +[ +"type", +{ +"DuckDB": "0c40d2d16c130d68a7c6c41d", +"None": "0c40d2d16c130d68a7c6c41d", +"bigquery": "0c40d2d16c130d68a7c6c41d", +"databricks": "0c40d2d16c130d68a7c6c41d", +"duckdb": "0c40d2d16c130d68a7c6c41d", +"generic": "0c40d2d16c130d68a7c6c41d", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "0c40d2d16c130d68a7c6c41d", +"postgres": "0c40d2d16c130d68a7c6c41d", +"postgresql": "0c40d2d16c130d68a7c6c41d", +"snowflake": "0c40d2d16c130d68a7c6c41d", +"tsql": "0c40d2d16c130d68a7c6c41d" +} +], +[ +"type", +{ +"DuckDB": "e1c36a5cdd2427ff2b089ac9", +"None": "e1c36a5cdd2427ff2b089ac9", +"bigquery": "e1c36a5cdd2427ff2b089ac9", +"databricks": "e1c36a5cdd2427ff2b089ac9", +"duckdb": "e1c36a5cdd2427ff2b089ac9", +"generic": "e1c36a5cdd2427ff2b089ac9", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "e1c36a5cdd2427ff2b089ac9", +"postgres": "e1c36a5cdd2427ff2b089ac9", +"postgresql": "e1c36a5cdd2427ff2b089ac9", +"snowflake": "18db5afe2c1e80d1ee652b54", +"tsql": "e1c36a5cdd2427ff2b089ac9" +} +], +[ +"type", +{ +"DuckDB": "f73576af0cd50cbe498a0092", +"None": "f73576af0cd50cbe498a0092", +"bigquery": "f73576af0cd50cbe498a0092", +"databricks": "f73576af0cd50cbe498a0092", +"duckdb": "f73576af0cd50cbe498a0092", +"generic": "f73576af0cd50cbe498a0092", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "f73576af0cd50cbe498a0092", +"postgres": "f73576af0cd50cbe498a0092", +"postgresql": "f73576af0cd50cbe498a0092", +"snowflake": "f73576af0cd50cbe498a0092", +"tsql": "f73576af0cd50cbe498a0092" +} +], +[ +"type", +{ +"DuckDB": "3f71ab5f3c1c040da96f2cec", +"None": "3f71ab5f3c1c040da96f2cec", +"bigquery": "3f71ab5f3c1c040da96f2cec", +"databricks": "3f71ab5f3c1c040da96f2cec", +"duckdb": "3f71ab5f3c1c040da96f2cec", +"generic": "3f71ab5f3c1c040da96f2cec", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "3f71ab5f3c1c040da96f2cec", +"postgres": "3f71ab5f3c1c040da96f2cec", +"postgresql": "3f71ab5f3c1c040da96f2cec", +"snowflake": "3f71ab5f3c1c040da96f2cec", +"tsql": "3f71ab5f3c1c040da96f2cec" +} +], +[ +"type", +{ +"DuckDB": "83fdbd1f0a6ee4e72faa4d94", +"None": "83fdbd1f0a6ee4e72faa4d94", +"bigquery": "83fdbd1f0a6ee4e72faa4d94", +"databricks": "83fdbd1f0a6ee4e72faa4d94", +"duckdb": "83fdbd1f0a6ee4e72faa4d94", +"generic": "83fdbd1f0a6ee4e72faa4d94", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "83fdbd1f0a6ee4e72faa4d94", +"postgres": "83fdbd1f0a6ee4e72faa4d94", +"postgresql": "83fdbd1f0a6ee4e72faa4d94", +"snowflake": "83fdbd1f0a6ee4e72faa4d94", +"tsql": "83fdbd1f0a6ee4e72faa4d94" +} +], +[ +"type", +{ +"DuckDB": "355e032cc5c0f24695836b3d", +"None": "355e032cc5c0f24695836b3d", +"bigquery": "d9a4e245156e760303573500", +"databricks": "e3bc1b8bad22d8104417b00f", +"duckdb": "355e032cc5c0f24695836b3d", +"generic": "355e032cc5c0f24695836b3d", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "355e032cc5c0f24695836b3d", +"postgres": "b0b09c4a6f7570ece56f59ce", +"postgresql": "b0b09c4a6f7570ece56f59ce", +"snowflake": "355e032cc5c0f24695836b3d", +"tsql": "355e032cc5c0f24695836b3d" +} +], +[ +"type", +{ +"DuckDB": "a40042061a75dff39acf27ea", +"None": "a40042061a75dff39acf27ea", +"bigquery": "a40042061a75dff39acf27ea", +"databricks": "a40042061a75dff39acf27ea", +"duckdb": "a40042061a75dff39acf27ea", +"generic": "a40042061a75dff39acf27ea", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "a40042061a75dff39acf27ea", +"postgres": "a40042061a75dff39acf27ea", +"postgresql": "a40042061a75dff39acf27ea", +"snowflake": "a40042061a75dff39acf27ea", +"tsql": "a40042061a75dff39acf27ea" +} +], +[ +"type", +{ +"DuckDB": "e46d4be44ab9e500e9190d26", +"None": "e46d4be44ab9e500e9190d26", +"bigquery": "e6ffdece2977be55da73b59a", +"databricks": "e46d4be44ab9e500e9190d26", +"duckdb": "e46d4be44ab9e500e9190d26", +"generic": "e46d4be44ab9e500e9190d26", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "e46d4be44ab9e500e9190d26", +"postgres": "e46d4be44ab9e500e9190d26", +"postgresql": "e46d4be44ab9e500e9190d26", +"snowflake": "e46d4be44ab9e500e9190d26", +"tsql": "e46d4be44ab9e500e9190d26" +} +], +[ +"type", +{ +"DuckDB": "d0c95c7a10940244afe0eb6c", +"None": "d0c95c7a10940244afe0eb6c", +"bigquery": "23ee196b7bd6039855a1460f", +"databricks": "d0c95c7a10940244afe0eb6c", +"duckdb": "d0c95c7a10940244afe0eb6c", +"generic": "d0c95c7a10940244afe0eb6c", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "d0c95c7a10940244afe0eb6c", +"postgres": "d0c95c7a10940244afe0eb6c", +"postgresql": "d0c95c7a10940244afe0eb6c", +"snowflake": "d0c95c7a10940244afe0eb6c", +"tsql": "d0c95c7a10940244afe0eb6c" +} +], +[ +"type", +{ +"DuckDB": "5c28019dce48a74708c90a76", +"None": "5c28019dce48a74708c90a76", +"bigquery": "f28a96f0eb38ad8874f6ec5d", +"databricks": "5c28019dce48a74708c90a76", +"duckdb": "5c28019dce48a74708c90a76", +"generic": "5c28019dce48a74708c90a76", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "5c28019dce48a74708c90a76", +"postgres": "5c28019dce48a74708c90a76", +"postgresql": "5c28019dce48a74708c90a76", +"snowflake": "a5656d70e208254d1d3e9b4f", +"tsql": "2a7a7132adc795ca2bc39c37" +} +], +[ +"type", +{ +"DuckDB": "2e4ac90e0dc84f220169a428", +"None": "2e4ac90e0dc84f220169a428", +"bigquery": "2e4ac90e0dc84f220169a428", +"databricks": "2e4ac90e0dc84f220169a428", +"duckdb": "2e4ac90e0dc84f220169a428", +"generic": "2e4ac90e0dc84f220169a428", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "2e4ac90e0dc84f220169a428", +"postgres": "2e4ac90e0dc84f220169a428", +"postgresql": "2e4ac90e0dc84f220169a428", +"snowflake": "2e4ac90e0dc84f220169a428", +"tsql": "2e4ac90e0dc84f220169a428" +} +], +[ +"type", +{ +"DuckDB": "f94b458b28b4e92e314740bf", +"None": "f94b458b28b4e92e314740bf", +"bigquery": "f94b458b28b4e92e314740bf", +"databricks": "f94b458b28b4e92e314740bf", +"duckdb": "f94b458b28b4e92e314740bf", +"generic": "f94b458b28b4e92e314740bf", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "f94b458b28b4e92e314740bf", +"postgres": "f94b458b28b4e92e314740bf", +"postgresql": "f94b458b28b4e92e314740bf", +"snowflake": "f94b458b28b4e92e314740bf", +"tsql": "f94b458b28b4e92e314740bf" +} +], +[ +"type", +{ +"DuckDB": "2705f19942a4194a72576911", +"None": "2705f19942a4194a72576911", +"bigquery": "6f763a99e9c69109526b40c0", +"databricks": "2705f19942a4194a72576911", +"duckdb": "2705f19942a4194a72576911", +"generic": "2705f19942a4194a72576911", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "2705f19942a4194a72576911", +"postgres": "2705f19942a4194a72576911", +"postgresql": "2705f19942a4194a72576911", +"snowflake": "2705f19942a4194a72576911", +"tsql": "2705f19942a4194a72576911" +} +], +[ +"type", +{ +"DuckDB": "42a76d5ff05d0f91911ff368", +"None": "42a76d5ff05d0f91911ff368", +"bigquery": "42a76d5ff05d0f91911ff368", +"databricks": "42a76d5ff05d0f91911ff368", +"duckdb": "42a76d5ff05d0f91911ff368", +"generic": "42a76d5ff05d0f91911ff368", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "42a76d5ff05d0f91911ff368", +"postgres": "42a76d5ff05d0f91911ff368", +"postgresql": "42a76d5ff05d0f91911ff368", +"snowflake": "42a76d5ff05d0f91911ff368", +"tsql": "42a76d5ff05d0f91911ff368" +} +], +[ +"type", +{ +"DuckDB": "de89632e277dbc8c97115419", +"None": "de89632e277dbc8c97115419", +"bigquery": "de89632e277dbc8c97115419", +"databricks": "de89632e277dbc8c97115419", +"duckdb": "de89632e277dbc8c97115419", +"generic": "de89632e277dbc8c97115419", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "de89632e277dbc8c97115419", +"postgres": "de89632e277dbc8c97115419", +"postgresql": "de89632e277dbc8c97115419", +"snowflake": "4b356542044f1267fcfc487a", +"tsql": "de89632e277dbc8c97115419" +} +], +[ +"type", +{ +"DuckDB": "f94b458b28b4e92e314740bf", +"None": "f94b458b28b4e92e314740bf", +"bigquery": "f94b458b28b4e92e314740bf", +"databricks": "f94b458b28b4e92e314740bf", +"duckdb": "f94b458b28b4e92e314740bf", +"generic": "f94b458b28b4e92e314740bf", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "f94b458b28b4e92e314740bf", +"postgres": "f94b458b28b4e92e314740bf", +"postgresql": "f94b458b28b4e92e314740bf", +"snowflake": "f94b458b28b4e92e314740bf", +"tsql": "f94b458b28b4e92e314740bf" +} +], +[ +"type", +{ +"DuckDB": "19a1a80ffc06169f32694de8", +"None": "19a1a80ffc06169f32694de8", +"bigquery": "19a1a80ffc06169f32694de8", +"databricks": "19a1a80ffc06169f32694de8", +"duckdb": "19a1a80ffc06169f32694de8", +"generic": "19a1a80ffc06169f32694de8", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "19a1a80ffc06169f32694de8", +"postgres": "19a1a80ffc06169f32694de8", +"postgresql": "19a1a80ffc06169f32694de8", +"snowflake": "19a1a80ffc06169f32694de8", +"tsql": "19a1a80ffc06169f32694de8" +} +], +[ +"type", +{ +"DuckDB": "7c11e0be7630905d93bd9ce1", +"None": "7c11e0be7630905d93bd9ce1", +"bigquery": "7c11e0be7630905d93bd9ce1", +"databricks": "7c11e0be7630905d93bd9ce1", +"duckdb": "7c11e0be7630905d93bd9ce1", +"generic": "7c11e0be7630905d93bd9ce1", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "7c11e0be7630905d93bd9ce1", +"postgres": "7c11e0be7630905d93bd9ce1", +"postgresql": "7c11e0be7630905d93bd9ce1", +"snowflake": "7c11e0be7630905d93bd9ce1", +"tsql": "7c11e0be7630905d93bd9ce1" +} +], +[ +"type", +{ +"DuckDB": "ebc821a95b9286e22c2b26d0", +"None": "ebc821a95b9286e22c2b26d0", +"bigquery": "19a1a80ffc06169f32694de8", +"databricks": "ebc821a95b9286e22c2b26d0", +"duckdb": "ebc821a95b9286e22c2b26d0", +"generic": "ebc821a95b9286e22c2b26d0", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "ebc821a95b9286e22c2b26d0", +"postgres": "ebc821a95b9286e22c2b26d0", +"postgresql": "ebc821a95b9286e22c2b26d0", +"snowflake": "ebc821a95b9286e22c2b26d0", +"tsql": "ebc821a95b9286e22c2b26d0" +} +], +[ +"type", +{ +"DuckDB": "181c436b3522e70edf3adf58", +"None": "181c436b3522e70edf3adf58", +"bigquery": "181c436b3522e70edf3adf58", +"databricks": "181c436b3522e70edf3adf58", +"duckdb": "181c436b3522e70edf3adf58", +"generic": "181c436b3522e70edf3adf58", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "181c436b3522e70edf3adf58", +"postgres": "181c436b3522e70edf3adf58", +"postgresql": "181c436b3522e70edf3adf58", +"snowflake": "181c436b3522e70edf3adf58", +"tsql": "181c436b3522e70edf3adf58" +} +], +[ +"type", +{ +"DuckDB": "24c3d9dcce7ee2c5b2bac1df", +"None": "547c73a68a3263d4ca786f4d", +"bigquery": "547c73a68a3263d4ca786f4d", +"databricks": "3ad35a92f1fdd0560316b488", +"duckdb": "24c3d9dcce7ee2c5b2bac1df", +"generic": "547c73a68a3263d4ca786f4d", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "6c03a3450ea4742ee7396e3c", +"postgres": "24c3d9dcce7ee2c5b2bac1df", +"postgresql": "24c3d9dcce7ee2c5b2bac1df", +"snowflake": "0591bc1bf9f4f62b80103d53", +"tsql": "d1dc9a140dbe2eb1874c6ad7" +} +], +[ +"type", +{ +"DuckDB": "b60a7259ca26ea325ba090a1", +"None": "b60a7259ca26ea325ba090a1", +"bigquery": "b60a7259ca26ea325ba090a1", +"databricks": "b60a7259ca26ea325ba090a1", +"duckdb": "b60a7259ca26ea325ba090a1", +"generic": "b60a7259ca26ea325ba090a1", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "b60a7259ca26ea325ba090a1", +"postgres": "b60a7259ca26ea325ba090a1", +"postgresql": "b60a7259ca26ea325ba090a1", +"snowflake": "b60a7259ca26ea325ba090a1", +"tsql": "b60a7259ca26ea325ba090a1" +} +], +[ +"type", +{ +"DuckDB": "79278352c17c9de0f5a28af5", +"None": "79278352c17c9de0f5a28af5", +"bigquery": "c9b810639795a7bfab91b98d", +"databricks": "79278352c17c9de0f5a28af5", +"duckdb": "79278352c17c9de0f5a28af5", +"generic": "79278352c17c9de0f5a28af5", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "79278352c17c9de0f5a28af5", +"postgres": "79278352c17c9de0f5a28af5", +"postgresql": "79278352c17c9de0f5a28af5", +"snowflake": "97a20344d811fb77c7690863", +"tsql": "79278352c17c9de0f5a28af5" +} +], +[ +"type", +{ +"DuckDB": "285056becb5d467811be7cd6", +"None": "285056becb5d467811be7cd6", +"bigquery": "0712c33a016f7dd6a37ee011", +"databricks": "285056becb5d467811be7cd6", +"duckdb": "285056becb5d467811be7cd6", +"generic": "285056becb5d467811be7cd6", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "fc10fc558d906a80a6404b7f", +"postgres": "285056becb5d467811be7cd6", +"postgresql": "285056becb5d467811be7cd6", +"snowflake": "0712c33a016f7dd6a37ee011", +"tsql": "285056becb5d467811be7cd6" +} +], +[ +"type", +{ +"DuckDB": "fe23594c781e79cbb0c8927a", +"None": "fe23594c781e79cbb0c8927a", +"bigquery": "fe23594c781e79cbb0c8927a", +"databricks": "fe23594c781e79cbb0c8927a", +"duckdb": "fe23594c781e79cbb0c8927a", +"generic": "fe23594c781e79cbb0c8927a", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "fe23594c781e79cbb0c8927a", +"postgres": "fe23594c781e79cbb0c8927a", +"postgresql": "fe23594c781e79cbb0c8927a", +"snowflake": "38b2ec94bf02be40007ce525", +"tsql": "fe23594c781e79cbb0c8927a" +} +], +[ +"type", +{ +"DuckDB": "fe23594c781e79cbb0c8927a", +"None": "fe23594c781e79cbb0c8927a", +"bigquery": "fe23594c781e79cbb0c8927a", +"databricks": "fe23594c781e79cbb0c8927a", +"duckdb": "fe23594c781e79cbb0c8927a", +"generic": "fe23594c781e79cbb0c8927a", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "fe23594c781e79cbb0c8927a", +"postgres": "fe23594c781e79cbb0c8927a", +"postgresql": "fe23594c781e79cbb0c8927a", +"snowflake": "38b2ec94bf02be40007ce525", +"tsql": "fe23594c781e79cbb0c8927a" +} +], +[ +"type", +{ +"DuckDB": "a3b6b25265be330ec52a3322", +"None": "a3b6b25265be330ec52a3322", +"bigquery": "204206d1d1eecf007966cc5b", +"databricks": "e3bc1b8bad22d8104417b00f", +"duckdb": "a3b6b25265be330ec52a3322", +"generic": "a3b6b25265be330ec52a3322", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "919b7ec6a7b49d8527b784cd", +"postgres": "a3b6b25265be330ec52a3322", +"postgresql": "a3b6b25265be330ec52a3322", +"snowflake": "919b7ec6a7b49d8527b784cd", +"tsql": "a3b6b25265be330ec52a3322" +} +], +[ +"type", +{ +"DuckDB": "4d0f0db1a550ed1e0da1a043", +"None": "4d0f0db1a550ed1e0da1a043", +"bigquery": "4d0f0db1a550ed1e0da1a043", +"databricks": "4d0f0db1a550ed1e0da1a043", +"duckdb": "4d0f0db1a550ed1e0da1a043", +"generic": "4d0f0db1a550ed1e0da1a043", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "4d0f0db1a550ed1e0da1a043", +"postgres": "4d0f0db1a550ed1e0da1a043", +"postgresql": "4d0f0db1a550ed1e0da1a043", +"snowflake": "4d0f0db1a550ed1e0da1a043", +"tsql": "4d0f0db1a550ed1e0da1a043" +} +], +[ +"type", +{ +"DuckDB": "6f4372a332076048e56d5076", +"None": "6f4372a332076048e56d5076", +"bigquery": "74a30f6aa9def0b58afc616c", +"databricks": "6f4372a332076048e56d5076", +"duckdb": "6f4372a332076048e56d5076", +"generic": "6f4372a332076048e56d5076", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "6f4372a332076048e56d5076", +"postgres": "6f4372a332076048e56d5076", +"postgresql": "6f4372a332076048e56d5076", +"snowflake": "daeeb0f00b3ee4211b8da00f", +"tsql": "6f4372a332076048e56d5076" +} +], +[ +"type", +{ +"DuckDB": "62368fc15cefd5807807b209", +"None": "62368fc15cefd5807807b209", +"bigquery": "e6ffdece2977be55da73b59a", +"databricks": "62368fc15cefd5807807b209", +"duckdb": "62368fc15cefd5807807b209", +"generic": "62368fc15cefd5807807b209", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "62368fc15cefd5807807b209", +"postgres": "62368fc15cefd5807807b209", +"postgresql": "62368fc15cefd5807807b209", +"snowflake": "62368fc15cefd5807807b209", +"tsql": "62368fc15cefd5807807b209" +} +], +[ +"type", +{ +"DuckDB": "e8b6e0bd2ded7b9eec6209e4", +"None": "e8b6e0bd2ded7b9eec6209e4", +"bigquery": "e8b6e0bd2ded7b9eec6209e4", +"databricks": "e8b6e0bd2ded7b9eec6209e4", +"duckdb": "e8b6e0bd2ded7b9eec6209e4", +"generic": "e8b6e0bd2ded7b9eec6209e4", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "e8b6e0bd2ded7b9eec6209e4", +"postgres": "e8b6e0bd2ded7b9eec6209e4", +"postgresql": "e8b6e0bd2ded7b9eec6209e4", +"snowflake": "e8b6e0bd2ded7b9eec6209e4", +"tsql": "e8b6e0bd2ded7b9eec6209e4" +} +], +[ +"type", +{ +"DuckDB": "087a9417cb511ff7bcfd6ccb", +"None": "383f8922f4b6f167d384037d", +"bigquery": "383f8922f4b6f167d384037d", +"databricks": "383f8922f4b6f167d384037d", +"duckdb": "087a9417cb511ff7bcfd6ccb", +"generic": "383f8922f4b6f167d384037d", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "383f8922f4b6f167d384037d", +"postgres": "383f8922f4b6f167d384037d", +"postgresql": "383f8922f4b6f167d384037d", +"snowflake": "383f8922f4b6f167d384037d", +"tsql": "383f8922f4b6f167d384037d" +} +], +[ +"type", +{ +"DuckDB": "e08a957777bd278f921ca0ee", +"None": "e08a957777bd278f921ca0ee", +"bigquery": "b1b23029bedaa16e2a6f8516", +"databricks": "e08a957777bd278f921ca0ee", +"duckdb": "e08a957777bd278f921ca0ee", +"generic": "e08a957777bd278f921ca0ee", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "e08a957777bd278f921ca0ee", +"postgres": "e08a957777bd278f921ca0ee", +"postgresql": "e08a957777bd278f921ca0ee", +"snowflake": "e08a957777bd278f921ca0ee", +"tsql": "e08a957777bd278f921ca0ee" +} +], +[ +"type", +{ +"DuckDB": "d79c3ac70093cb4cb531e71c", +"None": "d79c3ac70093cb4cb531e71c", +"bigquery": "b0477b36767a62145aa9158c", +"databricks": "d79c3ac70093cb4cb531e71c", +"duckdb": "d79c3ac70093cb4cb531e71c", +"generic": "d79c3ac70093cb4cb531e71c", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "d79c3ac70093cb4cb531e71c", +"postgres": "d79c3ac70093cb4cb531e71c", +"postgresql": "d79c3ac70093cb4cb531e71c", +"snowflake": "652ff8b21f638eac8fdc46c5", +"tsql": "d79c3ac70093cb4cb531e71c" +} +], +[ +"type", +{ +"DuckDB": "688179272da645629077e980", +"None": "688179272da645629077e980", +"bigquery": "688179272da645629077e980", +"databricks": "688179272da645629077e980", +"duckdb": "688179272da645629077e980", +"generic": "688179272da645629077e980", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "688179272da645629077e980", +"postgres": "688179272da645629077e980", +"postgresql": "688179272da645629077e980", +"snowflake": "b210f8eb26c37b422f786c6b", +"tsql": "688179272da645629077e980" +} +], +[ +"type", +{ +"DuckDB": "e08a957777bd278f921ca0ee", +"None": "e08a957777bd278f921ca0ee", +"bigquery": "b1b23029bedaa16e2a6f8516", +"databricks": "e08a957777bd278f921ca0ee", +"duckdb": "e08a957777bd278f921ca0ee", +"generic": "e08a957777bd278f921ca0ee", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "e08a957777bd278f921ca0ee", +"postgres": "e08a957777bd278f921ca0ee", +"postgresql": "e08a957777bd278f921ca0ee", +"snowflake": "e08a957777bd278f921ca0ee", +"tsql": "e08a957777bd278f921ca0ee" +} +], +[ +"type", +{ +"DuckDB": "3533f91995bca270f191503d", +"None": "3533f91995bca270f191503d", +"bigquery": "3533f91995bca270f191503d", +"databricks": "fcfd1f4cfe959c3d88cf43c4", +"duckdb": "3533f91995bca270f191503d", +"generic": "3533f91995bca270f191503d", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "6c03a3450ea4742ee7396e3c", +"postgres": "3533f91995bca270f191503d", +"postgresql": "3533f91995bca270f191503d", +"snowflake": "3533f91995bca270f191503d", +"tsql": "3533f91995bca270f191503d" +} +], +[ +"type", +{ +"DuckDB": "c2700ca3573352821e09af03", +"None": "c2700ca3573352821e09af03", +"bigquery": "a428302e4848ffe877284c84", +"databricks": "c2700ca3573352821e09af03", +"duckdb": "c2700ca3573352821e09af03", +"generic": "c2700ca3573352821e09af03", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "c2700ca3573352821e09af03", +"postgres": "c2700ca3573352821e09af03", +"postgresql": "c2700ca3573352821e09af03", +"snowflake": "652ff8b21f638eac8fdc46c5", +"tsql": "e80839f7b11a9775b7596b50" +} +], +[ +"type", +{ +"DuckDB": "eea9a25a6fbf8e049a445513", +"None": "eea9a25a6fbf8e049a445513", +"bigquery": "eea9a25a6fbf8e049a445513", +"databricks": "eea9a25a6fbf8e049a445513", +"duckdb": "eea9a25a6fbf8e049a445513", +"generic": "eea9a25a6fbf8e049a445513", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "eea9a25a6fbf8e049a445513", +"postgres": "eea9a25a6fbf8e049a445513", +"postgresql": "eea9a25a6fbf8e049a445513", +"snowflake": "eea9a25a6fbf8e049a445513", +"tsql": "eea9a25a6fbf8e049a445513" +} +], +[ +"type", +{ +"DuckDB": "251aba3fef503ce64556c701", +"None": "251aba3fef503ce64556c701", +"bigquery": "c50a316d091c821866e4bfba", +"databricks": "251aba3fef503ce64556c701", +"duckdb": "251aba3fef503ce64556c701", +"generic": "251aba3fef503ce64556c701", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "251aba3fef503ce64556c701", +"postgres": "b7d6fc051a3c1ea6deb29ff4", +"postgresql": "b7d6fc051a3c1ea6deb29ff4", +"snowflake": "251aba3fef503ce64556c701", +"tsql": "e3bc1b8bad22d8104417b00f" +} +], +[ +"type", +{ +"DuckDB": "110327dc45eac0e8d54a96dc", +"None": "110327dc45eac0e8d54a96dc", +"bigquery": "1a804f317a3e9a0016925b04", +"databricks": "1a804f317a3e9a0016925b04", +"duckdb": "110327dc45eac0e8d54a96dc", +"generic": "110327dc45eac0e8d54a96dc", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "1a804f317a3e9a0016925b04", +"postgres": "110327dc45eac0e8d54a96dc", +"postgresql": "110327dc45eac0e8d54a96dc", +"snowflake": "110327dc45eac0e8d54a96dc", +"tsql": "110327dc45eac0e8d54a96dc" +} +], +[ +"type", +{ +"DuckDB": "d6e37cd37419bfb26e09b080", +"None": "d6e37cd37419bfb26e09b080", +"bigquery": "d6e37cd37419bfb26e09b080", +"databricks": "d6e37cd37419bfb26e09b080", +"duckdb": "d6e37cd37419bfb26e09b080", +"generic": "d6e37cd37419bfb26e09b080", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "d6e37cd37419bfb26e09b080", +"postgres": "d6e37cd37419bfb26e09b080", +"postgresql": "d6e37cd37419bfb26e09b080", +"snowflake": "d6e37cd37419bfb26e09b080", +"tsql": "d6e37cd37419bfb26e09b080" +} +], +[ +"type", +{ +"DuckDB": "e46d4be44ab9e500e9190d26", +"None": "e46d4be44ab9e500e9190d26", +"bigquery": "e6ffdece2977be55da73b59a", +"databricks": "e46d4be44ab9e500e9190d26", +"duckdb": "e46d4be44ab9e500e9190d26", +"generic": "e46d4be44ab9e500e9190d26", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "e46d4be44ab9e500e9190d26", +"postgres": "e46d4be44ab9e500e9190d26", +"postgresql": "e46d4be44ab9e500e9190d26", +"snowflake": "e46d4be44ab9e500e9190d26", +"tsql": "e46d4be44ab9e500e9190d26" +} +], +[ +"type", +{ +"DuckDB": "0703bf71a54942bdaa28406e", +"None": "0703bf71a54942bdaa28406e", +"bigquery": "a428302e4848ffe877284c84", +"databricks": "0703bf71a54942bdaa28406e", +"duckdb": "0703bf71a54942bdaa28406e", +"generic": "0703bf71a54942bdaa28406e", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "0703bf71a54942bdaa28406e", +"postgres": "0703bf71a54942bdaa28406e", +"postgresql": "0703bf71a54942bdaa28406e", +"snowflake": "652ff8b21f638eac8fdc46c5", +"tsql": "441f377c46ddc162ec0a5976" +} +], +[ +"type", +{ +"DuckDB": "e060b5a5a8e9774b580d58d3", +"None": "e060b5a5a8e9774b580d58d3", +"bigquery": "319a9fbb02ed503eb114164b", +"databricks": "319a9fbb02ed503eb114164b", +"duckdb": "e060b5a5a8e9774b580d58d3", +"generic": "e060b5a5a8e9774b580d58d3", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "319a9fbb02ed503eb114164b", +"postgres": "e060b5a5a8e9774b580d58d3", +"postgresql": "e060b5a5a8e9774b580d58d3", +"snowflake": "e060b5a5a8e9774b580d58d3", +"tsql": "e060b5a5a8e9774b580d58d3" +} +], +[ +"type", +{ +"DuckDB": "c6654395c62d21b415299f72", +"None": "c6654395c62d21b415299f72", +"bigquery": "0712c33a016f7dd6a37ee011", +"databricks": "c6654395c62d21b415299f72", +"duckdb": "c6654395c62d21b415299f72", +"generic": "c6654395c62d21b415299f72", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "2978a8fe925c7f93c6e9fcfb", +"postgres": "c6654395c62d21b415299f72", +"postgresql": "c6654395c62d21b415299f72", +"snowflake": "0712c33a016f7dd6a37ee011", +"tsql": "c6654395c62d21b415299f72" +} +], +[ +"type", +{ +"DuckDB": "b0fba0f56f0cfe71621226b5", +"None": "b0fba0f56f0cfe71621226b5", +"bigquery": "f7fffd42e662ab4655dceb3b", +"databricks": "94b22f27d5086eaa9bb3eff5", +"duckdb": "b0fba0f56f0cfe71621226b5", +"generic": "b0fba0f56f0cfe71621226b5", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "b0fba0f56f0cfe71621226b5", +"postgres": "b0fba0f56f0cfe71621226b5", +"postgresql": "b0fba0f56f0cfe71621226b5", +"snowflake": "ffdce71ffba2fc524a0e9de5", +"tsql": "b0fba0f56f0cfe71621226b5" +} +], +[ +"type", +{ +"DuckDB": "63c80b5d8e861216f0c45bfd", +"None": "d227b99a82e505d599c2ed8a", +"bigquery": "aa04c66b4fed5190c90308fd", +"databricks": "d227b99a82e505d599c2ed8a", +"duckdb": "63c80b5d8e861216f0c45bfd", +"generic": "d227b99a82e505d599c2ed8a", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "d227b99a82e505d599c2ed8a", +"postgres": "d227b99a82e505d599c2ed8a", +"postgresql": "d227b99a82e505d599c2ed8a", +"snowflake": "d227b99a82e505d599c2ed8a", +"tsql": "d227b99a82e505d599c2ed8a" +} +], +[ +"type", +{ +"DuckDB": "c2700ca3573352821e09af03", +"None": "c2700ca3573352821e09af03", +"bigquery": "a428302e4848ffe877284c84", +"databricks": "c2700ca3573352821e09af03", +"duckdb": "c2700ca3573352821e09af03", +"generic": "c2700ca3573352821e09af03", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "c2700ca3573352821e09af03", +"postgres": "c2700ca3573352821e09af03", +"postgresql": "c2700ca3573352821e09af03", +"snowflake": "652ff8b21f638eac8fdc46c5", +"tsql": "e80839f7b11a9775b7596b50" +} +], +[ +"type", +{ +"DuckDB": "3915f3f73328f0838497b2d5", +"None": "3915f3f73328f0838497b2d5", +"bigquery": "946d5ee30ab7469c57d850df", +"databricks": "3915f3f73328f0838497b2d5", +"duckdb": "3915f3f73328f0838497b2d5", +"generic": "3915f3f73328f0838497b2d5", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "3915f3f73328f0838497b2d5", +"postgres": "3915f3f73328f0838497b2d5", +"postgresql": "3915f3f73328f0838497b2d5", +"snowflake": "f43dac38f34a1c0618a3f812", +"tsql": "3915f3f73328f0838497b2d5" +} +], +[ +"type", +{ +"DuckDB": "0703bf71a54942bdaa28406e", +"None": "0703bf71a54942bdaa28406e", +"bigquery": "a428302e4848ffe877284c84", +"databricks": "0703bf71a54942bdaa28406e", +"duckdb": "0703bf71a54942bdaa28406e", +"generic": "0703bf71a54942bdaa28406e", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "0703bf71a54942bdaa28406e", +"postgres": "0703bf71a54942bdaa28406e", +"postgresql": "0703bf71a54942bdaa28406e", +"snowflake": "652ff8b21f638eac8fdc46c5", +"tsql": "441f377c46ddc162ec0a5976" +} +], +[ +"type", +{ +"DuckDB": "b55b02912e30e27dcb40ad93", +"None": "b55b02912e30e27dcb40ad93", +"bigquery": "b55b02912e30e27dcb40ad93", +"databricks": "b55b02912e30e27dcb40ad93", +"duckdb": "b55b02912e30e27dcb40ad93", +"generic": "b55b02912e30e27dcb40ad93", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "b55b02912e30e27dcb40ad93", +"postgres": "b55b02912e30e27dcb40ad93", +"postgresql": "b55b02912e30e27dcb40ad93", +"snowflake": "b55b02912e30e27dcb40ad93", +"tsql": "b55b02912e30e27dcb40ad93" +} +], +[ +"type", +{ +"DuckDB": "e8cd7a4caa15ec2b6f990a1f", +"None": "1757eadf86c2a8956b520868", +"bigquery": "3688fe25b8bdff7eb938e6f9", +"databricks": "3688fe25b8bdff7eb938e6f9", +"duckdb": "e8cd7a4caa15ec2b6f990a1f", +"generic": "1757eadf86c2a8956b520868", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "3688fe25b8bdff7eb938e6f9", +"postgres": "e8cd7a4caa15ec2b6f990a1f", +"postgresql": "e8cd7a4caa15ec2b6f990a1f", +"snowflake": "fe491937bc4ec7b061f2be43", +"tsql": "3688fe25b8bdff7eb938e6f9" +} +], +[ +"type", +{ +"DuckDB": "c6106f30f23f392e17eadef4", +"None": "c6106f30f23f392e17eadef4", +"bigquery": "c6106f30f23f392e17eadef4", +"databricks": "c6106f30f23f392e17eadef4", +"duckdb": "c6106f30f23f392e17eadef4", +"generic": "c6106f30f23f392e17eadef4", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "c6106f30f23f392e17eadef4", +"postgres": "c6106f30f23f392e17eadef4", +"postgresql": "c6106f30f23f392e17eadef4", +"snowflake": "c6106f30f23f392e17eadef4", +"tsql": "c6106f30f23f392e17eadef4" +} +], +[ +"type", +{ +"DuckDB": "eb9c0f675dd300eb82500b21", +"None": "eb9c0f675dd300eb82500b21", +"bigquery": "b5c4d5044b2a6e70633f0d0a", +"databricks": "eb9c0f675dd300eb82500b21", +"duckdb": "eb9c0f675dd300eb82500b21", +"generic": "eb9c0f675dd300eb82500b21", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "eb9c0f675dd300eb82500b21", +"postgres": "eb9c0f675dd300eb82500b21", +"postgresql": "eb9c0f675dd300eb82500b21", +"snowflake": "4e24a80b20b9dee0cbbfac17", +"tsql": "eb9c0f675dd300eb82500b21" +} +], +[ +"type", +{ +"DuckDB": "3eb44072dafa3bef75c97b6a", +"None": "3eb44072dafa3bef75c97b6a", +"bigquery": "3eb44072dafa3bef75c97b6a", +"databricks": "3eb44072dafa3bef75c97b6a", +"duckdb": "3eb44072dafa3bef75c97b6a", +"generic": "3eb44072dafa3bef75c97b6a", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "3eb44072dafa3bef75c97b6a", +"postgres": "3eb44072dafa3bef75c97b6a", +"postgresql": "3eb44072dafa3bef75c97b6a", +"snowflake": "3eb44072dafa3bef75c97b6a", +"tsql": "3eb44072dafa3bef75c97b6a" +} +], +[ +"type", +{ +"DuckDB": "461923a0d34defd0c726d6e5", +"None": "461923a0d34defd0c726d6e5", +"bigquery": "b5c4d5044b2a6e70633f0d0a", +"databricks": "461923a0d34defd0c726d6e5", +"duckdb": "461923a0d34defd0c726d6e5", +"generic": "461923a0d34defd0c726d6e5", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "461923a0d34defd0c726d6e5", +"postgres": "461923a0d34defd0c726d6e5", +"postgresql": "461923a0d34defd0c726d6e5", +"snowflake": "461923a0d34defd0c726d6e5", +"tsql": "461923a0d34defd0c726d6e5" +} +], +[ +"type", +{ +"DuckDB": "d9315b336b73c3d8d4b6e9a3", +"None": "f2ed52f6bf46b4db9343551c", +"bigquery": "f2ed52f6bf46b4db9343551c", +"databricks": "f2ed52f6bf46b4db9343551c", +"duckdb": "d9315b336b73c3d8d4b6e9a3", +"generic": "f2ed52f6bf46b4db9343551c", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "f2ed52f6bf46b4db9343551c", +"postgres": "f2ed52f6bf46b4db9343551c", +"postgresql": "f2ed52f6bf46b4db9343551c", +"snowflake": "f2ed52f6bf46b4db9343551c", +"tsql": "f2ed52f6bf46b4db9343551c" +} +], +[ +"type", +{ +"DuckDB": "0960c90223e1eca15361360f", +"None": "0960c90223e1eca15361360f", +"bigquery": "0960c90223e1eca15361360f", +"databricks": "0960c90223e1eca15361360f", +"duckdb": "0960c90223e1eca15361360f", +"generic": "0960c90223e1eca15361360f", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "0960c90223e1eca15361360f", +"postgres": "0960c90223e1eca15361360f", +"postgresql": "0960c90223e1eca15361360f", +"snowflake": "0960c90223e1eca15361360f", +"tsql": "0960c90223e1eca15361360f" +} +], +[ +"type", +{ +"DuckDB": "e2879cf4770e7f48d2dd704a", +"None": "e2879cf4770e7f48d2dd704a", +"bigquery": "c9b810639795a7bfab91b98d", +"databricks": "e2879cf4770e7f48d2dd704a", +"duckdb": "e2879cf4770e7f48d2dd704a", +"generic": "e2879cf4770e7f48d2dd704a", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "e2879cf4770e7f48d2dd704a", +"postgres": "e2879cf4770e7f48d2dd704a", +"postgresql": "e2879cf4770e7f48d2dd704a", +"snowflake": "97a20344d811fb77c7690863", +"tsql": "e2879cf4770e7f48d2dd704a" +} +], +[ +"type", +{ +"DuckDB": "11d8d18c76077fddaf1b264f", +"None": "11d8d18c76077fddaf1b264f", +"bigquery": "11d8d18c76077fddaf1b264f", +"databricks": "11d8d18c76077fddaf1b264f", +"duckdb": "11d8d18c76077fddaf1b264f", +"generic": "11d8d18c76077fddaf1b264f", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "11d8d18c76077fddaf1b264f", +"postgres": "11d8d18c76077fddaf1b264f", +"postgresql": "11d8d18c76077fddaf1b264f", +"snowflake": "11d8d18c76077fddaf1b264f", +"tsql": "11d8d18c76077fddaf1b264f" +} +], +[ +"type", +{ +"DuckDB": "0b9d9879e289ea9a6a3e3e70", +"None": "0b9d9879e289ea9a6a3e3e70", +"bigquery": "0b9d9879e289ea9a6a3e3e70", +"databricks": "0b9d9879e289ea9a6a3e3e70", +"duckdb": "0b9d9879e289ea9a6a3e3e70", +"generic": "0b9d9879e289ea9a6a3e3e70", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "0b9d9879e289ea9a6a3e3e70", +"postgres": "0b9d9879e289ea9a6a3e3e70", +"postgresql": "0b9d9879e289ea9a6a3e3e70", +"snowflake": "0b9d9879e289ea9a6a3e3e70", +"tsql": "0b9d9879e289ea9a6a3e3e70" +} +], +[ +"type", +{ +"DuckDB": "8e484ef176389314b9fd318e", +"None": "8e484ef176389314b9fd318e", +"bigquery": "8e484ef176389314b9fd318e", +"databricks": "8e484ef176389314b9fd318e", +"duckdb": "8e484ef176389314b9fd318e", +"generic": "8e484ef176389314b9fd318e", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "8e484ef176389314b9fd318e", +"postgres": "8e484ef176389314b9fd318e", +"postgresql": "8e484ef176389314b9fd318e", +"snowflake": "8e484ef176389314b9fd318e", +"tsql": "8e484ef176389314b9fd318e" +} +], +[ +"type", +{ +"DuckDB": "41a317d0625259b54aa1dc94", +"None": "41a317d0625259b54aa1dc94", +"bigquery": "41a317d0625259b54aa1dc94", +"databricks": "41a317d0625259b54aa1dc94", +"duckdb": "41a317d0625259b54aa1dc94", +"generic": "41a317d0625259b54aa1dc94", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "41a317d0625259b54aa1dc94", +"postgres": "41a317d0625259b54aa1dc94", +"postgresql": "41a317d0625259b54aa1dc94", +"snowflake": "41a317d0625259b54aa1dc94", +"tsql": "41a317d0625259b54aa1dc94" +} +], +[ +"type", +{ +"DuckDB": "f01435c3d6e460ffd86479dc", +"None": "f01435c3d6e460ffd86479dc", +"bigquery": "99d6d9358db2ff349db17bb6", +"databricks": "72d1587b51c517b53f52a2d8", +"duckdb": "f01435c3d6e460ffd86479dc", +"generic": "f01435c3d6e460ffd86479dc", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "f01435c3d6e460ffd86479dc", +"postgres": "f01435c3d6e460ffd86479dc", +"postgresql": "f01435c3d6e460ffd86479dc", +"snowflake": "143dfed5733eda8a7f6ed075", +"tsql": "f01435c3d6e460ffd86479dc" +} +], +[ +"type", +{ +"DuckDB": "23ee196b7bd6039855a1460f", +"None": "23ee196b7bd6039855a1460f", +"bigquery": "23ee196b7bd6039855a1460f", +"databricks": "23ee196b7bd6039855a1460f", +"duckdb": "23ee196b7bd6039855a1460f", +"generic": "23ee196b7bd6039855a1460f", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "23ee196b7bd6039855a1460f", +"postgres": "23ee196b7bd6039855a1460f", +"postgresql": "23ee196b7bd6039855a1460f", +"snowflake": "5d25d5e13f81700741695ed4", +"tsql": "23ee196b7bd6039855a1460f" +} +], +[ +"type", +{ +"DuckDB": "3e2cff9b165a6eaf1c043756", +"None": "77fe8e560c0d80d58e64a3ac", +"bigquery": "77fe8e560c0d80d58e64a3ac", +"databricks": "a8b5c14299c94dad25520df6", +"duckdb": "3e2cff9b165a6eaf1c043756", +"generic": "77fe8e560c0d80d58e64a3ac", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "6c03a3450ea4742ee7396e3c", +"postgres": "545b06c80ff7b812dafe5136", +"postgresql": "545b06c80ff7b812dafe5136", +"snowflake": "2a7a3265ae4026b435644d0e", +"tsql": "d1dc9a140dbe2eb1874c6ad7" +} +], +[ +"type", +{ +"DuckDB": "29739921db4d47abc1ac18c7", +"None": "29739921db4d47abc1ac18c7", +"bigquery": "01d1b160c1768fa1cd4b2e45", +"databricks": "adbb06204fd66d8071c3dbc6", +"duckdb": "29739921db4d47abc1ac18c7", +"generic": "29739921db4d47abc1ac18c7", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "29739921db4d47abc1ac18c7", +"postgres": "29739921db4d47abc1ac18c7", +"postgresql": "29739921db4d47abc1ac18c7", +"snowflake": "216a7f0ead009a087eea4e1c", +"tsql": "561143bc26e834af800f173b" +} +], +[ +"type", +{ +"DuckDB": "3f71ab5f3c1c040da96f2cec", +"None": "3f71ab5f3c1c040da96f2cec", +"bigquery": "3f71ab5f3c1c040da96f2cec", +"databricks": "3f71ab5f3c1c040da96f2cec", +"duckdb": "3f71ab5f3c1c040da96f2cec", +"generic": "3f71ab5f3c1c040da96f2cec", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "3f71ab5f3c1c040da96f2cec", +"postgres": "3f71ab5f3c1c040da96f2cec", +"postgresql": "3f71ab5f3c1c040da96f2cec", +"snowflake": "3f71ab5f3c1c040da96f2cec", +"tsql": "3f71ab5f3c1c040da96f2cec" +} +], +[ +"type", +{ +"DuckDB": "f15c56475abfc73488abe63b", +"None": "f15c56475abfc73488abe63b", +"bigquery": "a428302e4848ffe877284c84", +"databricks": "f15c56475abfc73488abe63b", +"duckdb": "f15c56475abfc73488abe63b", +"generic": "f15c56475abfc73488abe63b", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "f15c56475abfc73488abe63b", +"postgres": "f15c56475abfc73488abe63b", +"postgresql": "f15c56475abfc73488abe63b", +"snowflake": "652ff8b21f638eac8fdc46c5", +"tsql": "f15c56475abfc73488abe63b" +} +], +[ +"type", +{ +"DuckDB": "669084d1ea704ae5b8ee05c2", +"None": "669084d1ea704ae5b8ee05c2", +"bigquery": "669084d1ea704ae5b8ee05c2", +"databricks": "669084d1ea704ae5b8ee05c2", +"duckdb": "669084d1ea704ae5b8ee05c2", +"generic": "669084d1ea704ae5b8ee05c2", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "669084d1ea704ae5b8ee05c2", +"postgres": "669084d1ea704ae5b8ee05c2", +"postgresql": "669084d1ea704ae5b8ee05c2", +"snowflake": "669084d1ea704ae5b8ee05c2", +"tsql": "669084d1ea704ae5b8ee05c2" +} +], +[ +"type", +{ +"DuckDB": "38b2ec94bf02be40007ce525", +"None": "38b2ec94bf02be40007ce525", +"bigquery": "38b2ec94bf02be40007ce525", +"databricks": "38b2ec94bf02be40007ce525", +"duckdb": "38b2ec94bf02be40007ce525", +"generic": "38b2ec94bf02be40007ce525", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "38b2ec94bf02be40007ce525", +"postgres": "38b2ec94bf02be40007ce525", +"postgresql": "38b2ec94bf02be40007ce525", +"snowflake": "38b2ec94bf02be40007ce525", +"tsql": "38b2ec94bf02be40007ce525" +} +], +[ +"type", +{ +"DuckDB": "53ea41ce10b9fa682ddf305d", +"None": "a1176e5228f8200c23e7a0a7", +"bigquery": "2795066c9a71fa3e3780c73b", +"databricks": "61058ba40f23266ededb040f", +"duckdb": "53ea41ce10b9fa682ddf305d", +"generic": "a1176e5228f8200c23e7a0a7", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "6c03a3450ea4742ee7396e3c", +"postgres": "a09c2bcd944462f73dd87c2d", +"postgresql": "a09c2bcd944462f73dd87c2d", +"snowflake": "9553636ef19ebb7706dabb5f", +"tsql": "d1dc9a140dbe2eb1874c6ad7" +} +], +[ +"type", +{ +"DuckDB": "66078c43faec49916ed11546", +"None": "66078c43faec49916ed11546", +"bigquery": "66078c43faec49916ed11546", +"databricks": "66078c43faec49916ed11546", +"duckdb": "66078c43faec49916ed11546", +"generic": "66078c43faec49916ed11546", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "66078c43faec49916ed11546", +"postgres": "66078c43faec49916ed11546", +"postgresql": "66078c43faec49916ed11546", +"snowflake": "66078c43faec49916ed11546", +"tsql": "66078c43faec49916ed11546" +} +], +[ +"type", +{ +"DuckDB": "cea3ac691106cc77e45d9414", +"None": "cea3ac691106cc77e45d9414", +"bigquery": "cea3ac691106cc77e45d9414", +"databricks": "cea3ac691106cc77e45d9414", +"duckdb": "cea3ac691106cc77e45d9414", +"generic": "cea3ac691106cc77e45d9414", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "cea3ac691106cc77e45d9414", +"postgres": "cea3ac691106cc77e45d9414", +"postgresql": "cea3ac691106cc77e45d9414", +"snowflake": "cea3ac691106cc77e45d9414", +"tsql": "cea3ac691106cc77e45d9414" +} +], +[ +"type", +{ +"DuckDB": "aae2b1fe6f2d9807ecde412b", +"None": "aae2b1fe6f2d9807ecde412b", +"bigquery": "e1c36a5cdd2427ff2b089ac9", +"databricks": "aae2b1fe6f2d9807ecde412b", +"duckdb": "aae2b1fe6f2d9807ecde412b", +"generic": "aae2b1fe6f2d9807ecde412b", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "aae2b1fe6f2d9807ecde412b", +"postgres": "aae2b1fe6f2d9807ecde412b", +"postgresql": "aae2b1fe6f2d9807ecde412b", +"snowflake": "aae2b1fe6f2d9807ecde412b", +"tsql": "aae2b1fe6f2d9807ecde412b" +} +], +[ +"type", +{ +"DuckDB": "937a574f550c49d90b6065cc", +"None": "937a574f550c49d90b6065cc", +"bigquery": "937a574f550c49d90b6065cc", +"databricks": "937a574f550c49d90b6065cc", +"duckdb": "937a574f550c49d90b6065cc", +"generic": "937a574f550c49d90b6065cc", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "937a574f550c49d90b6065cc", +"postgres": "937a574f550c49d90b6065cc", +"postgresql": "937a574f550c49d90b6065cc", +"snowflake": "937a574f550c49d90b6065cc", +"tsql": "937a574f550c49d90b6065cc" +} +], +[ +"type", +{ +"DuckDB": "ce156bc49d99761b01d1c550", +"None": "ce156bc49d99761b01d1c550", +"bigquery": "ce156bc49d99761b01d1c550", +"databricks": "ce156bc49d99761b01d1c550", +"duckdb": "ce156bc49d99761b01d1c550", +"generic": "ce156bc49d99761b01d1c550", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "ce156bc49d99761b01d1c550", +"postgres": "ce156bc49d99761b01d1c550", +"postgresql": "ce156bc49d99761b01d1c550", +"snowflake": "ce156bc49d99761b01d1c550", +"tsql": "ce156bc49d99761b01d1c550" +} +], +[ +"type", +{ +"DuckDB": "2cc8cf0f153f72622d15048c", +"None": "2cc8cf0f153f72622d15048c", +"bigquery": "2cc8cf0f153f72622d15048c", +"databricks": "2cc8cf0f153f72622d15048c", +"duckdb": "2cc8cf0f153f72622d15048c", +"generic": "2cc8cf0f153f72622d15048c", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "2cc8cf0f153f72622d15048c", +"postgres": "2cc8cf0f153f72622d15048c", +"postgresql": "2cc8cf0f153f72622d15048c", +"snowflake": "2cc8cf0f153f72622d15048c", +"tsql": "2cc8cf0f153f72622d15048c" +} +], +[ +"type", +{ +"DuckDB": "ba72bc162859c1861cc127e7", +"None": "ba72bc162859c1861cc127e7", +"bigquery": "ba72bc162859c1861cc127e7", +"databricks": "ba72bc162859c1861cc127e7", +"duckdb": "ba72bc162859c1861cc127e7", +"generic": "ba72bc162859c1861cc127e7", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "ba72bc162859c1861cc127e7", +"postgres": "ba72bc162859c1861cc127e7", +"postgresql": "ba72bc162859c1861cc127e7", +"snowflake": "ba72bc162859c1861cc127e7", +"tsql": "ba72bc162859c1861cc127e7" +} +], +[ +"type", +{ +"DuckDB": "1eb7fb4e8cf75773c5573562", +"None": "1eb7fb4e8cf75773c5573562", +"bigquery": "c9b810639795a7bfab91b98d", +"databricks": "1eb7fb4e8cf75773c5573562", +"duckdb": "1eb7fb4e8cf75773c5573562", +"generic": "1eb7fb4e8cf75773c5573562", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "1eb7fb4e8cf75773c5573562", +"postgres": "1eb7fb4e8cf75773c5573562", +"postgresql": "1eb7fb4e8cf75773c5573562", +"snowflake": "97a20344d811fb77c7690863", +"tsql": "1eb7fb4e8cf75773c5573562" +} +], +[ +"type", +{ +"DuckDB": "c2a3a3c3789aeea50e8c4f35", +"None": "c2a3a3c3789aeea50e8c4f35", +"bigquery": "c2a3a3c3789aeea50e8c4f35", +"databricks": "c2a3a3c3789aeea50e8c4f35", +"duckdb": "c2a3a3c3789aeea50e8c4f35", +"generic": "c2a3a3c3789aeea50e8c4f35", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "c2a3a3c3789aeea50e8c4f35", +"postgres": "c2a3a3c3789aeea50e8c4f35", +"postgresql": "c2a3a3c3789aeea50e8c4f35", +"snowflake": "c2a3a3c3789aeea50e8c4f35", +"tsql": "c2a3a3c3789aeea50e8c4f35" +} +], +[ +"type", +{ +"DuckDB": "16c4b7f3bdc7c21a00a78838", +"None": "054898738769701df3abbf2e", +"bigquery": "054898738769701df3abbf2e", +"databricks": "054898738769701df3abbf2e", +"duckdb": "16c4b7f3bdc7c21a00a78838", +"generic": "054898738769701df3abbf2e", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "054898738769701df3abbf2e", +"postgres": "054898738769701df3abbf2e", +"postgresql": "054898738769701df3abbf2e", +"snowflake": "054898738769701df3abbf2e", +"tsql": "054898738769701df3abbf2e" +} +], +[ +"type", +{ +"DuckDB": "b0b09c4a6f7570ece56f59ce", +"None": "b0b09c4a6f7570ece56f59ce", +"bigquery": "d9a4e245156e760303573500", +"databricks": "e3bc1b8bad22d8104417b00f", +"duckdb": "b0b09c4a6f7570ece56f59ce", +"generic": "b0b09c4a6f7570ece56f59ce", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "355e032cc5c0f24695836b3d", +"postgres": "b0b09c4a6f7570ece56f59ce", +"postgresql": "b0b09c4a6f7570ece56f59ce", +"snowflake": "355e032cc5c0f24695836b3d", +"tsql": "b0b09c4a6f7570ece56f59ce" +} +], +[ +"type", +{ +"DuckDB": "e8a5e051bb567983c365b3fd", +"None": "e8a5e051bb567983c365b3fd", +"bigquery": "88f7cced71c11944260bb54a", +"databricks": "e8a5e051bb567983c365b3fd", +"duckdb": "e8a5e051bb567983c365b3fd", +"generic": "e8a5e051bb567983c365b3fd", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "e8a5e051bb567983c365b3fd", +"postgres": "e8a5e051bb567983c365b3fd", +"postgresql": "e8a5e051bb567983c365b3fd", +"snowflake": "b210f8eb26c37b422f786c6b", +"tsql": "e8a5e051bb567983c365b3fd" +} +], +[ +"type", +{ +"DuckDB": "50563fc19d4ed8ceb4f5e8e4", +"None": "50563fc19d4ed8ceb4f5e8e4", +"bigquery": "b871f531d5fa48f344a9756b", +"databricks": "207b6dc5f2a2547137393792", +"duckdb": "50563fc19d4ed8ceb4f5e8e4", +"generic": "50563fc19d4ed8ceb4f5e8e4", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "50563fc19d4ed8ceb4f5e8e4", +"postgres": "8770742a4fe26efe6bd47a00", +"postgresql": "8770742a4fe26efe6bd47a00", +"snowflake": "a4cd3eca76c356ecd633fe7b", +"tsql": "50563fc19d4ed8ceb4f5e8e4" +} +], +[ +"type", +{ +"DuckDB": "19a1a80ffc06169f32694de8", +"None": "19a1a80ffc06169f32694de8", +"bigquery": "19a1a80ffc06169f32694de8", +"databricks": "19a1a80ffc06169f32694de8", +"duckdb": "19a1a80ffc06169f32694de8", +"generic": "19a1a80ffc06169f32694de8", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "19a1a80ffc06169f32694de8", +"postgres": "19a1a80ffc06169f32694de8", +"postgresql": "19a1a80ffc06169f32694de8", +"snowflake": "19a1a80ffc06169f32694de8", +"tsql": "19a1a80ffc06169f32694de8" +} +], +[ +"type", +{ +"DuckDB": "3f71ab5f3c1c040da96f2cec", +"None": "3f71ab5f3c1c040da96f2cec", +"bigquery": "3f71ab5f3c1c040da96f2cec", +"databricks": "3f71ab5f3c1c040da96f2cec", +"duckdb": "3f71ab5f3c1c040da96f2cec", +"generic": "3f71ab5f3c1c040da96f2cec", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "3f71ab5f3c1c040da96f2cec", +"postgres": "3f71ab5f3c1c040da96f2cec", +"postgresql": "3f71ab5f3c1c040da96f2cec", +"snowflake": "3f71ab5f3c1c040da96f2cec", +"tsql": "3f71ab5f3c1c040da96f2cec" +} +], +[ +"type", +{ +"DuckDB": "77ffdb80029bd6e2cca768ad", +"None": "77ffdb80029bd6e2cca768ad", +"bigquery": "77ffdb80029bd6e2cca768ad", +"databricks": "77ffdb80029bd6e2cca768ad", +"duckdb": "77ffdb80029bd6e2cca768ad", +"generic": "77ffdb80029bd6e2cca768ad", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "77ffdb80029bd6e2cca768ad", +"postgres": "77ffdb80029bd6e2cca768ad", +"postgresql": "77ffdb80029bd6e2cca768ad", +"snowflake": "77ffdb80029bd6e2cca768ad", +"tsql": "77ffdb80029bd6e2cca768ad" +} +], +[ +"type", +{ +"DuckDB": "c37de6584758b2433c289aee", +"None": "c37de6584758b2433c289aee", +"bigquery": "c37de6584758b2433c289aee", +"databricks": "c37de6584758b2433c289aee", +"duckdb": "c37de6584758b2433c289aee", +"generic": "c37de6584758b2433c289aee", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "c37de6584758b2433c289aee", +"postgres": "c37de6584758b2433c289aee", +"postgresql": "c37de6584758b2433c289aee", +"snowflake": "c37de6584758b2433c289aee", +"tsql": "c37de6584758b2433c289aee" +} +], +[ +"type", +{ +"DuckDB": "555111267818cbd3d0b07105", +"None": "555111267818cbd3d0b07105", +"bigquery": "555111267818cbd3d0b07105", +"databricks": "555111267818cbd3d0b07105", +"duckdb": "555111267818cbd3d0b07105", +"generic": "555111267818cbd3d0b07105", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "555111267818cbd3d0b07105", +"postgres": "555111267818cbd3d0b07105", +"postgresql": "555111267818cbd3d0b07105", +"snowflake": "555111267818cbd3d0b07105", +"tsql": "555111267818cbd3d0b07105" +} +], +[ +"type", +{ +"DuckDB": "2bfa352725f9d8a91250f75e", +"None": "2bfa352725f9d8a91250f75e", +"bigquery": "2bfa352725f9d8a91250f75e", +"databricks": "2bfa352725f9d8a91250f75e", +"duckdb": "2bfa352725f9d8a91250f75e", +"generic": "2bfa352725f9d8a91250f75e", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "2bfa352725f9d8a91250f75e", +"postgres": "2bfa352725f9d8a91250f75e", +"postgresql": "2bfa352725f9d8a91250f75e", +"snowflake": "2bfa352725f9d8a91250f75e", +"tsql": "2bfa352725f9d8a91250f75e" +} +], +[ +"type", +{ +"DuckDB": "42d4a23d9a52e79d0c3458d3", +"None": "3c0719ca5c83e0a20d0b0b42", +"bigquery": "3c0719ca5c83e0a20d0b0b42", +"databricks": "3c0719ca5c83e0a20d0b0b42", +"duckdb": "42d4a23d9a52e79d0c3458d3", +"generic": "3c0719ca5c83e0a20d0b0b42", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "3c0719ca5c83e0a20d0b0b42", +"postgres": "3c0719ca5c83e0a20d0b0b42", +"postgresql": "3c0719ca5c83e0a20d0b0b42", +"snowflake": "a3acd7ba35e81a800f967bd3", +"tsql": "3c0719ca5c83e0a20d0b0b42" +} +], +[ +"type", +{ +"DuckDB": "aae2b1fe6f2d9807ecde412b", +"None": "aae2b1fe6f2d9807ecde412b", +"bigquery": "e1c36a5cdd2427ff2b089ac9", +"databricks": "aae2b1fe6f2d9807ecde412b", +"duckdb": "aae2b1fe6f2d9807ecde412b", +"generic": "aae2b1fe6f2d9807ecde412b", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "aae2b1fe6f2d9807ecde412b", +"postgres": "aae2b1fe6f2d9807ecde412b", +"postgresql": "aae2b1fe6f2d9807ecde412b", +"snowflake": "aae2b1fe6f2d9807ecde412b", +"tsql": "aae2b1fe6f2d9807ecde412b" +} +], +[ +"type", +{ +"DuckDB": "2bfa352725f9d8a91250f75e", +"None": "2bfa352725f9d8a91250f75e", +"bigquery": "2bfa352725f9d8a91250f75e", +"databricks": "2bfa352725f9d8a91250f75e", +"duckdb": "2bfa352725f9d8a91250f75e", +"generic": "2bfa352725f9d8a91250f75e", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "2bfa352725f9d8a91250f75e", +"postgres": "2bfa352725f9d8a91250f75e", +"postgresql": "2bfa352725f9d8a91250f75e", +"snowflake": "2bfa352725f9d8a91250f75e", +"tsql": "2bfa352725f9d8a91250f75e" +} +], +[ +"type", +{ +"DuckDB": "919b7ec6a7b49d8527b784cd", +"None": "919b7ec6a7b49d8527b784cd", +"bigquery": "204206d1d1eecf007966cc5b", +"databricks": "e3bc1b8bad22d8104417b00f", +"duckdb": "919b7ec6a7b49d8527b784cd", +"generic": "919b7ec6a7b49d8527b784cd", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "919b7ec6a7b49d8527b784cd", +"postgres": "a3b6b25265be330ec52a3322", +"postgresql": "a3b6b25265be330ec52a3322", +"snowflake": "919b7ec6a7b49d8527b784cd", +"tsql": "919b7ec6a7b49d8527b784cd" +} +], +[ +"type", +{ +"DuckDB": "a428302e4848ffe877284c84", +"None": "a428302e4848ffe877284c84", +"bigquery": "a428302e4848ffe877284c84", +"databricks": "a428302e4848ffe877284c84", +"duckdb": "a428302e4848ffe877284c84", +"generic": "a428302e4848ffe877284c84", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "a428302e4848ffe877284c84", +"postgres": "a428302e4848ffe877284c84", +"postgresql": "a428302e4848ffe877284c84", +"snowflake": "652ff8b21f638eac8fdc46c5", +"tsql": "a428302e4848ffe877284c84" +} +], +[ +"type", +{ +"DuckDB": "5fd024c2193505b62de9c162", +"None": "5fd024c2193505b62de9c162", +"bigquery": "5fd024c2193505b62de9c162", +"databricks": "5fd024c2193505b62de9c162", +"duckdb": "5fd024c2193505b62de9c162", +"generic": "5fd024c2193505b62de9c162", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "5fd024c2193505b62de9c162", +"postgres": "5fd024c2193505b62de9c162", +"postgresql": "5fd024c2193505b62de9c162", +"snowflake": "5fd024c2193505b62de9c162", +"tsql": "5fd024c2193505b62de9c162" +} +], +[ +"type", +{ +"DuckDB": "4b356542044f1267fcfc487a", +"None": "4b356542044f1267fcfc487a", +"bigquery": "4b356542044f1267fcfc487a", +"databricks": "4b356542044f1267fcfc487a", +"duckdb": "4b356542044f1267fcfc487a", +"generic": "4b356542044f1267fcfc487a", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "4b356542044f1267fcfc487a", +"postgres": "4b356542044f1267fcfc487a", +"postgresql": "4b356542044f1267fcfc487a", +"snowflake": "4b356542044f1267fcfc487a", +"tsql": "4b356542044f1267fcfc487a" +} +], +[ +"type", +{ +"DuckDB": "ebc821a95b9286e22c2b26d0", +"None": "ebc821a95b9286e22c2b26d0", +"bigquery": "19a1a80ffc06169f32694de8", +"databricks": "ebc821a95b9286e22c2b26d0", +"duckdb": "ebc821a95b9286e22c2b26d0", +"generic": "ebc821a95b9286e22c2b26d0", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "ebc821a95b9286e22c2b26d0", +"postgres": "ebc821a95b9286e22c2b26d0", +"postgresql": "ebc821a95b9286e22c2b26d0", +"snowflake": "ebc821a95b9286e22c2b26d0", +"tsql": "ebc821a95b9286e22c2b26d0" +} +], +[ +"type", +{ +"DuckDB": "b0791f9f270e764eeeb6fb8e", +"None": "c7c38fdeaeb7858a44976f1d", +"bigquery": "cfb4a49a57197b0df1b2e905", +"databricks": "6bd27be6a47ef34ec1defbad", +"duckdb": "b0791f9f270e764eeeb6fb8e", +"generic": "c7c38fdeaeb7858a44976f1d", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "c7c38fdeaeb7858a44976f1d", +"postgres": "4d7604d41e3585ec187dec82", +"postgresql": "4d7604d41e3585ec187dec82", +"snowflake": "c7c38fdeaeb7858a44976f1d", +"tsql": "b0791f9f270e764eeeb6fb8e" +} +], +[ +"type", +{ +"DuckDB": "66bffd006fc7638db82257d2", +"None": "66bffd006fc7638db82257d2", +"bigquery": "66bffd006fc7638db82257d2", +"databricks": "66bffd006fc7638db82257d2", +"duckdb": "66bffd006fc7638db82257d2", +"generic": "66bffd006fc7638db82257d2", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "66bffd006fc7638db82257d2", +"postgres": "66bffd006fc7638db82257d2", +"postgresql": "66bffd006fc7638db82257d2", +"snowflake": "66bffd006fc7638db82257d2", +"tsql": "66bffd006fc7638db82257d2" +} +], +[ +"type", +{ +"DuckDB": "f43dac38f34a1c0618a3f812", +"None": "f43dac38f34a1c0618a3f812", +"bigquery": "946d5ee30ab7469c57d850df", +"databricks": "f43dac38f34a1c0618a3f812", +"duckdb": "f43dac38f34a1c0618a3f812", +"generic": "f43dac38f34a1c0618a3f812", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "f43dac38f34a1c0618a3f812", +"postgres": "f43dac38f34a1c0618a3f812", +"postgresql": "f43dac38f34a1c0618a3f812", +"snowflake": "f43dac38f34a1c0618a3f812", +"tsql": "f43dac38f34a1c0618a3f812" +} +], +[ +"type", +{ +"DuckDB": "4c4563a9f306a1bb11e116d9", +"None": "4c4563a9f306a1bb11e116d9", +"bigquery": "23ee196b7bd6039855a1460f", +"databricks": "4c4563a9f306a1bb11e116d9", +"duckdb": "4c4563a9f306a1bb11e116d9", +"generic": "4c4563a9f306a1bb11e116d9", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "4c4563a9f306a1bb11e116d9", +"postgres": "4c4563a9f306a1bb11e116d9", +"postgresql": "4c4563a9f306a1bb11e116d9", +"snowflake": "5d25d5e13f81700741695ed4", +"tsql": "4c4563a9f306a1bb11e116d9" +} +], +[ +"type", +{ +"DuckDB": "52928fec41d9097d054cb63d", +"None": "52928fec41d9097d054cb63d", +"bigquery": "52928fec41d9097d054cb63d", +"databricks": "52928fec41d9097d054cb63d", +"duckdb": "52928fec41d9097d054cb63d", +"generic": "52928fec41d9097d054cb63d", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "52928fec41d9097d054cb63d", +"postgres": "52928fec41d9097d054cb63d", +"postgresql": "52928fec41d9097d054cb63d", +"snowflake": "52928fec41d9097d054cb63d", +"tsql": "52928fec41d9097d054cb63d" +} +], +[ +"type", +{ +"DuckDB": "787213ce6b6e210ded1d752c", +"None": "787213ce6b6e210ded1d752c", +"bigquery": "b1b23029bedaa16e2a6f8516", +"databricks": "787213ce6b6e210ded1d752c", +"duckdb": "787213ce6b6e210ded1d752c", +"generic": "787213ce6b6e210ded1d752c", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "787213ce6b6e210ded1d752c", +"postgres": "787213ce6b6e210ded1d752c", +"postgresql": "787213ce6b6e210ded1d752c", +"snowflake": "b561884132dbe7e42b719110", +"tsql": "787213ce6b6e210ded1d752c" +} +], +[ +"type", +{ +"DuckDB": "c6654395c62d21b415299f72", +"None": "c6654395c62d21b415299f72", +"bigquery": "0712c33a016f7dd6a37ee011", +"databricks": "c6654395c62d21b415299f72", +"duckdb": "c6654395c62d21b415299f72", +"generic": "c6654395c62d21b415299f72", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "2978a8fe925c7f93c6e9fcfb", +"postgres": "c6654395c62d21b415299f72", +"postgresql": "c6654395c62d21b415299f72", +"snowflake": "0712c33a016f7dd6a37ee011", +"tsql": "c6654395c62d21b415299f72" +} +], +[ +"type", +{ +"DuckDB": "2ffee1a4ca7dc4a711fc0d27", +"None": "2ffee1a4ca7dc4a711fc0d27", +"bigquery": "2ffee1a4ca7dc4a711fc0d27", +"databricks": "2ffee1a4ca7dc4a711fc0d27", +"duckdb": "2ffee1a4ca7dc4a711fc0d27", +"generic": "2ffee1a4ca7dc4a711fc0d27", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "2ffee1a4ca7dc4a711fc0d27", +"postgres": "2ffee1a4ca7dc4a711fc0d27", +"postgresql": "2ffee1a4ca7dc4a711fc0d27", +"snowflake": "2ffee1a4ca7dc4a711fc0d27", +"tsql": "2ffee1a4ca7dc4a711fc0d27" +} +], +[ +"type", +{ +"DuckDB": "c6889f2965db73017be6f6e7", +"None": "c6889f2965db73017be6f6e7", +"bigquery": "a428302e4848ffe877284c84", +"databricks": "c6889f2965db73017be6f6e7", +"duckdb": "c6889f2965db73017be6f6e7", +"generic": "c6889f2965db73017be6f6e7", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "c6889f2965db73017be6f6e7", +"postgres": "c6889f2965db73017be6f6e7", +"postgresql": "c6889f2965db73017be6f6e7", +"snowflake": "652ff8b21f638eac8fdc46c5", +"tsql": "c6889f2965db73017be6f6e7" +} +], +[ +"type", +{ +"DuckDB": "5abf4ec799a2ec32fb10da7e", +"None": "de89632e277dbc8c97115419", +"bigquery": "de89632e277dbc8c97115419", +"databricks": "de89632e277dbc8c97115419", +"duckdb": "5abf4ec799a2ec32fb10da7e", +"generic": "de89632e277dbc8c97115419", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "de89632e277dbc8c97115419", +"postgres": "de89632e277dbc8c97115419", +"postgresql": "de89632e277dbc8c97115419", +"snowflake": "4b356542044f1267fcfc487a", +"tsql": "de89632e277dbc8c97115419" +} +], +[ +"type", +{ +"DuckDB": "d61c83ef8bfdf043fa672cb5", +"None": "d61c83ef8bfdf043fa672cb5", +"bigquery": "c9b810639795a7bfab91b98d", +"databricks": "d61c83ef8bfdf043fa672cb5", +"duckdb": "d61c83ef8bfdf043fa672cb5", +"generic": "d61c83ef8bfdf043fa672cb5", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "d61c83ef8bfdf043fa672cb5", +"postgres": "d61c83ef8bfdf043fa672cb5", +"postgresql": "d61c83ef8bfdf043fa672cb5", +"snowflake": "97a20344d811fb77c7690863", +"tsql": "d61c83ef8bfdf043fa672cb5" +} +], +[ +"type", +{ +"DuckDB": "9c2cff8be7225cf79883ca65", +"None": "9c2cff8be7225cf79883ca65", +"bigquery": "9c2cff8be7225cf79883ca65", +"databricks": "901ac89f8d9ec18bd3a61e4b", +"duckdb": "9c2cff8be7225cf79883ca65", +"generic": "9c2cff8be7225cf79883ca65", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "901ac89f8d9ec18bd3a61e4b", +"postgres": "9c2cff8be7225cf79883ca65", +"postgresql": "9c2cff8be7225cf79883ca65", +"snowflake": "9c2cff8be7225cf79883ca65", +"tsql": "9c2cff8be7225cf79883ca65" +} +], +[ +"type", +{ +"DuckDB": "05ebf79d18b2ae4eaa41f450", +"None": "ab62f43260f32e2cf62666fc", +"bigquery": "aa04c66b4fed5190c90308fd", +"databricks": "ab62f43260f32e2cf62666fc", +"duckdb": "05ebf79d18b2ae4eaa41f450", +"generic": "ab62f43260f32e2cf62666fc", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "ab62f43260f32e2cf62666fc", +"postgres": "ab62f43260f32e2cf62666fc", +"postgresql": "ab62f43260f32e2cf62666fc", +"snowflake": "ab62f43260f32e2cf62666fc", +"tsql": "ab62f43260f32e2cf62666fc" +} +], +[ +"type", +{ +"DuckDB": "1eb7fb4e8cf75773c5573562", +"None": "1eb7fb4e8cf75773c5573562", +"bigquery": "c9b810639795a7bfab91b98d", +"databricks": "1eb7fb4e8cf75773c5573562", +"duckdb": "1eb7fb4e8cf75773c5573562", +"generic": "1eb7fb4e8cf75773c5573562", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "1eb7fb4e8cf75773c5573562", +"postgres": "1eb7fb4e8cf75773c5573562", +"postgresql": "1eb7fb4e8cf75773c5573562", +"snowflake": "97a20344d811fb77c7690863", +"tsql": "1eb7fb4e8cf75773c5573562" +} +], +[ +"type", +{ +"DuckDB": "97e5335218efead1a4226b8d", +"None": "97e5335218efead1a4226b8d", +"bigquery": "97e5335218efead1a4226b8d", +"databricks": "97e5335218efead1a4226b8d", +"duckdb": "97e5335218efead1a4226b8d", +"generic": "97e5335218efead1a4226b8d", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "97e5335218efead1a4226b8d", +"postgres": "97e5335218efead1a4226b8d", +"postgresql": "97e5335218efead1a4226b8d", +"snowflake": "97e5335218efead1a4226b8d", +"tsql": "97e5335218efead1a4226b8d" +} +], +[ +"type", +{ +"DuckDB": "ee47e1424cb01deb0cf51760", +"None": "ee47e1424cb01deb0cf51760", +"bigquery": "ee47e1424cb01deb0cf51760", +"databricks": "ee47e1424cb01deb0cf51760", +"duckdb": "ee47e1424cb01deb0cf51760", +"generic": "ee47e1424cb01deb0cf51760", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "ee47e1424cb01deb0cf51760", +"postgres": "ee47e1424cb01deb0cf51760", +"postgresql": "ee47e1424cb01deb0cf51760", +"snowflake": "ee47e1424cb01deb0cf51760", +"tsql": "ee47e1424cb01deb0cf51760" +} +], +[ +"type", +{ +"DuckDB": "2d4aea8dec5521e258596f3d", +"None": "2d4aea8dec5521e258596f3d", +"bigquery": "2d4aea8dec5521e258596f3d", +"databricks": "2d4aea8dec5521e258596f3d", +"duckdb": "2d4aea8dec5521e258596f3d", +"generic": "2d4aea8dec5521e258596f3d", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "2d4aea8dec5521e258596f3d", +"postgres": "f15c56475abfc73488abe63b", +"postgresql": "f15c56475abfc73488abe63b", +"snowflake": "652ff8b21f638eac8fdc46c5", +"tsql": "2d4aea8dec5521e258596f3d" +} +], +[ +"type", +{ +"DuckDB": "8917b70db141a02ac2e2bb1e", +"None": "8917b70db141a02ac2e2bb1e", +"bigquery": "8917b70db141a02ac2e2bb1e", +"databricks": "8917b70db141a02ac2e2bb1e", +"duckdb": "8917b70db141a02ac2e2bb1e", +"generic": "8917b70db141a02ac2e2bb1e", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "8917b70db141a02ac2e2bb1e", +"postgres": "8917b70db141a02ac2e2bb1e", +"postgresql": "8917b70db141a02ac2e2bb1e", +"snowflake": "8917b70db141a02ac2e2bb1e", +"tsql": "8917b70db141a02ac2e2bb1e" +} +], +[ +"type", +{ +"DuckDB": "ef480cafe4d260b70ce5214c", +"None": "ef480cafe4d260b70ce5214c", +"bigquery": "ef480cafe4d260b70ce5214c", +"databricks": "ef480cafe4d260b70ce5214c", +"duckdb": "ef480cafe4d260b70ce5214c", +"generic": "ef480cafe4d260b70ce5214c", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "ef480cafe4d260b70ce5214c", +"postgres": "ef480cafe4d260b70ce5214c", +"postgresql": "ef480cafe4d260b70ce5214c", +"snowflake": "ef480cafe4d260b70ce5214c", +"tsql": "ef480cafe4d260b70ce5214c" +} +], +[ +"type", +{ +"DuckDB": "19bdd92ea0cc5fb028657510", +"None": "78b2cf275c640af54feeca31", +"bigquery": "78b2cf275c640af54feeca31", +"databricks": "1e75e5227bea0ae294ac7af1", +"duckdb": "19bdd92ea0cc5fb028657510", +"generic": "78b2cf275c640af54feeca31", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "19bdd92ea0cc5fb028657510", +"postgres": "78b2cf275c640af54feeca31", +"postgresql": "78b2cf275c640af54feeca31", +"snowflake": "8ff614b7306c0edbe36ce00b", +"tsql": "78b2cf275c640af54feeca31" +} +], +[ +"type", +{ +"DuckDB": "ee47e1424cb01deb0cf51760", +"None": "ee47e1424cb01deb0cf51760", +"bigquery": "ee47e1424cb01deb0cf51760", +"databricks": "ee47e1424cb01deb0cf51760", +"duckdb": "ee47e1424cb01deb0cf51760", +"generic": "ee47e1424cb01deb0cf51760", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "ee47e1424cb01deb0cf51760", +"postgres": "ee47e1424cb01deb0cf51760", +"postgresql": "ee47e1424cb01deb0cf51760", +"snowflake": "ee47e1424cb01deb0cf51760", +"tsql": "ee47e1424cb01deb0cf51760" +} +], +[ +"type", +{ +"DuckDB": "aab0389e2b5470136660bf8a", +"None": "aab0389e2b5470136660bf8a", +"bigquery": "c9b810639795a7bfab91b98d", +"databricks": "aab0389e2b5470136660bf8a", +"duckdb": "aab0389e2b5470136660bf8a", +"generic": "aab0389e2b5470136660bf8a", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "aab0389e2b5470136660bf8a", +"postgres": "aab0389e2b5470136660bf8a", +"postgresql": "aab0389e2b5470136660bf8a", +"snowflake": "97a20344d811fb77c7690863", +"tsql": "aab0389e2b5470136660bf8a" +} +], +[ +"type", +{ +"DuckDB": "fe23594c781e79cbb0c8927a", +"None": "fe23594c781e79cbb0c8927a", +"bigquery": "fe23594c781e79cbb0c8927a", +"databricks": "fe23594c781e79cbb0c8927a", +"duckdb": "fe23594c781e79cbb0c8927a", +"generic": "fe23594c781e79cbb0c8927a", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "fe23594c781e79cbb0c8927a", +"postgres": "fe23594c781e79cbb0c8927a", +"postgresql": "fe23594c781e79cbb0c8927a", +"snowflake": "38b2ec94bf02be40007ce525", +"tsql": "fe23594c781e79cbb0c8927a" +} +], +[ +"type", +{ +"DuckDB": "61d08c878cc506dd91ca4586", +"None": "61d08c878cc506dd91ca4586", +"bigquery": "73f0a74496572926a274036e", +"databricks": "e3bc1b8bad22d8104417b00f", +"duckdb": "61d08c878cc506dd91ca4586", +"generic": "61d08c878cc506dd91ca4586", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "c100cdbd268164cf084295be", +"postgres": "61d08c878cc506dd91ca4586", +"postgresql": "61d08c878cc506dd91ca4586", +"snowflake": "c100cdbd268164cf084295be", +"tsql": "61d08c878cc506dd91ca4586" +} +], +[ +"type", +{ +"DuckDB": "755657fbcced1de4551fb370", +"None": "41ae0d23941c87be23d59e1f", +"bigquery": "41ae0d23941c87be23d59e1f", +"databricks": "41ae0d23941c87be23d59e1f", +"duckdb": "755657fbcced1de4551fb370", +"generic": "41ae0d23941c87be23d59e1f", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "41ae0d23941c87be23d59e1f", +"postgres": "41ae0d23941c87be23d59e1f", +"postgresql": "41ae0d23941c87be23d59e1f", +"snowflake": "41ae0d23941c87be23d59e1f", +"tsql": "41ae0d23941c87be23d59e1f" +} +], +[ +"type", +{ +"DuckDB": "3f71ab5f3c1c040da96f2cec", +"None": "3f71ab5f3c1c040da96f2cec", +"bigquery": "3f71ab5f3c1c040da96f2cec", +"databricks": "3f71ab5f3c1c040da96f2cec", +"duckdb": "3f71ab5f3c1c040da96f2cec", +"generic": "3f71ab5f3c1c040da96f2cec", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "3f71ab5f3c1c040da96f2cec", +"postgres": "3f71ab5f3c1c040da96f2cec", +"postgresql": "3f71ab5f3c1c040da96f2cec", +"snowflake": "3f71ab5f3c1c040da96f2cec", +"tsql": "3f71ab5f3c1c040da96f2cec" +} +], +[ +"type", +{ +"DuckDB": "251aba3fef503ce64556c701", +"None": "251aba3fef503ce64556c701", +"bigquery": "c50a316d091c821866e4bfba", +"databricks": "251aba3fef503ce64556c701", +"duckdb": "251aba3fef503ce64556c701", +"generic": "251aba3fef503ce64556c701", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "251aba3fef503ce64556c701", +"postgres": "251aba3fef503ce64556c701", +"postgresql": "251aba3fef503ce64556c701", +"snowflake": "c50a316d091c821866e4bfba", +"tsql": "251aba3fef503ce64556c701" +} +], +[ +"type", +{ +"DuckDB": "79278352c17c9de0f5a28af5", +"None": "79278352c17c9de0f5a28af5", +"bigquery": "c9b810639795a7bfab91b98d", +"databricks": "79278352c17c9de0f5a28af5", +"duckdb": "79278352c17c9de0f5a28af5", +"generic": "79278352c17c9de0f5a28af5", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "79278352c17c9de0f5a28af5", +"postgres": "79278352c17c9de0f5a28af5", +"postgresql": "79278352c17c9de0f5a28af5", +"snowflake": "97a20344d811fb77c7690863", +"tsql": "79278352c17c9de0f5a28af5" +} +], +[ +"type", +{ +"DuckDB": "c82815abe30b3d099903f838", +"None": "c82815abe30b3d099903f838", +"bigquery": "c82815abe30b3d099903f838", +"databricks": "c82815abe30b3d099903f838", +"duckdb": "c82815abe30b3d099903f838", +"generic": "c82815abe30b3d099903f838", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "c82815abe30b3d099903f838", +"postgres": "c82815abe30b3d099903f838", +"postgresql": "c82815abe30b3d099903f838", +"snowflake": "c82815abe30b3d099903f838", +"tsql": "07ca53fdc57a22a78ad75787" +} +], +[ +"type", +{ +"DuckDB": "d6e37cd37419bfb26e09b080", +"None": "d6e37cd37419bfb26e09b080", +"bigquery": "d6e37cd37419bfb26e09b080", +"databricks": "d6e37cd37419bfb26e09b080", +"duckdb": "d6e37cd37419bfb26e09b080", +"generic": "d6e37cd37419bfb26e09b080", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "d6e37cd37419bfb26e09b080", +"postgres": "d6e37cd37419bfb26e09b080", +"postgresql": "d6e37cd37419bfb26e09b080", +"snowflake": "d6e37cd37419bfb26e09b080", +"tsql": "d6e37cd37419bfb26e09b080" +} +], +[ +"type", +{ +"DuckDB": "5c28019dce48a74708c90a76", +"None": "5c28019dce48a74708c90a76", +"bigquery": "f28a96f0eb38ad8874f6ec5d", +"databricks": "5c28019dce48a74708c90a76", +"duckdb": "5c28019dce48a74708c90a76", +"generic": "5c28019dce48a74708c90a76", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "5c28019dce48a74708c90a76", +"postgres": "5c28019dce48a74708c90a76", +"postgresql": "5c28019dce48a74708c90a76", +"snowflake": "a5656d70e208254d1d3e9b4f", +"tsql": "2a7a7132adc795ca2bc39c37" +} +], +[ +"type", +{ +"DuckDB": "f4c43a87a78970bca1f88b09", +"None": "f4c43a87a78970bca1f88b09", +"bigquery": "f4c43a87a78970bca1f88b09", +"databricks": "f4c43a87a78970bca1f88b09", +"duckdb": "f4c43a87a78970bca1f88b09", +"generic": "f4c43a87a78970bca1f88b09", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "f4c43a87a78970bca1f88b09", +"postgres": "f4c43a87a78970bca1f88b09", +"postgresql": "f4c43a87a78970bca1f88b09", +"snowflake": "652ff8b21f638eac8fdc46c5", +"tsql": "f4c43a87a78970bca1f88b09" +} +], +[ +"type", +{ +"DuckDB": "669084d1ea704ae5b8ee05c2", +"None": "669084d1ea704ae5b8ee05c2", +"bigquery": "669084d1ea704ae5b8ee05c2", +"databricks": "669084d1ea704ae5b8ee05c2", +"duckdb": "669084d1ea704ae5b8ee05c2", +"generic": "669084d1ea704ae5b8ee05c2", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "669084d1ea704ae5b8ee05c2", +"postgres": "669084d1ea704ae5b8ee05c2", +"postgresql": "669084d1ea704ae5b8ee05c2", +"snowflake": "669084d1ea704ae5b8ee05c2", +"tsql": "669084d1ea704ae5b8ee05c2" +} +], +[ +"type", +{ +"DuckDB": "9070740b5c7f7fb5d091ad05", +"None": "9070740b5c7f7fb5d091ad05", +"bigquery": "9070740b5c7f7fb5d091ad05", +"databricks": "9070740b5c7f7fb5d091ad05", +"duckdb": "9070740b5c7f7fb5d091ad05", +"generic": "9070740b5c7f7fb5d091ad05", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "9070740b5c7f7fb5d091ad05", +"postgres": "9070740b5c7f7fb5d091ad05", +"postgresql": "9070740b5c7f7fb5d091ad05", +"snowflake": "9070740b5c7f7fb5d091ad05", +"tsql": "9070740b5c7f7fb5d091ad05" +} +], +[ +"type", +{ +"DuckDB": "19a1a80ffc06169f32694de8", +"None": "19a1a80ffc06169f32694de8", +"bigquery": "19a1a80ffc06169f32694de8", +"databricks": "19a1a80ffc06169f32694de8", +"duckdb": "19a1a80ffc06169f32694de8", +"generic": "19a1a80ffc06169f32694de8", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "19a1a80ffc06169f32694de8", +"postgres": "19a1a80ffc06169f32694de8", +"postgresql": "19a1a80ffc06169f32694de8", +"snowflake": "19a1a80ffc06169f32694de8", +"tsql": "19a1a80ffc06169f32694de8" +} +], +[ +"type", +{ +"DuckDB": "2bfa352725f9d8a91250f75e", +"None": "2bfa352725f9d8a91250f75e", +"bigquery": "2bfa352725f9d8a91250f75e", +"databricks": "2bfa352725f9d8a91250f75e", +"duckdb": "2bfa352725f9d8a91250f75e", +"generic": "2bfa352725f9d8a91250f75e", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "2bfa352725f9d8a91250f75e", +"postgres": "2bfa352725f9d8a91250f75e", +"postgresql": "2bfa352725f9d8a91250f75e", +"snowflake": "2bfa352725f9d8a91250f75e", +"tsql": "2bfa352725f9d8a91250f75e" +} +], +[ +"type", +{ +"DuckDB": "c0eec31620dfc2ac0028173d", +"None": "7f902bdd94be27212c27de4d", +"bigquery": "02e0b2ed25f32a8d09350a23", +"databricks": "7f902bdd94be27212c27de4d", +"duckdb": "c0eec31620dfc2ac0028173d", +"generic": "7f902bdd94be27212c27de4d", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "6c03a3450ea4742ee7396e3c", +"postgres": "6d562c54c27c6810625f7693", +"postgresql": "6d562c54c27c6810625f7693", +"snowflake": "354dee69d4f0c63cf79046ac", +"tsql": "bf34c743a59d7c3f212cf17b" +} +], +[ +"type", +{ +"DuckDB": "6cffd1617edd6454241ee732", +"None": "6cffd1617edd6454241ee732", +"bigquery": "6cffd1617edd6454241ee732", +"databricks": "6cffd1617edd6454241ee732", +"duckdb": "6cffd1617edd6454241ee732", +"generic": "6cffd1617edd6454241ee732", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "6cffd1617edd6454241ee732", +"postgres": "6cffd1617edd6454241ee732", +"postgresql": "6cffd1617edd6454241ee732", +"snowflake": "6cffd1617edd6454241ee732", +"tsql": "6cffd1617edd6454241ee732" +} +], +[ +"type", +{ +"DuckDB": "111af35848fe500ec2ae54b2", +"None": "111af35848fe500ec2ae54b2", +"bigquery": "c50a316d091c821866e4bfba", +"databricks": "e3bc1b8bad22d8104417b00f", +"duckdb": "111af35848fe500ec2ae54b2", +"generic": "111af35848fe500ec2ae54b2", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "e3bc1b8bad22d8104417b00f", +"postgres": "111af35848fe500ec2ae54b2", +"postgresql": "111af35848fe500ec2ae54b2", +"snowflake": "e3bc1b8bad22d8104417b00f", +"tsql": "111af35848fe500ec2ae54b2" +} +], +[ +"type", +{ +"DuckDB": "a766fea06fc070b352976b0a", +"None": "a766fea06fc070b352976b0a", +"bigquery": "e4f0244beaa01667e80482b6", +"databricks": "e4f0244beaa01667e80482b6", +"duckdb": "a766fea06fc070b352976b0a", +"generic": "a766fea06fc070b352976b0a", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "e4f0244beaa01667e80482b6", +"postgres": "a766fea06fc070b352976b0a", +"postgresql": "a766fea06fc070b352976b0a", +"snowflake": "a766fea06fc070b352976b0a", +"tsql": "a766fea06fc070b352976b0a" +} +], +[ +"type", +{ +"DuckDB": "6a912271e85e6d85c1238bc0", +"None": "6a912271e85e6d85c1238bc0", +"bigquery": "6a912271e85e6d85c1238bc0", +"databricks": "6a912271e85e6d85c1238bc0", +"duckdb": "6a912271e85e6d85c1238bc0", +"generic": "6a912271e85e6d85c1238bc0", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "6a912271e85e6d85c1238bc0", +"postgres": "6a912271e85e6d85c1238bc0", +"postgresql": "6a912271e85e6d85c1238bc0", +"snowflake": "6a912271e85e6d85c1238bc0", +"tsql": "6a912271e85e6d85c1238bc0" +} +], +[ +"type", +{ +"DuckDB": "3efe8bb57c98fcbe74096b3c", +"None": "3efe8bb57c98fcbe74096b3c", +"bigquery": "68d2179839f17f0eb289d1aa", +"databricks": "e3bc1b8bad22d8104417b00f", +"duckdb": "3efe8bb57c98fcbe74096b3c", +"generic": "3efe8bb57c98fcbe74096b3c", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "1d8b945fd793ecdcacb90c21", +"postgres": "3efe8bb57c98fcbe74096b3c", +"postgresql": "3efe8bb57c98fcbe74096b3c", +"snowflake": "1d8b945fd793ecdcacb90c21", +"tsql": "3efe8bb57c98fcbe74096b3c" +} +], +[ +"type", +{ +"DuckDB": "c50a316d091c821866e4bfba", +"None": "c50a316d091c821866e4bfba", +"bigquery": "c50a316d091c821866e4bfba", +"databricks": "c50a316d091c821866e4bfba", +"duckdb": "c50a316d091c821866e4bfba", +"generic": "c50a316d091c821866e4bfba", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "c50a316d091c821866e4bfba", +"postgres": "c50a316d091c821866e4bfba", +"postgresql": "c50a316d091c821866e4bfba", +"snowflake": "c50a316d091c821866e4bfba", +"tsql": "c50a316d091c821866e4bfba" +} +], +[ +"type", +{ +"DuckDB": "19bdd92ea0cc5fb028657510", +"None": "b8321619b794db091c9e96a1", +"bigquery": "b8321619b794db091c9e96a1", +"databricks": "1e75e5227bea0ae294ac7af1", +"duckdb": "19bdd92ea0cc5fb028657510", +"generic": "b8321619b794db091c9e96a1", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "b8321619b794db091c9e96a1", +"postgres": "b8321619b794db091c9e96a1", +"postgresql": "b8321619b794db091c9e96a1", +"snowflake": "b8321619b794db091c9e96a1", +"tsql": "b8321619b794db091c9e96a1" +} +], +[ +"type", +{ +"DuckDB": "c50a316d091c821866e4bfba", +"None": "c50a316d091c821866e4bfba", +"bigquery": "c50a316d091c821866e4bfba", +"databricks": "c50a316d091c821866e4bfba", +"duckdb": "c50a316d091c821866e4bfba", +"generic": "c50a316d091c821866e4bfba", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "c50a316d091c821866e4bfba", +"postgres": "c50a316d091c821866e4bfba", +"postgresql": "c50a316d091c821866e4bfba", +"snowflake": "c50a316d091c821866e4bfba", +"tsql": "c50a316d091c821866e4bfba" +} +], +[ +"type", +{ +"DuckDB": "8a3f094f18fb4047f0febf59", +"None": "8a3f094f18fb4047f0febf59", +"bigquery": "5c28019dce48a74708c90a76", +"databricks": "8a3f094f18fb4047f0febf59", +"duckdb": "8a3f094f18fb4047f0febf59", +"generic": "8a3f094f18fb4047f0febf59", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "5c28019dce48a74708c90a76", +"postgres": "8a3f094f18fb4047f0febf59", +"postgresql": "8a3f094f18fb4047f0febf59", +"snowflake": "850deea990b52b82b36a9848", +"tsql": "cc8534b198fe0c225bbffd8d" +} +], +[ +"type", +{ +"DuckDB": "2bfa352725f9d8a91250f75e", +"None": "2bfa352725f9d8a91250f75e", +"bigquery": "2bfa352725f9d8a91250f75e", +"databricks": "2bfa352725f9d8a91250f75e", +"duckdb": "2bfa352725f9d8a91250f75e", +"generic": "2bfa352725f9d8a91250f75e", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "2bfa352725f9d8a91250f75e", +"postgres": "2bfa352725f9d8a91250f75e", +"postgresql": "2bfa352725f9d8a91250f75e", +"snowflake": "2bfa352725f9d8a91250f75e", +"tsql": "2bfa352725f9d8a91250f75e" +} +], +[ +"type", +{ +"DuckDB": "07c9e779f7ae9c58f4f0c902", +"None": "07c9e779f7ae9c58f4f0c902", +"bigquery": "07c9e779f7ae9c58f4f0c902", +"databricks": "07c9e779f7ae9c58f4f0c902", +"duckdb": "07c9e779f7ae9c58f4f0c902", +"generic": "07c9e779f7ae9c58f4f0c902", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "07c9e779f7ae9c58f4f0c902", +"postgres": "07c9e779f7ae9c58f4f0c902", +"postgresql": "07c9e779f7ae9c58f4f0c902", +"snowflake": "07c9e779f7ae9c58f4f0c902", +"tsql": "07c9e779f7ae9c58f4f0c902" +} +], +[ +"type", +{ +"DuckDB": "1eb7fb4e8cf75773c5573562", +"None": "1eb7fb4e8cf75773c5573562", +"bigquery": "c9b810639795a7bfab91b98d", +"databricks": "1eb7fb4e8cf75773c5573562", +"duckdb": "1eb7fb4e8cf75773c5573562", +"generic": "1eb7fb4e8cf75773c5573562", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "1eb7fb4e8cf75773c5573562", +"postgres": "1eb7fb4e8cf75773c5573562", +"postgresql": "1eb7fb4e8cf75773c5573562", +"snowflake": "97a20344d811fb77c7690863", +"tsql": "1eb7fb4e8cf75773c5573562" +} +], +[ +"type", +{ +"DuckDB": "5c28019dce48a74708c90a76", +"None": "5c28019dce48a74708c90a76", +"bigquery": "f28a96f0eb38ad8874f6ec5d", +"databricks": "5c28019dce48a74708c90a76", +"duckdb": "5c28019dce48a74708c90a76", +"generic": "5c28019dce48a74708c90a76", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "5c28019dce48a74708c90a76", +"postgres": "5c28019dce48a74708c90a76", +"postgresql": "5c28019dce48a74708c90a76", +"snowflake": "a5656d70e208254d1d3e9b4f", +"tsql": "2a7a7132adc795ca2bc39c37" +} +], +[ +"type", +{ +"DuckDB": "ebc821a95b9286e22c2b26d0", +"None": "ebc821a95b9286e22c2b26d0", +"bigquery": "19a1a80ffc06169f32694de8", +"databricks": "ebc821a95b9286e22c2b26d0", +"duckdb": "ebc821a95b9286e22c2b26d0", +"generic": "ebc821a95b9286e22c2b26d0", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "ebc821a95b9286e22c2b26d0", +"postgres": "ebc821a95b9286e22c2b26d0", +"postgresql": "ebc821a95b9286e22c2b26d0", +"snowflake": "ebc821a95b9286e22c2b26d0", +"tsql": "ebc821a95b9286e22c2b26d0" +} +], +[ +"type", +{ +"DuckDB": "e248573edaaaa875cb926c45", +"None": "e248573edaaaa875cb926c45", +"bigquery": "2a0918be53051fe629d9ff8f", +"databricks": "e248573edaaaa875cb926c45", +"duckdb": "e248573edaaaa875cb926c45", +"generic": "e248573edaaaa875cb926c45", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "e248573edaaaa875cb926c45", +"postgres": "e248573edaaaa875cb926c45", +"postgresql": "e248573edaaaa875cb926c45", +"snowflake": "e248573edaaaa875cb926c45", +"tsql": "e248573edaaaa875cb926c45" +} +], +[ +"type", +{ +"DuckDB": "0b8ad171901cc2b7725617da", +"None": "0b8ad171901cc2b7725617da", +"bigquery": "0b8ad171901cc2b7725617da", +"databricks": "0b8ad171901cc2b7725617da", +"duckdb": "0b8ad171901cc2b7725617da", +"generic": "0b8ad171901cc2b7725617da", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "0b8ad171901cc2b7725617da", +"postgres": "0b8ad171901cc2b7725617da", +"postgresql": "0b8ad171901cc2b7725617da", +"snowflake": "0b8ad171901cc2b7725617da", +"tsql": "0b8ad171901cc2b7725617da" +} +], +[ +"type", +{ +"DuckDB": "d44c023c720f385769f2ab81", +"None": "d44c023c720f385769f2ab81", +"bigquery": "d44c023c720f385769f2ab81", +"databricks": "d44c023c720f385769f2ab81", +"duckdb": "d44c023c720f385769f2ab81", +"generic": "d44c023c720f385769f2ab81", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "d44c023c720f385769f2ab81", +"postgres": "d44c023c720f385769f2ab81", +"postgresql": "d44c023c720f385769f2ab81", +"snowflake": "d44c023c720f385769f2ab81", +"tsql": "d44c023c720f385769f2ab81" +} +], +[ +"type", +{ +"DuckDB": "8a3f094f18fb4047f0febf59", +"None": "8a3f094f18fb4047f0febf59", +"bigquery": "5c28019dce48a74708c90a76", +"databricks": "8a3f094f18fb4047f0febf59", +"duckdb": "8a3f094f18fb4047f0febf59", +"generic": "8a3f094f18fb4047f0febf59", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "5c28019dce48a74708c90a76", +"postgres": "8a3f094f18fb4047f0febf59", +"postgresql": "8a3f094f18fb4047f0febf59", +"snowflake": "850deea990b52b82b36a9848", +"tsql": "cc8534b198fe0c225bbffd8d" +} +], +[ +"type", +{ +"DuckDB": "5abf4ec799a2ec32fb10da7e", +"None": "5abf4ec799a2ec32fb10da7e", +"bigquery": "5abf4ec799a2ec32fb10da7e", +"databricks": "5abf4ec799a2ec32fb10da7e", +"duckdb": "5abf4ec799a2ec32fb10da7e", +"generic": "5abf4ec799a2ec32fb10da7e", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "5abf4ec799a2ec32fb10da7e", +"postgres": "5abf4ec799a2ec32fb10da7e", +"postgresql": "5abf4ec799a2ec32fb10da7e", +"snowflake": "a5656d70e208254d1d3e9b4f", +"tsql": "5abf4ec799a2ec32fb10da7e" +} +], +[ +"type", +{ +"DuckDB": "c5c5fbb0257c93153cb84430", +"None": "c5c5fbb0257c93153cb84430", +"bigquery": "c5c5fbb0257c93153cb84430", +"databricks": "c5c5fbb0257c93153cb84430", +"duckdb": "c5c5fbb0257c93153cb84430", +"generic": "c5c5fbb0257c93153cb84430", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "c5c5fbb0257c93153cb84430", +"postgres": "c5c5fbb0257c93153cb84430", +"postgresql": "c5c5fbb0257c93153cb84430", +"snowflake": "c5c5fbb0257c93153cb84430", +"tsql": "c5c5fbb0257c93153cb84430" +} +], +[ +"type", +{ +"DuckDB": "d6e37cd37419bfb26e09b080", +"None": "d6e37cd37419bfb26e09b080", +"bigquery": "d6e37cd37419bfb26e09b080", +"databricks": "d6e37cd37419bfb26e09b080", +"duckdb": "d6e37cd37419bfb26e09b080", +"generic": "d6e37cd37419bfb26e09b080", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "d6e37cd37419bfb26e09b080", +"postgres": "d6e37cd37419bfb26e09b080", +"postgresql": "d6e37cd37419bfb26e09b080", +"snowflake": "d6e37cd37419bfb26e09b080", +"tsql": "d6e37cd37419bfb26e09b080" +} +], +[ +"type", +{ +"DuckDB": "d34f84c1b71b9c9c0c20abb0", +"None": "d34f84c1b71b9c9c0c20abb0", +"bigquery": "d34f84c1b71b9c9c0c20abb0", +"databricks": "c662d9470aa4255dfb493df1", +"duckdb": "d34f84c1b71b9c9c0c20abb0", +"generic": "d34f84c1b71b9c9c0c20abb0", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "c662d9470aa4255dfb493df1", +"postgres": "d34f84c1b71b9c9c0c20abb0", +"postgresql": "d34f84c1b71b9c9c0c20abb0", +"snowflake": "d34f84c1b71b9c9c0c20abb0", +"tsql": "d34f84c1b71b9c9c0c20abb0" +} +], +[ +"type", +{ +"DuckDB": "c50a316d091c821866e4bfba", +"None": "c50a316d091c821866e4bfba", +"bigquery": "c50a316d091c821866e4bfba", +"databricks": "c50a316d091c821866e4bfba", +"duckdb": "c50a316d091c821866e4bfba", +"generic": "c50a316d091c821866e4bfba", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "c50a316d091c821866e4bfba", +"postgres": "c50a316d091c821866e4bfba", +"postgresql": "c50a316d091c821866e4bfba", +"snowflake": "c50a316d091c821866e4bfba", +"tsql": "c50a316d091c821866e4bfba" +} +], +[ +"type", +{ +"DuckDB": "8a3f094f18fb4047f0febf59", +"None": "bbb2563edda71d0b69ef0855", +"bigquery": "5c28019dce48a74708c90a76", +"databricks": "bbb2563edda71d0b69ef0855", +"duckdb": "8a3f094f18fb4047f0febf59", +"generic": "bbb2563edda71d0b69ef0855", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "51d717b08676179ee1ccefe4", +"postgres": "bbb2563edda71d0b69ef0855", +"postgresql": "bbb2563edda71d0b69ef0855", +"snowflake": "bbb2563edda71d0b69ef0855", +"tsql": "83fd3ed7282be0616dc3037e" +} +], +[ +"type", +{ +"DuckDB": "79278352c17c9de0f5a28af5", +"None": "79278352c17c9de0f5a28af5", +"bigquery": "c9b810639795a7bfab91b98d", +"databricks": "79278352c17c9de0f5a28af5", +"duckdb": "79278352c17c9de0f5a28af5", +"generic": "79278352c17c9de0f5a28af5", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "79278352c17c9de0f5a28af5", +"postgres": "79278352c17c9de0f5a28af5", +"postgresql": "79278352c17c9de0f5a28af5", +"snowflake": "97a20344d811fb77c7690863", +"tsql": "79278352c17c9de0f5a28af5" +} +], +[ +"type", +{ +"DuckDB": "c1eef7499ef79562fa125447", +"None": "c1eef7499ef79562fa125447", +"bigquery": "c1eef7499ef79562fa125447", +"databricks": "c1eef7499ef79562fa125447", +"duckdb": "c1eef7499ef79562fa125447", +"generic": "c1eef7499ef79562fa125447", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "c1eef7499ef79562fa125447", +"postgres": "c1eef7499ef79562fa125447", +"postgresql": "c1eef7499ef79562fa125447", +"snowflake": "c1eef7499ef79562fa125447", +"tsql": "c1eef7499ef79562fa125447" +} +], +[ +"type", +{ +"DuckDB": "b210f8eb26c37b422f786c6b", +"None": "b210f8eb26c37b422f786c6b", +"bigquery": "88f7cced71c11944260bb54a", +"databricks": "b210f8eb26c37b422f786c6b", +"duckdb": "b210f8eb26c37b422f786c6b", +"generic": "b210f8eb26c37b422f786c6b", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "b210f8eb26c37b422f786c6b", +"postgres": "b210f8eb26c37b422f786c6b", +"postgresql": "b210f8eb26c37b422f786c6b", +"snowflake": "b210f8eb26c37b422f786c6b", +"tsql": "b210f8eb26c37b422f786c6b" +} +], +[ +"type", +{ +"DuckDB": "2d4aea8dec5521e258596f3d", +"None": "2d4aea8dec5521e258596f3d", +"bigquery": "2d4aea8dec5521e258596f3d", +"databricks": "2d4aea8dec5521e258596f3d", +"duckdb": "2d4aea8dec5521e258596f3d", +"generic": "2d4aea8dec5521e258596f3d", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "2d4aea8dec5521e258596f3d", +"postgres": "f15c56475abfc73488abe63b", +"postgresql": "f15c56475abfc73488abe63b", +"snowflake": "652ff8b21f638eac8fdc46c5", +"tsql": "2d4aea8dec5521e258596f3d" +} +], +[ +"type", +{ +"DuckDB": "b4d65f2c9d0405e88d28938b", +"None": "ba98b19402ac6379a4172de9", +"bigquery": "ba98b19402ac6379a4172de9", +"databricks": "ba98b19402ac6379a4172de9", +"duckdb": "b4d65f2c9d0405e88d28938b", +"generic": "ba98b19402ac6379a4172de9", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "ba98b19402ac6379a4172de9", +"postgres": "ba98b19402ac6379a4172de9", +"postgresql": "ba98b19402ac6379a4172de9", +"snowflake": "ba98b19402ac6379a4172de9", +"tsql": "ba98b19402ac6379a4172de9" +} +], +[ +"type", +{ +"DuckDB": "e46d4be44ab9e500e9190d26", +"None": "e46d4be44ab9e500e9190d26", +"bigquery": "e6ffdece2977be55da73b59a", +"databricks": "e46d4be44ab9e500e9190d26", +"duckdb": "e46d4be44ab9e500e9190d26", +"generic": "e46d4be44ab9e500e9190d26", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "e46d4be44ab9e500e9190d26", +"postgres": "e46d4be44ab9e500e9190d26", +"postgresql": "e46d4be44ab9e500e9190d26", +"snowflake": "e46d4be44ab9e500e9190d26", +"tsql": "e46d4be44ab9e500e9190d26" +} +], +[ +"type", +{ +"DuckDB": "6c58c6a62958e64e6a26bf9c", +"None": "6c58c6a62958e64e6a26bf9c", +"bigquery": "204206d1d1eecf007966cc5b", +"databricks": "6c58c6a62958e64e6a26bf9c", +"duckdb": "6c58c6a62958e64e6a26bf9c", +"generic": "6c58c6a62958e64e6a26bf9c", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "6c58c6a62958e64e6a26bf9c", +"postgres": "571886088d0423ed1a0f1696", +"postgresql": "571886088d0423ed1a0f1696", +"snowflake": "6c58c6a62958e64e6a26bf9c", +"tsql": "919b7ec6a7b49d8527b784cd" +} +], +[ +"type", +{ +"DuckDB": "2bfa352725f9d8a91250f75e", +"None": "2bfa352725f9d8a91250f75e", +"bigquery": "2bfa352725f9d8a91250f75e", +"databricks": "2bfa352725f9d8a91250f75e", +"duckdb": "2bfa352725f9d8a91250f75e", +"generic": "2bfa352725f9d8a91250f75e", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "2bfa352725f9d8a91250f75e", +"postgres": "2bfa352725f9d8a91250f75e", +"postgresql": "2bfa352725f9d8a91250f75e", +"snowflake": "2bfa352725f9d8a91250f75e", +"tsql": "2bfa352725f9d8a91250f75e" +} +], +[ +"type", +{ +"DuckDB": "42a76d5ff05d0f91911ff368", +"None": "42a76d5ff05d0f91911ff368", +"bigquery": "42a76d5ff05d0f91911ff368", +"databricks": "42a76d5ff05d0f91911ff368", +"duckdb": "42a76d5ff05d0f91911ff368", +"generic": "42a76d5ff05d0f91911ff368", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "42a76d5ff05d0f91911ff368", +"postgres": "42a76d5ff05d0f91911ff368", +"postgresql": "42a76d5ff05d0f91911ff368", +"snowflake": "42a76d5ff05d0f91911ff368", +"tsql": "42a76d5ff05d0f91911ff368" +} +], +[ +"type", +{ +"DuckDB": "251aba3fef503ce64556c701", +"None": "251aba3fef503ce64556c701", +"bigquery": "c50a316d091c821866e4bfba", +"databricks": "251aba3fef503ce64556c701", +"duckdb": "251aba3fef503ce64556c701", +"generic": "251aba3fef503ce64556c701", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "251aba3fef503ce64556c701", +"postgres": "251aba3fef503ce64556c701", +"postgresql": "251aba3fef503ce64556c701", +"snowflake": "c50a316d091c821866e4bfba", +"tsql": "251aba3fef503ce64556c701" +} +], +[ +"type", +{ +"DuckDB": "5d25d5e13f81700741695ed4", +"None": "5d25d5e13f81700741695ed4", +"bigquery": "23ee196b7bd6039855a1460f", +"databricks": "5d25d5e13f81700741695ed4", +"duckdb": "5d25d5e13f81700741695ed4", +"generic": "5d25d5e13f81700741695ed4", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "5d25d5e13f81700741695ed4", +"postgres": "5d25d5e13f81700741695ed4", +"postgresql": "5d25d5e13f81700741695ed4", +"snowflake": "5d25d5e13f81700741695ed4", +"tsql": "5d25d5e13f81700741695ed4" +} +], +[ +"type", +{ +"DuckDB": "19bdd92ea0cc5fb028657510", +"None": "1e75e5227bea0ae294ac7af1", +"bigquery": "1e75e5227bea0ae294ac7af1", +"databricks": "1e75e5227bea0ae294ac7af1", +"duckdb": "19bdd92ea0cc5fb028657510", +"generic": "1e75e5227bea0ae294ac7af1", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "19bdd92ea0cc5fb028657510", +"postgres": "19bdd92ea0cc5fb028657510", +"postgresql": "19bdd92ea0cc5fb028657510", +"snowflake": "8ff614b7306c0edbe36ce00b", +"tsql": "901e8c830028411846541f65" +} +], +[ +"type", +{ +"DuckDB": "268b9b7c7862c9de6569286a", +"None": "268b9b7c7862c9de6569286a", +"bigquery": "268b9b7c7862c9de6569286a", +"databricks": "268b9b7c7862c9de6569286a", +"duckdb": "268b9b7c7862c9de6569286a", +"generic": "268b9b7c7862c9de6569286a", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "268b9b7c7862c9de6569286a", +"postgres": "268b9b7c7862c9de6569286a", +"postgresql": "268b9b7c7862c9de6569286a", +"snowflake": "268b9b7c7862c9de6569286a", +"tsql": "268b9b7c7862c9de6569286a" +} +], +[ +"type", +{ +"DuckDB": "da33de41a707d0e067e415fd", +"None": "da33de41a707d0e067e415fd", +"bigquery": "da33de41a707d0e067e415fd", +"databricks": "da33de41a707d0e067e415fd", +"duckdb": "da33de41a707d0e067e415fd", +"generic": "da33de41a707d0e067e415fd", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "da33de41a707d0e067e415fd", +"postgres": "da33de41a707d0e067e415fd", +"postgresql": "da33de41a707d0e067e415fd", +"snowflake": "da33de41a707d0e067e415fd", +"tsql": "da33de41a707d0e067e415fd" +} +], +[ +"type", +{ +"DuckDB": "7c8df74df226e73b459bfdba", +"None": "7c8df74df226e73b459bfdba", +"bigquery": "7c8df74df226e73b459bfdba", +"databricks": "7c8df74df226e73b459bfdba", +"duckdb": "7c8df74df226e73b459bfdba", +"generic": "7c8df74df226e73b459bfdba", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "7c8df74df226e73b459bfdba", +"postgres": "7c8df74df226e73b459bfdba", +"postgresql": "7c8df74df226e73b459bfdba", +"snowflake": "7c8df74df226e73b459bfdba", +"tsql": "7c8df74df226e73b459bfdba" +} +], +[ +"type", +{ +"DuckDB": "ebb346128c80cb653e9694c8", +"None": "ebb346128c80cb653e9694c8", +"bigquery": "ebb346128c80cb653e9694c8", +"databricks": "ebb346128c80cb653e9694c8", +"duckdb": "ebb346128c80cb653e9694c8", +"generic": "ebb346128c80cb653e9694c8", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "ebb346128c80cb653e9694c8", +"postgres": "ebb346128c80cb653e9694c8", +"postgresql": "ebb346128c80cb653e9694c8", +"snowflake": "ebb346128c80cb653e9694c8", +"tsql": "ebb346128c80cb653e9694c8" +} +], +[ +"type", +{ +"DuckDB": "9f4b51f000ffbe30f6b7d826", +"None": "bacfe825b19ef52bc792ab22", +"bigquery": "00714a615c9e7a090fb122c5", +"databricks": "00714a615c9e7a090fb122c5", +"duckdb": "9f4b51f000ffbe30f6b7d826", +"generic": "bacfe825b19ef52bc792ab22", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "00714a615c9e7a090fb122c5", +"postgres": "bacfe825b19ef52bc792ab22", +"postgresql": "bacfe825b19ef52bc792ab22", +"snowflake": "bacfe825b19ef52bc792ab22", +"tsql": "bacfe825b19ef52bc792ab22" +} +], +[ +"type", +{ +"DuckDB": "f85dfff687194a44f32eeb15", +"None": "f85dfff687194a44f32eeb15", +"bigquery": "f85dfff687194a44f32eeb15", +"databricks": "f85dfff687194a44f32eeb15", +"duckdb": "f85dfff687194a44f32eeb15", +"generic": "f85dfff687194a44f32eeb15", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "f85dfff687194a44f32eeb15", +"postgres": "f85dfff687194a44f32eeb15", +"postgresql": "f85dfff687194a44f32eeb15", +"snowflake": "f85dfff687194a44f32eeb15", +"tsql": "f85dfff687194a44f32eeb15" +} +], +[ +"type", +{ +"DuckDB": "24b677b214ecdacdb007642e", +"None": "24b677b214ecdacdb007642e", +"bigquery": "24b677b214ecdacdb007642e", +"databricks": "24b677b214ecdacdb007642e", +"duckdb": "24b677b214ecdacdb007642e", +"generic": "24b677b214ecdacdb007642e", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "24b677b214ecdacdb007642e", +"postgres": "24b677b214ecdacdb007642e", +"postgresql": "24b677b214ecdacdb007642e", +"snowflake": "24b677b214ecdacdb007642e", +"tsql": "24b677b214ecdacdb007642e" +} +], +[ +"type", +{ +"DuckDB": "4c2128e6078118fd0d3856fa", +"None": "4c2128e6078118fd0d3856fa", +"bigquery": "4c2128e6078118fd0d3856fa", +"databricks": "4c2128e6078118fd0d3856fa", +"duckdb": "4c2128e6078118fd0d3856fa", +"generic": "4c2128e6078118fd0d3856fa", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "4c2128e6078118fd0d3856fa", +"postgres": "4c2128e6078118fd0d3856fa", +"postgresql": "4c2128e6078118fd0d3856fa", +"snowflake": "4c2128e6078118fd0d3856fa", +"tsql": "4c2128e6078118fd0d3856fa" +} +], +[ +"type", +{ +"DuckDB": "8698d724534891869075175e", +"None": "0017a88bb60ec3403c786ed8", +"bigquery": "2795066c9a71fa3e3780c73b", +"databricks": "0017a88bb60ec3403c786ed8", +"duckdb": "8698d724534891869075175e", +"generic": "0017a88bb60ec3403c786ed8", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "6c03a3450ea4742ee7396e3c", +"postgres": "8698d724534891869075175e", +"postgresql": "8698d724534891869075175e", +"snowflake": "b3b752c645651b849e23d39a", +"tsql": "d1dc9a140dbe2eb1874c6ad7" +} +], +[ +"type", +{ +"DuckDB": "b1b23029bedaa16e2a6f8516", +"None": "b1b23029bedaa16e2a6f8516", +"bigquery": "b1b23029bedaa16e2a6f8516", +"databricks": "b1b23029bedaa16e2a6f8516", +"duckdb": "b1b23029bedaa16e2a6f8516", +"generic": "b1b23029bedaa16e2a6f8516", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "b1b23029bedaa16e2a6f8516", +"postgres": "b1b23029bedaa16e2a6f8516", +"postgresql": "b1b23029bedaa16e2a6f8516", +"snowflake": "b561884132dbe7e42b719110", +"tsql": "b1b23029bedaa16e2a6f8516" +} +], +[ +"type", +{ +"DuckDB": "1eb7fb4e8cf75773c5573562", +"None": "1eb7fb4e8cf75773c5573562", +"bigquery": "c9b810639795a7bfab91b98d", +"databricks": "1eb7fb4e8cf75773c5573562", +"duckdb": "1eb7fb4e8cf75773c5573562", +"generic": "1eb7fb4e8cf75773c5573562", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "1eb7fb4e8cf75773c5573562", +"postgres": "1eb7fb4e8cf75773c5573562", +"postgresql": "1eb7fb4e8cf75773c5573562", +"snowflake": "97a20344d811fb77c7690863", +"tsql": "1eb7fb4e8cf75773c5573562" +} +], +[ +"type", +{ +"DuckDB": "e7b8de8bd235305d79e2b6b1", +"None": "e7b8de8bd235305d79e2b6b1", +"bigquery": "e7b8de8bd235305d79e2b6b1", +"databricks": "e7b8de8bd235305d79e2b6b1", +"duckdb": "e7b8de8bd235305d79e2b6b1", +"generic": "e7b8de8bd235305d79e2b6b1", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "e7b8de8bd235305d79e2b6b1", +"postgres": "e7b8de8bd235305d79e2b6b1", +"postgresql": "e7b8de8bd235305d79e2b6b1", +"snowflake": "e7b8de8bd235305d79e2b6b1", +"tsql": "e7b8de8bd235305d79e2b6b1" +} +], +[ +"type", +{ +"DuckDB": "9aff7fcc7d550e1a8d105471", +"None": "9aff7fcc7d550e1a8d105471", +"bigquery": "f9bb9d0c419201aea072940b", +"databricks": "9aff7fcc7d550e1a8d105471", +"duckdb": "9aff7fcc7d550e1a8d105471", +"generic": "9aff7fcc7d550e1a8d105471", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "9aff7fcc7d550e1a8d105471", +"postgres": "9aff7fcc7d550e1a8d105471", +"postgresql": "9aff7fcc7d550e1a8d105471", +"snowflake": "9aff7fcc7d550e1a8d105471", +"tsql": "9aff7fcc7d550e1a8d105471" +} +], +[ +"type", +{ +"DuckDB": "242bf50062e95bc8534ca887", +"None": "242bf50062e95bc8534ca887", +"bigquery": "242bf50062e95bc8534ca887", +"databricks": "242bf50062e95bc8534ca887", +"duckdb": "242bf50062e95bc8534ca887", +"generic": "242bf50062e95bc8534ca887", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "242bf50062e95bc8534ca887", +"postgres": "242bf50062e95bc8534ca887", +"postgresql": "242bf50062e95bc8534ca887", +"snowflake": "242bf50062e95bc8534ca887", +"tsql": "242bf50062e95bc8534ca887" +} +], +[ +"type", +{ +"DuckDB": "23ee196b7bd6039855a1460f", +"None": "23ee196b7bd6039855a1460f", +"bigquery": "23ee196b7bd6039855a1460f", +"databricks": "23ee196b7bd6039855a1460f", +"duckdb": "23ee196b7bd6039855a1460f", +"generic": "23ee196b7bd6039855a1460f", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "23ee196b7bd6039855a1460f", +"postgres": "23ee196b7bd6039855a1460f", +"postgresql": "23ee196b7bd6039855a1460f", +"snowflake": "5d25d5e13f81700741695ed4", +"tsql": "23ee196b7bd6039855a1460f" +} +], +[ +"type", +{ +"DuckDB": "13f1401e7cd410600a4c9485", +"None": "13f1401e7cd410600a4c9485", +"bigquery": "74a30f6aa9def0b58afc616c", +"databricks": "13f1401e7cd410600a4c9485", +"duckdb": "13f1401e7cd410600a4c9485", +"generic": "13f1401e7cd410600a4c9485", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "13f1401e7cd410600a4c9485", +"postgres": "13f1401e7cd410600a4c9485", +"postgresql": "13f1401e7cd410600a4c9485", +"snowflake": "9b5f44707b5f4764b82741be", +"tsql": "13f1401e7cd410600a4c9485" +} +], +[ +"type", +{ +"DuckDB": "e1554f02dea662c971e7b9b9", +"None": "6f851103102e7b986535376f", +"bigquery": "58b7e0908df666938398205f", +"databricks": "6f851103102e7b986535376f", +"duckdb": "e1554f02dea662c971e7b9b9", +"generic": "6f851103102e7b986535376f", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "1a853242fb56557e2865a86a", +"postgres": "a0b34c5b4e5ace89b22c6971", +"postgresql": "a0b34c5b4e5ace89b22c6971", +"snowflake": "87800133cac38d9119180c0a", +"tsql": "0e9ef5373e5d52970e8e1656" +} +], +[ +"type", +{ +"DuckDB": "15be07c71f6871ae037caae3", +"None": "15be07c71f6871ae037caae3", +"bigquery": "15be07c71f6871ae037caae3", +"databricks": "15be07c71f6871ae037caae3", +"duckdb": "15be07c71f6871ae037caae3", +"generic": "15be07c71f6871ae037caae3", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "15be07c71f6871ae037caae3", +"postgres": "15be07c71f6871ae037caae3", +"postgresql": "15be07c71f6871ae037caae3", +"snowflake": "15be07c71f6871ae037caae3", +"tsql": "15be07c71f6871ae037caae3" +} +], +[ +"type", +{ +"DuckDB": "b210f8eb26c37b422f786c6b", +"None": "b210f8eb26c37b422f786c6b", +"bigquery": "88f7cced71c11944260bb54a", +"databricks": "b210f8eb26c37b422f786c6b", +"duckdb": "b210f8eb26c37b422f786c6b", +"generic": "b210f8eb26c37b422f786c6b", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "b210f8eb26c37b422f786c6b", +"postgres": "b210f8eb26c37b422f786c6b", +"postgresql": "b210f8eb26c37b422f786c6b", +"snowflake": "b210f8eb26c37b422f786c6b", +"tsql": "b210f8eb26c37b422f786c6b" +} +], +[ +"type", +{ +"DuckDB": "3d23f811a03db519b598c815", +"None": "3d23f811a03db519b598c815", +"bigquery": "3d23f811a03db519b598c815", +"databricks": "3d23f811a03db519b598c815", +"duckdb": "3d23f811a03db519b598c815", +"generic": "3d23f811a03db519b598c815", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "3d23f811a03db519b598c815", +"postgres": "3d23f811a03db519b598c815", +"postgresql": "3d23f811a03db519b598c815", +"snowflake": "3d23f811a03db519b598c815", +"tsql": "3d23f811a03db519b598c815" +} +], +[ +"type", +{ +"DuckDB": "fa55698f69d154f89214f351", +"None": "fa55698f69d154f89214f351", +"bigquery": "fa55698f69d154f89214f351", +"databricks": "fa55698f69d154f89214f351", +"duckdb": "fa55698f69d154f89214f351", +"generic": "fa55698f69d154f89214f351", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "fa55698f69d154f89214f351", +"postgres": "fa55698f69d154f89214f351", +"postgresql": "fa55698f69d154f89214f351", +"snowflake": "fa55698f69d154f89214f351", +"tsql": "fa55698f69d154f89214f351" +} +], +[ +"type", +{ +"DuckDB": "3009be83c84cdfc92bbb075e", +"None": "3009be83c84cdfc92bbb075e", +"bigquery": "3009be83c84cdfc92bbb075e", +"databricks": "3009be83c84cdfc92bbb075e", +"duckdb": "3009be83c84cdfc92bbb075e", +"generic": "3009be83c84cdfc92bbb075e", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "3009be83c84cdfc92bbb075e", +"postgres": "3009be83c84cdfc92bbb075e", +"postgresql": "3009be83c84cdfc92bbb075e", +"snowflake": "3009be83c84cdfc92bbb075e", +"tsql": "3009be83c84cdfc92bbb075e" +} +], +[ +"type", +{ +"DuckDB": "23ee196b7bd6039855a1460f", +"None": "23ee196b7bd6039855a1460f", +"bigquery": "23ee196b7bd6039855a1460f", +"databricks": "23ee196b7bd6039855a1460f", +"duckdb": "23ee196b7bd6039855a1460f", +"generic": "23ee196b7bd6039855a1460f", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "23ee196b7bd6039855a1460f", +"postgres": "23ee196b7bd6039855a1460f", +"postgresql": "23ee196b7bd6039855a1460f", +"snowflake": "5d25d5e13f81700741695ed4", +"tsql": "23ee196b7bd6039855a1460f" +} +], +[ +"type", +{ +"DuckDB": "9d6807d797be08f8376a5a19", +"None": "9d6807d797be08f8376a5a19", +"bigquery": "9d6807d797be08f8376a5a19", +"databricks": "9d6807d797be08f8376a5a19", +"duckdb": "9d6807d797be08f8376a5a19", +"generic": "9d6807d797be08f8376a5a19", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "9d6807d797be08f8376a5a19", +"postgres": "9d6807d797be08f8376a5a19", +"postgresql": "9d6807d797be08f8376a5a19", +"snowflake": "9d6807d797be08f8376a5a19", +"tsql": "9d6807d797be08f8376a5a19" +} +], +[ +"type", +{ +"DuckDB": "1eb7fb4e8cf75773c5573562", +"None": "1eb7fb4e8cf75773c5573562", +"bigquery": "c9b810639795a7bfab91b98d", +"databricks": "1eb7fb4e8cf75773c5573562", +"duckdb": "1eb7fb4e8cf75773c5573562", +"generic": "1eb7fb4e8cf75773c5573562", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "1eb7fb4e8cf75773c5573562", +"postgres": "1eb7fb4e8cf75773c5573562", +"postgresql": "1eb7fb4e8cf75773c5573562", +"snowflake": "97a20344d811fb77c7690863", +"tsql": "1eb7fb4e8cf75773c5573562" +} +], +[ +"type", +{ +"DuckDB": "d61c83ef8bfdf043fa672cb5", +"None": "d61c83ef8bfdf043fa672cb5", +"bigquery": "c9b810639795a7bfab91b98d", +"databricks": "d61c83ef8bfdf043fa672cb5", +"duckdb": "d61c83ef8bfdf043fa672cb5", +"generic": "d61c83ef8bfdf043fa672cb5", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "d61c83ef8bfdf043fa672cb5", +"postgres": "d61c83ef8bfdf043fa672cb5", +"postgresql": "d61c83ef8bfdf043fa672cb5", +"snowflake": "97a20344d811fb77c7690863", +"tsql": "d61c83ef8bfdf043fa672cb5" +} +], +[ +"type", +{ +"DuckDB": "fe23594c781e79cbb0c8927a", +"None": "fe23594c781e79cbb0c8927a", +"bigquery": "fe23594c781e79cbb0c8927a", +"databricks": "fe23594c781e79cbb0c8927a", +"duckdb": "fe23594c781e79cbb0c8927a", +"generic": "fe23594c781e79cbb0c8927a", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "fe23594c781e79cbb0c8927a", +"postgres": "fe23594c781e79cbb0c8927a", +"postgresql": "fe23594c781e79cbb0c8927a", +"snowflake": "38b2ec94bf02be40007ce525", +"tsql": "fe23594c781e79cbb0c8927a" +} +], +[ +"type", +{ +"DuckDB": "100c78a43fb3cbda50787a10", +"None": "100c78a43fb3cbda50787a10", +"bigquery": "100c78a43fb3cbda50787a10", +"databricks": "100c78a43fb3cbda50787a10", +"duckdb": "100c78a43fb3cbda50787a10", +"generic": "100c78a43fb3cbda50787a10", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "100c78a43fb3cbda50787a10", +"postgres": "100c78a43fb3cbda50787a10", +"postgresql": "100c78a43fb3cbda50787a10", +"snowflake": "100c78a43fb3cbda50787a10", +"tsql": "100c78a43fb3cbda50787a10" +} +], +[ +"type", +{ +"DuckDB": "aab0389e2b5470136660bf8a", +"None": "aab0389e2b5470136660bf8a", +"bigquery": "c9b810639795a7bfab91b98d", +"databricks": "aab0389e2b5470136660bf8a", +"duckdb": "aab0389e2b5470136660bf8a", +"generic": "aab0389e2b5470136660bf8a", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "aab0389e2b5470136660bf8a", +"postgres": "aab0389e2b5470136660bf8a", +"postgresql": "aab0389e2b5470136660bf8a", +"snowflake": "97a20344d811fb77c7690863", +"tsql": "aab0389e2b5470136660bf8a" +} +], +[ +"type", +{ +"DuckDB": "624eb95d280fa0653ec73f7f", +"None": "624eb95d280fa0653ec73f7f", +"bigquery": "624eb95d280fa0653ec73f7f", +"databricks": "624eb95d280fa0653ec73f7f", +"duckdb": "624eb95d280fa0653ec73f7f", +"generic": "624eb95d280fa0653ec73f7f", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "624eb95d280fa0653ec73f7f", +"postgres": "624eb95d280fa0653ec73f7f", +"postgresql": "624eb95d280fa0653ec73f7f", +"snowflake": "624eb95d280fa0653ec73f7f", +"tsql": "624eb95d280fa0653ec73f7f" +} +], +[ +"type", +{ +"DuckDB": "6b04f574865e71733e09ba1d", +"None": "6b04f574865e71733e09ba1d", +"bigquery": "6b04f574865e71733e09ba1d", +"databricks": "6b04f574865e71733e09ba1d", +"duckdb": "6b04f574865e71733e09ba1d", +"generic": "6b04f574865e71733e09ba1d", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "6b04f574865e71733e09ba1d", +"postgres": "6b04f574865e71733e09ba1d", +"postgresql": "6b04f574865e71733e09ba1d", +"snowflake": "6b04f574865e71733e09ba1d", +"tsql": "6b04f574865e71733e09ba1d" +} +], +[ +"type", +{ +"DuckDB": "8a3f094f18fb4047f0febf59", +"None": "8a3f094f18fb4047f0febf59", +"bigquery": "5c28019dce48a74708c90a76", +"databricks": "8a3f094f18fb4047f0febf59", +"duckdb": "8a3f094f18fb4047f0febf59", +"generic": "8a3f094f18fb4047f0febf59", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "5c28019dce48a74708c90a76", +"postgres": "8a3f094f18fb4047f0febf59", +"postgresql": "8a3f094f18fb4047f0febf59", +"snowflake": "850deea990b52b82b36a9848", +"tsql": "cc8534b198fe0c225bbffd8d" +} +], +[ +"type", +{ +"DuckDB": "4062ec81199547543ab068fb", +"None": "4062ec81199547543ab068fb", +"bigquery": "7009fc15fd2c35608ab16caf", +"databricks": "0739784ba4c53d23afd45a6b", +"duckdb": "4062ec81199547543ab068fb", +"generic": "4062ec81199547543ab068fb", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "4062ec81199547543ab068fb", +"postgres": "4062ec81199547543ab068fb", +"postgresql": "4062ec81199547543ab068fb", +"snowflake": "0739784ba4c53d23afd45a6b", +"tsql": "0739784ba4c53d23afd45a6b" +} +], +[ +"type", +{ +"DuckDB": "07f8200cee37aa0f6990da3d", +"None": "07f8200cee37aa0f6990da3d", +"bigquery": "07f8200cee37aa0f6990da3d", +"databricks": "07f8200cee37aa0f6990da3d", +"duckdb": "07f8200cee37aa0f6990da3d", +"generic": "07f8200cee37aa0f6990da3d", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "07f8200cee37aa0f6990da3d", +"postgres": "07f8200cee37aa0f6990da3d", +"postgresql": "07f8200cee37aa0f6990da3d", +"snowflake": "07f8200cee37aa0f6990da3d", +"tsql": "07f8200cee37aa0f6990da3d" +} +], +[ +"type", +{ +"DuckDB": "ab5ad6180652b3b00d1f5b01", +"None": "ab5ad6180652b3b00d1f5b01", +"bigquery": "946d5ee30ab7469c57d850df", +"databricks": "ab5ad6180652b3b00d1f5b01", +"duckdb": "ab5ad6180652b3b00d1f5b01", +"generic": "ab5ad6180652b3b00d1f5b01", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "ab5ad6180652b3b00d1f5b01", +"postgres": "ab5ad6180652b3b00d1f5b01", +"postgresql": "ab5ad6180652b3b00d1f5b01", +"snowflake": "f43dac38f34a1c0618a3f812", +"tsql": "ab5ad6180652b3b00d1f5b01" +} +], +[ +"type", +{ +"DuckDB": "47a5c4cbcdc5fda84d74a947", +"None": "47a5c4cbcdc5fda84d74a947", +"bigquery": "47a5c4cbcdc5fda84d74a947", +"databricks": "47a5c4cbcdc5fda84d74a947", +"duckdb": "47a5c4cbcdc5fda84d74a947", +"generic": "47a5c4cbcdc5fda84d74a947", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "47a5c4cbcdc5fda84d74a947", +"postgres": "47a5c4cbcdc5fda84d74a947", +"postgresql": "47a5c4cbcdc5fda84d74a947", +"snowflake": "47a5c4cbcdc5fda84d74a947", +"tsql": "47a5c4cbcdc5fda84d74a947" +} +], +[ +"type", +{ +"DuckDB": "e46d4be44ab9e500e9190d26", +"None": "e46d4be44ab9e500e9190d26", +"bigquery": "e6ffdece2977be55da73b59a", +"databricks": "e46d4be44ab9e500e9190d26", +"duckdb": "e46d4be44ab9e500e9190d26", +"generic": "e46d4be44ab9e500e9190d26", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "e46d4be44ab9e500e9190d26", +"postgres": "e46d4be44ab9e500e9190d26", +"postgresql": "e46d4be44ab9e500e9190d26", +"snowflake": "e46d4be44ab9e500e9190d26", +"tsql": "e46d4be44ab9e500e9190d26" +} +], +[ +"type", +{ +"DuckDB": "8a3f094f18fb4047f0febf59", +"None": "fe23594c781e79cbb0c8927a", +"bigquery": "fe23594c781e79cbb0c8927a", +"databricks": "fe23594c781e79cbb0c8927a", +"duckdb": "8a3f094f18fb4047f0febf59", +"generic": "fe23594c781e79cbb0c8927a", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "fe23594c781e79cbb0c8927a", +"postgres": "fe23594c781e79cbb0c8927a", +"postgresql": "fe23594c781e79cbb0c8927a", +"snowflake": "38b2ec94bf02be40007ce525", +"tsql": "fe23594c781e79cbb0c8927a" +} +], +[ +"type", +{ +"DuckDB": "de89632e277dbc8c97115419", +"None": "de89632e277dbc8c97115419", +"bigquery": "de89632e277dbc8c97115419", +"databricks": "de89632e277dbc8c97115419", +"duckdb": "de89632e277dbc8c97115419", +"generic": "de89632e277dbc8c97115419", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "de89632e277dbc8c97115419", +"postgres": "de89632e277dbc8c97115419", +"postgresql": "de89632e277dbc8c97115419", +"snowflake": "4b356542044f1267fcfc487a", +"tsql": "de89632e277dbc8c97115419" +} +], +[ +"type", +{ +"DuckDB": "792f7d3389f076f50c713946", +"None": "792f7d3389f076f50c713946", +"bigquery": "792f7d3389f076f50c713946", +"databricks": "4fb572024031cb7631777be1", +"duckdb": "792f7d3389f076f50c713946", +"generic": "792f7d3389f076f50c713946", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "792f7d3389f076f50c713946", +"postgres": "792f7d3389f076f50c713946", +"postgresql": "792f7d3389f076f50c713946", +"snowflake": "792f7d3389f076f50c713946", +"tsql": "792f7d3389f076f50c713946" +} +], +[ +"type", +{ +"DuckDB": "aae2b1fe6f2d9807ecde412b", +"None": "aae2b1fe6f2d9807ecde412b", +"bigquery": "e1c36a5cdd2427ff2b089ac9", +"databricks": "aae2b1fe6f2d9807ecde412b", +"duckdb": "aae2b1fe6f2d9807ecde412b", +"generic": "aae2b1fe6f2d9807ecde412b", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "aae2b1fe6f2d9807ecde412b", +"postgres": "aae2b1fe6f2d9807ecde412b", +"postgresql": "aae2b1fe6f2d9807ecde412b", +"snowflake": "aae2b1fe6f2d9807ecde412b", +"tsql": "aae2b1fe6f2d9807ecde412b" +} +], +[ +"type", +{ +"DuckDB": "16adcdd909f51e3f33d7cdde", +"None": "1f3277ab2fff19e327e21fe0", +"bigquery": "1f3277ab2fff19e327e21fe0", +"databricks": "1f3277ab2fff19e327e21fe0", +"duckdb": "16adcdd909f51e3f33d7cdde", +"generic": "1f3277ab2fff19e327e21fe0", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "6c03a3450ea4742ee7396e3c", +"postgres": "de3f085b785f38a4bda19034", +"postgresql": "de3f085b785f38a4bda19034", +"snowflake": "42ed29994060215ec30494f1", +"tsql": "d1dc9a140dbe2eb1874c6ad7" +} +], +[ +"type", +{ +"DuckDB": "690b44350cdb6852c9bc71a3", +"None": "690b44350cdb6852c9bc71a3", +"bigquery": "690b44350cdb6852c9bc71a3", +"databricks": "690b44350cdb6852c9bc71a3", +"duckdb": "690b44350cdb6852c9bc71a3", +"generic": "690b44350cdb6852c9bc71a3", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "690b44350cdb6852c9bc71a3", +"postgres": "690b44350cdb6852c9bc71a3", +"postgresql": "690b44350cdb6852c9bc71a3", +"snowflake": "690b44350cdb6852c9bc71a3", +"tsql": "690b44350cdb6852c9bc71a3" +} +], +[ +"type", +{ +"DuckDB": "3a7ffeb8f81df6ccd57f3689", +"None": "3a7ffeb8f81df6ccd57f3689", +"bigquery": "3a7ffeb8f81df6ccd57f3689", +"databricks": "3a7ffeb8f81df6ccd57f3689", +"duckdb": "3a7ffeb8f81df6ccd57f3689", +"generic": "3a7ffeb8f81df6ccd57f3689", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "3a7ffeb8f81df6ccd57f3689", +"postgres": "3a7ffeb8f81df6ccd57f3689", +"postgresql": "3a7ffeb8f81df6ccd57f3689", +"snowflake": "3a7ffeb8f81df6ccd57f3689", +"tsql": "3a7ffeb8f81df6ccd57f3689" +} +], +[ +"type", +{ +"DuckDB": "c752fd9fe2ad3b86b8b899da", +"None": "c752fd9fe2ad3b86b8b899da", +"bigquery": "c752fd9fe2ad3b86b8b899da", +"databricks": "c752fd9fe2ad3b86b8b899da", +"duckdb": "c752fd9fe2ad3b86b8b899da", +"generic": "c752fd9fe2ad3b86b8b899da", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "c752fd9fe2ad3b86b8b899da", +"postgres": "e998cd8f0f74af0526b75ff0", +"postgresql": "e998cd8f0f74af0526b75ff0", +"snowflake": "652ff8b21f638eac8fdc46c5", +"tsql": "c752fd9fe2ad3b86b8b899da" +} +], +[ +"type", +{ +"DuckDB": "01d51e9454e607e1bab153ef", +"None": "01d51e9454e607e1bab153ef", +"bigquery": "01d51e9454e607e1bab153ef", +"databricks": "01d51e9454e607e1bab153ef", +"duckdb": "01d51e9454e607e1bab153ef", +"generic": "01d51e9454e607e1bab153ef", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "01d51e9454e607e1bab153ef", +"postgres": "01d51e9454e607e1bab153ef", +"postgresql": "01d51e9454e607e1bab153ef", +"snowflake": "01d51e9454e607e1bab153ef", +"tsql": "01d51e9454e607e1bab153ef" +} +], +[ +"type", +{ +"DuckDB": "802f1c1fcb97ddd5679172d2", +"None": "802f1c1fcb97ddd5679172d2", +"bigquery": "a428302e4848ffe877284c84", +"databricks": "802f1c1fcb97ddd5679172d2", +"duckdb": "802f1c1fcb97ddd5679172d2", +"generic": "802f1c1fcb97ddd5679172d2", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "802f1c1fcb97ddd5679172d2", +"postgres": "802f1c1fcb97ddd5679172d2", +"postgresql": "802f1c1fcb97ddd5679172d2", +"snowflake": "652ff8b21f638eac8fdc46c5", +"tsql": "08784560ad78e14a02cc066f" +} +], +[ +"type", +{ +"DuckDB": "19a1a80ffc06169f32694de8", +"None": "19a1a80ffc06169f32694de8", +"bigquery": "19a1a80ffc06169f32694de8", +"databricks": "19a1a80ffc06169f32694de8", +"duckdb": "19a1a80ffc06169f32694de8", +"generic": "19a1a80ffc06169f32694de8", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "19a1a80ffc06169f32694de8", +"postgres": "19a1a80ffc06169f32694de8", +"postgresql": "19a1a80ffc06169f32694de8", +"snowflake": "19a1a80ffc06169f32694de8", +"tsql": "19a1a80ffc06169f32694de8" +} +], +[ +"type", +{ +"DuckDB": "ebc821a95b9286e22c2b26d0", +"None": "ebc821a95b9286e22c2b26d0", +"bigquery": "19a1a80ffc06169f32694de8", +"databricks": "ebc821a95b9286e22c2b26d0", +"duckdb": "ebc821a95b9286e22c2b26d0", +"generic": "ebc821a95b9286e22c2b26d0", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "ebc821a95b9286e22c2b26d0", +"postgres": "ebc821a95b9286e22c2b26d0", +"postgresql": "ebc821a95b9286e22c2b26d0", +"snowflake": "ebc821a95b9286e22c2b26d0", +"tsql": "ebc821a95b9286e22c2b26d0" +} +], +[ +"type", +{ +"DuckDB": "fe0bedb7dda0e9247a51fdee", +"None": "fe0bedb7dda0e9247a51fdee", +"bigquery": "fe0bedb7dda0e9247a51fdee", +"databricks": "fe0bedb7dda0e9247a51fdee", +"duckdb": "fe0bedb7dda0e9247a51fdee", +"generic": "fe0bedb7dda0e9247a51fdee", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "fe0bedb7dda0e9247a51fdee", +"postgres": "fe0bedb7dda0e9247a51fdee", +"postgresql": "fe0bedb7dda0e9247a51fdee", +"snowflake": "fe0bedb7dda0e9247a51fdee", +"tsql": "fe0bedb7dda0e9247a51fdee" +} +], +[ +"type", +{ +"DuckDB": "e1250582e271934cbcb2a788", +"None": "e1250582e271934cbcb2a788", +"bigquery": "e1250582e271934cbcb2a788", +"databricks": "e1250582e271934cbcb2a788", +"duckdb": "e1250582e271934cbcb2a788", +"generic": "e1250582e271934cbcb2a788", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "e1250582e271934cbcb2a788", +"postgres": "e1250582e271934cbcb2a788", +"postgresql": "e1250582e271934cbcb2a788", +"snowflake": "e1250582e271934cbcb2a788", +"tsql": "e1250582e271934cbcb2a788" +} +], +[ +"type", +{ +"DuckDB": "dbf9ebbc7016f5ac5df2817e", +"None": "dbf9ebbc7016f5ac5df2817e", +"bigquery": "dbf9ebbc7016f5ac5df2817e", +"databricks": "dbf9ebbc7016f5ac5df2817e", +"duckdb": "dbf9ebbc7016f5ac5df2817e", +"generic": "dbf9ebbc7016f5ac5df2817e", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "dbf9ebbc7016f5ac5df2817e", +"postgres": "dbf9ebbc7016f5ac5df2817e", +"postgresql": "dbf9ebbc7016f5ac5df2817e", +"snowflake": "dbf9ebbc7016f5ac5df2817e", +"tsql": "dbf9ebbc7016f5ac5df2817e" +} +], +[ +"type", +{ +"DuckDB": "aab0389e2b5470136660bf8a", +"None": "aab0389e2b5470136660bf8a", +"bigquery": "c9b810639795a7bfab91b98d", +"databricks": "aab0389e2b5470136660bf8a", +"duckdb": "aab0389e2b5470136660bf8a", +"generic": "aab0389e2b5470136660bf8a", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "aab0389e2b5470136660bf8a", +"postgres": "aab0389e2b5470136660bf8a", +"postgresql": "aab0389e2b5470136660bf8a", +"snowflake": "97a20344d811fb77c7690863", +"tsql": "aab0389e2b5470136660bf8a" +} +], +[ +"type", +{ +"DuckDB": "72bd5e38b32893397eb51579", +"None": "730d7cf7510ba0934828d971", +"bigquery": "730d7cf7510ba0934828d971", +"databricks": "730d7cf7510ba0934828d971", +"duckdb": "72bd5e38b32893397eb51579", +"generic": "730d7cf7510ba0934828d971", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "1bdf5908ca249b2331a0427c", +"postgres": "1bdf5908ca249b2331a0427c", +"postgresql": "1bdf5908ca249b2331a0427c", +"snowflake": "8ff614b7306c0edbe36ce00b", +"tsql": "1bdf5908ca249b2331a0427c" +} +], +[ +"type", +{ +"DuckDB": "b0791f9f270e764eeeb6fb8e", +"None": "c7c38fdeaeb7858a44976f1d", +"bigquery": "cfb4a49a57197b0df1b2e905", +"databricks": "6bd27be6a47ef34ec1defbad", +"duckdb": "b0791f9f270e764eeeb6fb8e", +"generic": "c7c38fdeaeb7858a44976f1d", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "c7c38fdeaeb7858a44976f1d", +"postgres": "4d7604d41e3585ec187dec82", +"postgresql": "4d7604d41e3585ec187dec82", +"snowflake": "c7c38fdeaeb7858a44976f1d", +"tsql": "b0791f9f270e764eeeb6fb8e" +} +], +[ +"type", +{ +"DuckDB": "0b9d9879e289ea9a6a3e3e70", +"None": "0b9d9879e289ea9a6a3e3e70", +"bigquery": "0b9d9879e289ea9a6a3e3e70", +"databricks": "0b9d9879e289ea9a6a3e3e70", +"duckdb": "0b9d9879e289ea9a6a3e3e70", +"generic": "0b9d9879e289ea9a6a3e3e70", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "0b9d9879e289ea9a6a3e3e70", +"postgres": "0b9d9879e289ea9a6a3e3e70", +"postgresql": "0b9d9879e289ea9a6a3e3e70", +"snowflake": "0b9d9879e289ea9a6a3e3e70", +"tsql": "0b9d9879e289ea9a6a3e3e70" +} +], +[ +"type", +{ +"DuckDB": "ba0da7ef018b990fcc83cba1", +"None": "ba0da7ef018b990fcc83cba1", +"bigquery": "ba0da7ef018b990fcc83cba1", +"databricks": "ba0da7ef018b990fcc83cba1", +"duckdb": "ba0da7ef018b990fcc83cba1", +"generic": "ba0da7ef018b990fcc83cba1", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "ba0da7ef018b990fcc83cba1", +"postgres": "ba0da7ef018b990fcc83cba1", +"postgresql": "ba0da7ef018b990fcc83cba1", +"snowflake": "ba0da7ef018b990fcc83cba1", +"tsql": "ba0da7ef018b990fcc83cba1" +} +], +[ +"type", +{ +"DuckDB": "51b0e597909858f7f7aa4571", +"None": "51b0e597909858f7f7aa4571", +"bigquery": "deb9d53b04b7825e460d826a", +"databricks": "846f4ee64c34aab0cdabb9a0", +"duckdb": "51b0e597909858f7f7aa4571", +"generic": "51b0e597909858f7f7aa4571", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "51b0e597909858f7f7aa4571", +"postgres": "51b0e597909858f7f7aa4571", +"postgresql": "51b0e597909858f7f7aa4571", +"snowflake": "50d14e3a5691e6cb8689aa29", +"tsql": "51b0e597909858f7f7aa4571" +} +], +[ +"type", +{ +"DuckDB": "8698d724534891869075175e", +"None": "0017a88bb60ec3403c786ed8", +"bigquery": "2795066c9a71fa3e3780c73b", +"databricks": "0017a88bb60ec3403c786ed8", +"duckdb": "8698d724534891869075175e", +"generic": "0017a88bb60ec3403c786ed8", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "6c03a3450ea4742ee7396e3c", +"postgres": "8698d724534891869075175e", +"postgresql": "8698d724534891869075175e", +"snowflake": "b3b752c645651b849e23d39a", +"tsql": "d1dc9a140dbe2eb1874c6ad7" +} +], +[ +"type", +{ +"DuckDB": "881106a4a0d2de0ff7c56373", +"None": "881106a4a0d2de0ff7c56373", +"bigquery": "881106a4a0d2de0ff7c56373", +"databricks": "881106a4a0d2de0ff7c56373", +"duckdb": "881106a4a0d2de0ff7c56373", +"generic": "881106a4a0d2de0ff7c56373", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "881106a4a0d2de0ff7c56373", +"postgres": "881106a4a0d2de0ff7c56373", +"postgresql": "881106a4a0d2de0ff7c56373", +"snowflake": "881106a4a0d2de0ff7c56373", +"tsql": "881106a4a0d2de0ff7c56373" +} +], +[ +"type", +{ +"DuckDB": "669084d1ea704ae5b8ee05c2", +"None": "669084d1ea704ae5b8ee05c2", +"bigquery": "669084d1ea704ae5b8ee05c2", +"databricks": "669084d1ea704ae5b8ee05c2", +"duckdb": "669084d1ea704ae5b8ee05c2", +"generic": "669084d1ea704ae5b8ee05c2", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "669084d1ea704ae5b8ee05c2", +"postgres": "669084d1ea704ae5b8ee05c2", +"postgresql": "669084d1ea704ae5b8ee05c2", +"snowflake": "669084d1ea704ae5b8ee05c2", +"tsql": "669084d1ea704ae5b8ee05c2" +} +], +[ +"type", +{ +"DuckDB": "013a8446f043affffcf194f8", +"None": "013a8446f043affffcf194f8", +"bigquery": "013a8446f043affffcf194f8", +"databricks": "013a8446f043affffcf194f8", +"duckdb": "013a8446f043affffcf194f8", +"generic": "013a8446f043affffcf194f8", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "013a8446f043affffcf194f8", +"postgres": "013a8446f043affffcf194f8", +"postgresql": "013a8446f043affffcf194f8", +"snowflake": "97a20344d811fb77c7690863", +"tsql": "013a8446f043affffcf194f8" +} +], +[ +"type", +{ +"DuckDB": "804fec6876d0b43935790142", +"None": "804fec6876d0b43935790142", +"bigquery": "804fec6876d0b43935790142", +"databricks": "804fec6876d0b43935790142", +"duckdb": "804fec6876d0b43935790142", +"generic": "804fec6876d0b43935790142", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "804fec6876d0b43935790142", +"postgres": "804fec6876d0b43935790142", +"postgresql": "804fec6876d0b43935790142", +"snowflake": "804fec6876d0b43935790142", +"tsql": "804fec6876d0b43935790142" +} +], +[ +"type", +{ +"DuckDB": "0dcd6a19b7dc6f6b6d4a5006", +"None": "0dcd6a19b7dc6f6b6d4a5006", +"bigquery": "0dcd6a19b7dc6f6b6d4a5006", +"databricks": "0dcd6a19b7dc6f6b6d4a5006", +"duckdb": "0dcd6a19b7dc6f6b6d4a5006", +"generic": "0dcd6a19b7dc6f6b6d4a5006", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "0dcd6a19b7dc6f6b6d4a5006", +"postgres": "0dcd6a19b7dc6f6b6d4a5006", +"postgresql": "0dcd6a19b7dc6f6b6d4a5006", +"snowflake": "0dcd6a19b7dc6f6b6d4a5006", +"tsql": "0dcd6a19b7dc6f6b6d4a5006" +} +], +[ +"type", +{ +"DuckDB": "9d6807d797be08f8376a5a19", +"None": "9d6807d797be08f8376a5a19", +"bigquery": "9d6807d797be08f8376a5a19", +"databricks": "9d6807d797be08f8376a5a19", +"duckdb": "9d6807d797be08f8376a5a19", +"generic": "9d6807d797be08f8376a5a19", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "9d6807d797be08f8376a5a19", +"postgres": "9d6807d797be08f8376a5a19", +"postgresql": "9d6807d797be08f8376a5a19", +"snowflake": "9d6807d797be08f8376a5a19", +"tsql": "9d6807d797be08f8376a5a19" +} +], +[ +"type", +{ +"DuckDB": "3915f3f73328f0838497b2d5", +"None": "3915f3f73328f0838497b2d5", +"bigquery": "946d5ee30ab7469c57d850df", +"databricks": "3915f3f73328f0838497b2d5", +"duckdb": "3915f3f73328f0838497b2d5", +"generic": "3915f3f73328f0838497b2d5", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "3915f3f73328f0838497b2d5", +"postgres": "3915f3f73328f0838497b2d5", +"postgresql": "3915f3f73328f0838497b2d5", +"snowflake": "f43dac38f34a1c0618a3f812", +"tsql": "3915f3f73328f0838497b2d5" +} +], +[ +"type", +{ +"DuckDB": "0dcd6a19b7dc6f6b6d4a5006", +"None": "0dcd6a19b7dc6f6b6d4a5006", +"bigquery": "0dcd6a19b7dc6f6b6d4a5006", +"databricks": "0dcd6a19b7dc6f6b6d4a5006", +"duckdb": "0dcd6a19b7dc6f6b6d4a5006", +"generic": "0dcd6a19b7dc6f6b6d4a5006", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "0dcd6a19b7dc6f6b6d4a5006", +"postgres": "0dcd6a19b7dc6f6b6d4a5006", +"postgresql": "0dcd6a19b7dc6f6b6d4a5006", +"snowflake": "0dcd6a19b7dc6f6b6d4a5006", +"tsql": "0dcd6a19b7dc6f6b6d4a5006" +} +], +[ +"type", +{ +"DuckDB": "fe23594c781e79cbb0c8927a", +"None": "fe23594c781e79cbb0c8927a", +"bigquery": "fe23594c781e79cbb0c8927a", +"databricks": "fe23594c781e79cbb0c8927a", +"duckdb": "fe23594c781e79cbb0c8927a", +"generic": "fe23594c781e79cbb0c8927a", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "fe23594c781e79cbb0c8927a", +"postgres": "fe23594c781e79cbb0c8927a", +"postgresql": "fe23594c781e79cbb0c8927a", +"snowflake": "38b2ec94bf02be40007ce525", +"tsql": "fe23594c781e79cbb0c8927a" +} +], +[ +"type", +{ +"DuckDB": "d03c5e5797a8cbc0c6a81112", +"None": "d03c5e5797a8cbc0c6a81112", +"bigquery": "d03c5e5797a8cbc0c6a81112", +"databricks": "d03c5e5797a8cbc0c6a81112", +"duckdb": "d03c5e5797a8cbc0c6a81112", +"generic": "d03c5e5797a8cbc0c6a81112", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "d03c5e5797a8cbc0c6a81112", +"postgres": "d03c5e5797a8cbc0c6a81112", +"postgresql": "d03c5e5797a8cbc0c6a81112", +"snowflake": "d03c5e5797a8cbc0c6a81112", +"tsql": "d03c5e5797a8cbc0c6a81112" +} +], +[ +"type", +{ +"DuckDB": "6cffd1617edd6454241ee732", +"None": "6cffd1617edd6454241ee732", +"bigquery": "6cffd1617edd6454241ee732", +"databricks": "6cffd1617edd6454241ee732", +"duckdb": "6cffd1617edd6454241ee732", +"generic": "6cffd1617edd6454241ee732", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "6cffd1617edd6454241ee732", +"postgres": "6cffd1617edd6454241ee732", +"postgresql": "6cffd1617edd6454241ee732", +"snowflake": "6cffd1617edd6454241ee732", +"tsql": "6cffd1617edd6454241ee732" +} +], +[ +"type", +{ +"DuckDB": "815698ef0c2515c76f250086", +"None": "98d56a64e9a7ee905a58c95c", +"bigquery": "98d56a64e9a7ee905a58c95c", +"databricks": "98d56a64e9a7ee905a58c95c", +"duckdb": "815698ef0c2515c76f250086", +"generic": "98d56a64e9a7ee905a58c95c", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "6c03a3450ea4742ee7396e3c", +"postgres": "815698ef0c2515c76f250086", +"postgresql": "815698ef0c2515c76f250086", +"snowflake": "822641f83fbdcddae47b409f", +"tsql": "b34cea19c30a73dc21f7a04c" +} +], +[ +"type", +{ +"DuckDB": "1275b5b0c52f69cf592c004b", +"None": "1275b5b0c52f69cf592c004b", +"bigquery": "1275b5b0c52f69cf592c004b", +"databricks": "1275b5b0c52f69cf592c004b", +"duckdb": "1275b5b0c52f69cf592c004b", +"generic": "1275b5b0c52f69cf592c004b", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "1275b5b0c52f69cf592c004b", +"postgres": "1275b5b0c52f69cf592c004b", +"postgresql": "1275b5b0c52f69cf592c004b", +"snowflake": "1275b5b0c52f69cf592c004b", +"tsql": "1275b5b0c52f69cf592c004b" +} +], +[ +"type", +{ +"DuckDB": "80d6c9c5f502ef25b9434309", +"None": "80d6c9c5f502ef25b9434309", +"bigquery": "80d6c9c5f502ef25b9434309", +"databricks": "80d6c9c5f502ef25b9434309", +"duckdb": "80d6c9c5f502ef25b9434309", +"generic": "80d6c9c5f502ef25b9434309", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "80d6c9c5f502ef25b9434309", +"postgres": "80d6c9c5f502ef25b9434309", +"postgresql": "80d6c9c5f502ef25b9434309", +"snowflake": "80d6c9c5f502ef25b9434309", +"tsql": "80d6c9c5f502ef25b9434309" +} +], +[ +"type", +{ +"DuckDB": "42f6a9fe8a8cc486c2c77ae1", +"None": "42f6a9fe8a8cc486c2c77ae1", +"bigquery": "42f6a9fe8a8cc486c2c77ae1", +"databricks": "42f6a9fe8a8cc486c2c77ae1", +"duckdb": "42f6a9fe8a8cc486c2c77ae1", +"generic": "42f6a9fe8a8cc486c2c77ae1", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "42f6a9fe8a8cc486c2c77ae1", +"postgres": "42f6a9fe8a8cc486c2c77ae1", +"postgresql": "42f6a9fe8a8cc486c2c77ae1", +"snowflake": "42f6a9fe8a8cc486c2c77ae1", +"tsql": "42f6a9fe8a8cc486c2c77ae1" +} +], +[ +"type", +{ +"DuckDB": "7894730ae1c06f4ea3920947", +"None": "7894730ae1c06f4ea3920947", +"bigquery": "7894730ae1c06f4ea3920947", +"databricks": "7894730ae1c06f4ea3920947", +"duckdb": "7894730ae1c06f4ea3920947", +"generic": "7894730ae1c06f4ea3920947", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "7894730ae1c06f4ea3920947", +"postgres": "7894730ae1c06f4ea3920947", +"postgresql": "7894730ae1c06f4ea3920947", +"snowflake": "7894730ae1c06f4ea3920947", +"tsql": "7894730ae1c06f4ea3920947" +} +], +[ +"type", +{ +"DuckDB": "f0c468b3e6d6df98b4358aff", +"None": "752ae7fc618de4a182e18bd3", +"bigquery": "752ae7fc618de4a182e18bd3", +"databricks": "aa5bc52ba6ea9e0a428084da", +"duckdb": "f0c468b3e6d6df98b4358aff", +"generic": "752ae7fc618de4a182e18bd3", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "6c03a3450ea4742ee7396e3c", +"postgres": "f0c468b3e6d6df98b4358aff", +"postgresql": "f0c468b3e6d6df98b4358aff", +"snowflake": "6dc518f5329c32ce13bfa506", +"tsql": "d1dc9a140dbe2eb1874c6ad7" +} +], +[ +"type", +{ +"DuckDB": "9829fa9011a92bb968bb5996", +"None": "9829fa9011a92bb968bb5996", +"bigquery": "9829fa9011a92bb968bb5996", +"databricks": "9829fa9011a92bb968bb5996", +"duckdb": "9829fa9011a92bb968bb5996", +"generic": "9829fa9011a92bb968bb5996", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "9829fa9011a92bb968bb5996", +"postgres": "9829fa9011a92bb968bb5996", +"postgresql": "9829fa9011a92bb968bb5996", +"snowflake": "9829fa9011a92bb968bb5996", +"tsql": "9829fa9011a92bb968bb5996" +} +], +[ +"type", +{ +"DuckDB": "c50a316d091c821866e4bfba", +"None": "c50a316d091c821866e4bfba", +"bigquery": "c50a316d091c821866e4bfba", +"databricks": "c50a316d091c821866e4bfba", +"duckdb": "c50a316d091c821866e4bfba", +"generic": "c50a316d091c821866e4bfba", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "c50a316d091c821866e4bfba", +"postgres": "c50a316d091c821866e4bfba", +"postgresql": "c50a316d091c821866e4bfba", +"snowflake": "c50a316d091c821866e4bfba", +"tsql": "c50a316d091c821866e4bfba" +} +], +[ +"type", +{ +"DuckDB": "c50a316d091c821866e4bfba", +"None": "c50a316d091c821866e4bfba", +"bigquery": "c50a316d091c821866e4bfba", +"databricks": "c50a316d091c821866e4bfba", +"duckdb": "c50a316d091c821866e4bfba", +"generic": "c50a316d091c821866e4bfba", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "c50a316d091c821866e4bfba", +"postgres": "c50a316d091c821866e4bfba", +"postgresql": "c50a316d091c821866e4bfba", +"snowflake": "c50a316d091c821866e4bfba", +"tsql": "c50a316d091c821866e4bfba" +} +], +[ +"type", +{ +"DuckDB": "0ca1be8f7d61ca627e620450", +"None": "0ca1be8f7d61ca627e620450", +"bigquery": "e1c36a5cdd2427ff2b089ac9", +"databricks": "0ca1be8f7d61ca627e620450", +"duckdb": "0ca1be8f7d61ca627e620450", +"generic": "0ca1be8f7d61ca627e620450", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "0ca1be8f7d61ca627e620450", +"postgres": "0ca1be8f7d61ca627e620450", +"postgresql": "0ca1be8f7d61ca627e620450", +"snowflake": "18db5afe2c1e80d1ee652b54", +"tsql": "0ca1be8f7d61ca627e620450" +} +], +[ +"type", +{ +"DuckDB": "c50a316d091c821866e4bfba", +"None": "c50a316d091c821866e4bfba", +"bigquery": "c50a316d091c821866e4bfba", +"databricks": "c50a316d091c821866e4bfba", +"duckdb": "c50a316d091c821866e4bfba", +"generic": "c50a316d091c821866e4bfba", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "c50a316d091c821866e4bfba", +"postgres": "c50a316d091c821866e4bfba", +"postgresql": "c50a316d091c821866e4bfba", +"snowflake": "c50a316d091c821866e4bfba", +"tsql": "c50a316d091c821866e4bfba" +} +], +[ +"type", +{ +"DuckDB": "19a1a80ffc06169f32694de8", +"None": "19a1a80ffc06169f32694de8", +"bigquery": "19a1a80ffc06169f32694de8", +"databricks": "19a1a80ffc06169f32694de8", +"duckdb": "19a1a80ffc06169f32694de8", +"generic": "19a1a80ffc06169f32694de8", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "19a1a80ffc06169f32694de8", +"postgres": "19a1a80ffc06169f32694de8", +"postgresql": "19a1a80ffc06169f32694de8", +"snowflake": "19a1a80ffc06169f32694de8", +"tsql": "19a1a80ffc06169f32694de8" +} +], +[ +"type", +{ +"DuckDB": "8993aba016a0adde404608e3", +"None": "8993aba016a0adde404608e3", +"bigquery": "8993aba016a0adde404608e3", +"databricks": "8993aba016a0adde404608e3", +"duckdb": "8993aba016a0adde404608e3", +"generic": "8993aba016a0adde404608e3", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "8993aba016a0adde404608e3", +"postgres": "8993aba016a0adde404608e3", +"postgresql": "8993aba016a0adde404608e3", +"snowflake": "8993aba016a0adde404608e3", +"tsql": "8993aba016a0adde404608e3" +} +], +[ +"type", +{ +"DuckDB": "837168a49b84e7ed918ea148", +"None": "837168a49b84e7ed918ea148", +"bigquery": "837168a49b84e7ed918ea148", +"databricks": "837168a49b84e7ed918ea148", +"duckdb": "837168a49b84e7ed918ea148", +"generic": "837168a49b84e7ed918ea148", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "837168a49b84e7ed918ea148", +"postgres": "837168a49b84e7ed918ea148", +"postgresql": "837168a49b84e7ed918ea148", +"snowflake": "837168a49b84e7ed918ea148", +"tsql": "837168a49b84e7ed918ea148" +} +], +[ +"type", +{ +"DuckDB": "3915f3f73328f0838497b2d5", +"None": "3915f3f73328f0838497b2d5", +"bigquery": "946d5ee30ab7469c57d850df", +"databricks": "3915f3f73328f0838497b2d5", +"duckdb": "3915f3f73328f0838497b2d5", +"generic": "3915f3f73328f0838497b2d5", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "3915f3f73328f0838497b2d5", +"postgres": "3915f3f73328f0838497b2d5", +"postgresql": "3915f3f73328f0838497b2d5", +"snowflake": "f43dac38f34a1c0618a3f812", +"tsql": "3915f3f73328f0838497b2d5" +} +], +[ +"type", +{ +"DuckDB": "d61c83ef8bfdf043fa672cb5", +"None": "d61c83ef8bfdf043fa672cb5", +"bigquery": "c9b810639795a7bfab91b98d", +"databricks": "d61c83ef8bfdf043fa672cb5", +"duckdb": "d61c83ef8bfdf043fa672cb5", +"generic": "d61c83ef8bfdf043fa672cb5", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "d61c83ef8bfdf043fa672cb5", +"postgres": "d61c83ef8bfdf043fa672cb5", +"postgresql": "d61c83ef8bfdf043fa672cb5", +"snowflake": "97a20344d811fb77c7690863", +"tsql": "d61c83ef8bfdf043fa672cb5" +} +], +[ +"type", +{ +"DuckDB": "2bfa352725f9d8a91250f75e", +"None": "2bfa352725f9d8a91250f75e", +"bigquery": "2bfa352725f9d8a91250f75e", +"databricks": "2bfa352725f9d8a91250f75e", +"duckdb": "2bfa352725f9d8a91250f75e", +"generic": "2bfa352725f9d8a91250f75e", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "2bfa352725f9d8a91250f75e", +"postgres": "2bfa352725f9d8a91250f75e", +"postgresql": "2bfa352725f9d8a91250f75e", +"snowflake": "2bfa352725f9d8a91250f75e", +"tsql": "2bfa352725f9d8a91250f75e" +} +], +[ +"type", +{ +"DuckDB": "08736485547ba339930697e9", +"None": "08736485547ba339930697e9", +"bigquery": "08736485547ba339930697e9", +"databricks": "08736485547ba339930697e9", +"duckdb": "08736485547ba339930697e9", +"generic": "08736485547ba339930697e9", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "08736485547ba339930697e9", +"postgres": "08736485547ba339930697e9", +"postgresql": "08736485547ba339930697e9", +"snowflake": "08736485547ba339930697e9", +"tsql": "08736485547ba339930697e9" +} +], +[ +"type", +{ +"DuckDB": "c6889f2965db73017be6f6e7", +"None": "c6889f2965db73017be6f6e7", +"bigquery": "a428302e4848ffe877284c84", +"databricks": "c6889f2965db73017be6f6e7", +"duckdb": "c6889f2965db73017be6f6e7", +"generic": "c6889f2965db73017be6f6e7", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "c6889f2965db73017be6f6e7", +"postgres": "c6889f2965db73017be6f6e7", +"postgresql": "c6889f2965db73017be6f6e7", +"snowflake": "652ff8b21f638eac8fdc46c5", +"tsql": "c6889f2965db73017be6f6e7" +} +], +[ +"type", +{ +"DuckDB": "461923a0d34defd0c726d6e5", +"None": "461923a0d34defd0c726d6e5", +"bigquery": "b5c4d5044b2a6e70633f0d0a", +"databricks": "461923a0d34defd0c726d6e5", +"duckdb": "461923a0d34defd0c726d6e5", +"generic": "461923a0d34defd0c726d6e5", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "461923a0d34defd0c726d6e5", +"postgres": "461923a0d34defd0c726d6e5", +"postgresql": "461923a0d34defd0c726d6e5", +"snowflake": "461923a0d34defd0c726d6e5", +"tsql": "461923a0d34defd0c726d6e5" +} +], +[ +"type", +{ +"DuckDB": "624eb95d280fa0653ec73f7f", +"None": "624eb95d280fa0653ec73f7f", +"bigquery": "624eb95d280fa0653ec73f7f", +"databricks": "624eb95d280fa0653ec73f7f", +"duckdb": "624eb95d280fa0653ec73f7f", +"generic": "624eb95d280fa0653ec73f7f", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "624eb95d280fa0653ec73f7f", +"postgres": "624eb95d280fa0653ec73f7f", +"postgresql": "624eb95d280fa0653ec73f7f", +"snowflake": "624eb95d280fa0653ec73f7f", +"tsql": "624eb95d280fa0653ec73f7f" +} +], +[ +"type", +{ +"DuckDB": "70fb4728c3adcf6dbe4975d5", +"None": "70fb4728c3adcf6dbe4975d5", +"bigquery": "70fb4728c3adcf6dbe4975d5", +"databricks": "70fb4728c3adcf6dbe4975d5", +"duckdb": "70fb4728c3adcf6dbe4975d5", +"generic": "70fb4728c3adcf6dbe4975d5", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "70fb4728c3adcf6dbe4975d5", +"postgres": "70fb4728c3adcf6dbe4975d5", +"postgresql": "70fb4728c3adcf6dbe4975d5", +"snowflake": "70fb4728c3adcf6dbe4975d5", +"tsql": "70fb4728c3adcf6dbe4975d5" +} +], +[ +"type", +{ +"DuckDB": "bce60580ef3a1dc4ce569fff", +"None": "bce60580ef3a1dc4ce569fff", +"bigquery": "bce60580ef3a1dc4ce569fff", +"databricks": "bce60580ef3a1dc4ce569fff", +"duckdb": "bce60580ef3a1dc4ce569fff", +"generic": "bce60580ef3a1dc4ce569fff", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "bce60580ef3a1dc4ce569fff", +"postgres": "bce60580ef3a1dc4ce569fff", +"postgresql": "bce60580ef3a1dc4ce569fff", +"snowflake": "bce60580ef3a1dc4ce569fff", +"tsql": "bce60580ef3a1dc4ce569fff" +} +], +[ +"type", +{ +"DuckDB": "a104f9b34b3d9d798095a6b4", +"None": "a104f9b34b3d9d798095a6b4", +"bigquery": "a104f9b34b3d9d798095a6b4", +"databricks": "a104f9b34b3d9d798095a6b4", +"duckdb": "a104f9b34b3d9d798095a6b4", +"generic": "a104f9b34b3d9d798095a6b4", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "a104f9b34b3d9d798095a6b4", +"postgres": "a104f9b34b3d9d798095a6b4", +"postgresql": "a104f9b34b3d9d798095a6b4", +"snowflake": "a104f9b34b3d9d798095a6b4", +"tsql": "a104f9b34b3d9d798095a6b4" +} +], +[ +"type", +{ +"DuckDB": "858855737713d0cff353f8ac", +"None": "858855737713d0cff353f8ac", +"bigquery": "858855737713d0cff353f8ac", +"databricks": "858855737713d0cff353f8ac", +"duckdb": "858855737713d0cff353f8ac", +"generic": "858855737713d0cff353f8ac", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "858855737713d0cff353f8ac", +"postgres": "858855737713d0cff353f8ac", +"postgresql": "858855737713d0cff353f8ac", +"snowflake": "858855737713d0cff353f8ac", +"tsql": "858855737713d0cff353f8ac" +} +], +[ +"type", +{ +"DuckDB": "62368fc15cefd5807807b209", +"None": "62368fc15cefd5807807b209", +"bigquery": "e6ffdece2977be55da73b59a", +"databricks": "62368fc15cefd5807807b209", +"duckdb": "62368fc15cefd5807807b209", +"generic": "62368fc15cefd5807807b209", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "62368fc15cefd5807807b209", +"postgres": "62368fc15cefd5807807b209", +"postgresql": "62368fc15cefd5807807b209", +"snowflake": "62368fc15cefd5807807b209", +"tsql": "62368fc15cefd5807807b209" +} +], +[ +"type", +{ +"DuckDB": "e57ac1541fb51b362cd5b470", +"None": "e57ac1541fb51b362cd5b470", +"bigquery": "e57ac1541fb51b362cd5b470", +"databricks": "e57ac1541fb51b362cd5b470", +"duckdb": "e57ac1541fb51b362cd5b470", +"generic": "e57ac1541fb51b362cd5b470", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "e57ac1541fb51b362cd5b470", +"postgres": "e57ac1541fb51b362cd5b470", +"postgresql": "e57ac1541fb51b362cd5b470", +"snowflake": "4b356542044f1267fcfc487a", +"tsql": "e57ac1541fb51b362cd5b470" +} +], +[ +"type", +{ +"DuckDB": "4ce8ae479c93f9ff48189fc3", +"None": "4ce8ae479c93f9ff48189fc3", +"bigquery": "4ce8ae479c93f9ff48189fc3", +"databricks": "4ce8ae479c93f9ff48189fc3", +"duckdb": "4ce8ae479c93f9ff48189fc3", +"generic": "4ce8ae479c93f9ff48189fc3", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "4ce8ae479c93f9ff48189fc3", +"postgres": "4ce8ae479c93f9ff48189fc3", +"postgresql": "4ce8ae479c93f9ff48189fc3", +"snowflake": "4ce8ae479c93f9ff48189fc3", +"tsql": "4ce8ae479c93f9ff48189fc3" +} +], +[ +"type", +{ +"DuckDB": "fb5907c56dd752ac5f1dbd95", +"None": "fb5907c56dd752ac5f1dbd95", +"bigquery": "fb5907c56dd752ac5f1dbd95", +"databricks": "fb5907c56dd752ac5f1dbd95", +"duckdb": "fb5907c56dd752ac5f1dbd95", +"generic": "fb5907c56dd752ac5f1dbd95", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "fb5907c56dd752ac5f1dbd95", +"postgres": "fb5907c56dd752ac5f1dbd95", +"postgresql": "fb5907c56dd752ac5f1dbd95", +"snowflake": "fb5907c56dd752ac5f1dbd95", +"tsql": "fb5907c56dd752ac5f1dbd95" +} +], +[ +"type", +{ +"DuckDB": "aab5b077409069695e7d847d", +"None": "aab5b077409069695e7d847d", +"bigquery": "aab5b077409069695e7d847d", +"databricks": "aab5b077409069695e7d847d", +"duckdb": "aab5b077409069695e7d847d", +"generic": "aab5b077409069695e7d847d", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "aab5b077409069695e7d847d", +"postgres": "aab5b077409069695e7d847d", +"postgresql": "aab5b077409069695e7d847d", +"snowflake": "aab5b077409069695e7d847d", +"tsql": "aab5b077409069695e7d847d" +} +], +[ +"type", +{ +"DuckDB": "638ca9212b62ada31a448c62", +"None": "1fec266134381c760a254d16", +"bigquery": "1fec266134381c760a254d16", +"databricks": "1fec266134381c760a254d16", +"duckdb": "638ca9212b62ada31a448c62", +"generic": "1fec266134381c760a254d16", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "1fec266134381c760a254d16", +"postgres": "1fec266134381c760a254d16", +"postgresql": "1fec266134381c760a254d16", +"snowflake": "1fec266134381c760a254d16", +"tsql": "1fec266134381c760a254d16" +} +], +[ +"type", +{ +"DuckDB": "de89632e277dbc8c97115419", +"None": "de89632e277dbc8c97115419", +"bigquery": "de89632e277dbc8c97115419", +"databricks": "de89632e277dbc8c97115419", +"duckdb": "de89632e277dbc8c97115419", +"generic": "de89632e277dbc8c97115419", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "de89632e277dbc8c97115419", +"postgres": "de89632e277dbc8c97115419", +"postgresql": "de89632e277dbc8c97115419", +"snowflake": "4b356542044f1267fcfc487a", +"tsql": "de89632e277dbc8c97115419" +} +], +[ +"type", +{ +"DuckDB": "b1b23029bedaa16e2a6f8516", +"None": "b1b23029bedaa16e2a6f8516", +"bigquery": "b1b23029bedaa16e2a6f8516", +"databricks": "b1b23029bedaa16e2a6f8516", +"duckdb": "b1b23029bedaa16e2a6f8516", +"generic": "b1b23029bedaa16e2a6f8516", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "b1b23029bedaa16e2a6f8516", +"postgres": "b1b23029bedaa16e2a6f8516", +"postgresql": "b1b23029bedaa16e2a6f8516", +"snowflake": "b561884132dbe7e42b719110", +"tsql": "b1b23029bedaa16e2a6f8516" +} +], +[ +"type", +{ +"DuckDB": "111af35848fe500ec2ae54b2", +"None": "111af35848fe500ec2ae54b2", +"bigquery": "c50a316d091c821866e4bfba", +"databricks": "e3bc1b8bad22d8104417b00f", +"duckdb": "111af35848fe500ec2ae54b2", +"generic": "111af35848fe500ec2ae54b2", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "e3bc1b8bad22d8104417b00f", +"postgres": "111af35848fe500ec2ae54b2", +"postgresql": "111af35848fe500ec2ae54b2", +"snowflake": "e3bc1b8bad22d8104417b00f", +"tsql": "111af35848fe500ec2ae54b2" +} +], +[ +"type", +{ +"DuckDB": "a428302e4848ffe877284c84", +"None": "a428302e4848ffe877284c84", +"bigquery": "a428302e4848ffe877284c84", +"databricks": "a428302e4848ffe877284c84", +"duckdb": "a428302e4848ffe877284c84", +"generic": "a428302e4848ffe877284c84", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "a428302e4848ffe877284c84", +"postgres": "a428302e4848ffe877284c84", +"postgresql": "a428302e4848ffe877284c84", +"snowflake": "652ff8b21f638eac8fdc46c5", +"tsql": "a428302e4848ffe877284c84" +} +], +[ +"type", +{ +"DuckDB": "47d74d1b45fedd02ec465220", +"None": "47d74d1b45fedd02ec465220", +"bigquery": "47d74d1b45fedd02ec465220", +"databricks": "47d74d1b45fedd02ec465220", +"duckdb": "47d74d1b45fedd02ec465220", +"generic": "47d74d1b45fedd02ec465220", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "47d74d1b45fedd02ec465220", +"postgres": "47d74d1b45fedd02ec465220", +"postgresql": "47d74d1b45fedd02ec465220", +"snowflake": "47d74d1b45fedd02ec465220", +"tsql": "47d74d1b45fedd02ec465220" +} +], +[ +"type", +{ +"DuckDB": "60a23b7dcae6c79f4de83068", +"None": "60a23b7dcae6c79f4de83068", +"bigquery": "60a23b7dcae6c79f4de83068", +"databricks": "60a23b7dcae6c79f4de83068", +"duckdb": "60a23b7dcae6c79f4de83068", +"generic": "60a23b7dcae6c79f4de83068", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "60a23b7dcae6c79f4de83068", +"postgres": "60a23b7dcae6c79f4de83068", +"postgresql": "60a23b7dcae6c79f4de83068", +"snowflake": "60a23b7dcae6c79f4de83068", +"tsql": "60a23b7dcae6c79f4de83068" +} +], +[ +"type", +{ +"DuckDB": "1879bc874141d9160106e020", +"None": "c513dcc8ed8dfd8935374a47", +"bigquery": "c513dcc8ed8dfd8935374a47", +"databricks": "c513dcc8ed8dfd8935374a47", +"duckdb": "1879bc874141d9160106e020", +"generic": "c513dcc8ed8dfd8935374a47", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "c513dcc8ed8dfd8935374a47", +"postgres": "c513dcc8ed8dfd8935374a47", +"postgresql": "c513dcc8ed8dfd8935374a47", +"snowflake": "c513dcc8ed8dfd8935374a47", +"tsql": "c513dcc8ed8dfd8935374a47" +} +], +[ +"type", +{ +"DuckDB": "2705f19942a4194a72576911", +"None": "2705f19942a4194a72576911", +"bigquery": "6f763a99e9c69109526b40c0", +"databricks": "2705f19942a4194a72576911", +"duckdb": "2705f19942a4194a72576911", +"generic": "2705f19942a4194a72576911", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "2705f19942a4194a72576911", +"postgres": "2705f19942a4194a72576911", +"postgresql": "2705f19942a4194a72576911", +"snowflake": "2705f19942a4194a72576911", +"tsql": "2705f19942a4194a72576911" +} +], +[ +"type", +{ +"DuckDB": "9b1399d4f1923837359745f8", +"None": "9b1399d4f1923837359745f8", +"bigquery": "9b1399d4f1923837359745f8", +"databricks": "9b1399d4f1923837359745f8", +"duckdb": "9b1399d4f1923837359745f8", +"generic": "9b1399d4f1923837359745f8", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "9b1399d4f1923837359745f8", +"postgres": "9b1399d4f1923837359745f8", +"postgresql": "9b1399d4f1923837359745f8", +"snowflake": "9b1399d4f1923837359745f8", +"tsql": "9b1399d4f1923837359745f8" +} +], +[ +"type", +{ +"DuckDB": "c43574432afc90bcba6944b2", +"None": "7040afbb3a088baf55e328b2", +"bigquery": "ba611057434e43344935471b", +"databricks": "ba611057434e43344935471b", +"duckdb": "c43574432afc90bcba6944b2", +"generic": "7040afbb3a088baf55e328b2", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "6c03a3450ea4742ee7396e3c", +"postgres": "1b3243409566f14d81c11fff", +"postgresql": "1b3243409566f14d81c11fff", +"snowflake": "06a9af03923de91e5e27860a", +"tsql": "3866c29c7e0df841d464b98c" +} +], +[ +"type", +{ +"DuckDB": "d229e289e63364bf0d56e920", +"None": "28c3447161aa1c0a550659b8", +"bigquery": "28c3447161aa1c0a550659b8", +"databricks": "b8e50cd0369cf0810e7054be", +"duckdb": "d229e289e63364bf0d56e920", +"generic": "28c3447161aa1c0a550659b8", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "28c3447161aa1c0a550659b8", +"postgres": "28c3447161aa1c0a550659b8", +"postgresql": "28c3447161aa1c0a550659b8", +"snowflake": "d90e8915a295b2cd5e690bd1", +"tsql": "28c3447161aa1c0a550659b8" +} +], +[ +"type", +{ +"DuckDB": "42d4a23d9a52e79d0c3458d3", +"None": "a3acd7ba35e81a800f967bd3", +"bigquery": "3c0719ca5c83e0a20d0b0b42", +"databricks": "a3acd7ba35e81a800f967bd3", +"duckdb": "42d4a23d9a52e79d0c3458d3", +"generic": "a3acd7ba35e81a800f967bd3", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "a3acd7ba35e81a800f967bd3", +"postgres": "a3acd7ba35e81a800f967bd3", +"postgresql": "a3acd7ba35e81a800f967bd3", +"snowflake": "a3acd7ba35e81a800f967bd3", +"tsql": "a3acd7ba35e81a800f967bd3" +} +], +[ +"type", +{ +"DuckDB": "c6106f30f23f392e17eadef4", +"None": "c6106f30f23f392e17eadef4", +"bigquery": "c6106f30f23f392e17eadef4", +"databricks": "c6106f30f23f392e17eadef4", +"duckdb": "c6106f30f23f392e17eadef4", +"generic": "c6106f30f23f392e17eadef4", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "c6106f30f23f392e17eadef4", +"postgres": "c6106f30f23f392e17eadef4", +"postgresql": "c6106f30f23f392e17eadef4", +"snowflake": "c6106f30f23f392e17eadef4", +"tsql": "c6106f30f23f392e17eadef4" +} +], +[ +"type", +{ +"DuckDB": "804fec6876d0b43935790142", +"None": "804fec6876d0b43935790142", +"bigquery": "804fec6876d0b43935790142", +"databricks": "804fec6876d0b43935790142", +"duckdb": "804fec6876d0b43935790142", +"generic": "804fec6876d0b43935790142", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "804fec6876d0b43935790142", +"postgres": "804fec6876d0b43935790142", +"postgresql": "804fec6876d0b43935790142", +"snowflake": "804fec6876d0b43935790142", +"tsql": "804fec6876d0b43935790142" +} +], +[ +"type", +{ +"DuckDB": "79278352c17c9de0f5a28af5", +"None": "79278352c17c9de0f5a28af5", +"bigquery": "c9b810639795a7bfab91b98d", +"databricks": "79278352c17c9de0f5a28af5", +"duckdb": "79278352c17c9de0f5a28af5", +"generic": "79278352c17c9de0f5a28af5", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "79278352c17c9de0f5a28af5", +"postgres": "79278352c17c9de0f5a28af5", +"postgresql": "79278352c17c9de0f5a28af5", +"snowflake": "97a20344d811fb77c7690863", +"tsql": "79278352c17c9de0f5a28af5" +} +], +[ +"type", +{ +"DuckDB": "194c385aa00f52f45426748f", +"None": "7b87db889221e05e13ec3845", +"bigquery": "7b87db889221e05e13ec3845", +"databricks": "7b87db889221e05e13ec3845", +"duckdb": "194c385aa00f52f45426748f", +"generic": "7b87db889221e05e13ec3845", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "7b87db889221e05e13ec3845", +"postgres": "7b87db889221e05e13ec3845", +"postgresql": "7b87db889221e05e13ec3845", +"snowflake": "7b87db889221e05e13ec3845", +"tsql": "7b87db889221e05e13ec3845" +} +], +[ +"type", +{ +"DuckDB": "19a1a80ffc06169f32694de8", +"None": "19a1a80ffc06169f32694de8", +"bigquery": "19a1a80ffc06169f32694de8", +"databricks": "19a1a80ffc06169f32694de8", +"duckdb": "19a1a80ffc06169f32694de8", +"generic": "19a1a80ffc06169f32694de8", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "19a1a80ffc06169f32694de8", +"postgres": "19a1a80ffc06169f32694de8", +"postgresql": "19a1a80ffc06169f32694de8", +"snowflake": "19a1a80ffc06169f32694de8", +"tsql": "19a1a80ffc06169f32694de8" +} +], +[ +"type", +{ +"DuckDB": "c69a366e715a81bca598d475", +"None": "c69a366e715a81bca598d475", +"bigquery": "b5e374ae8299a92b732a3c43", +"databricks": "eb72e9a8e16bab9ee01146ee", +"duckdb": "c69a366e715a81bca598d475", +"generic": "c69a366e715a81bca598d475", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "c69a366e715a81bca598d475", +"postgres": "c69a366e715a81bca598d475", +"postgresql": "c69a366e715a81bca598d475", +"snowflake": "f41d94b0bed9910074641da6", +"tsql": "c69a366e715a81bca598d475" +} +], +[ +"type", +{ +"DuckDB": "558da38ec4d9d5d6c72f60cf", +"None": "558da38ec4d9d5d6c72f60cf", +"bigquery": "e6ffdece2977be55da73b59a", +"databricks": "558da38ec4d9d5d6c72f60cf", +"duckdb": "558da38ec4d9d5d6c72f60cf", +"generic": "558da38ec4d9d5d6c72f60cf", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "558da38ec4d9d5d6c72f60cf", +"postgres": "558da38ec4d9d5d6c72f60cf", +"postgresql": "558da38ec4d9d5d6c72f60cf", +"snowflake": "558da38ec4d9d5d6c72f60cf", +"tsql": "558da38ec4d9d5d6c72f60cf" +} +], +[ +"type", +{ +"DuckDB": "b210f8eb26c37b422f786c6b", +"None": "b210f8eb26c37b422f786c6b", +"bigquery": "88f7cced71c11944260bb54a", +"databricks": "b210f8eb26c37b422f786c6b", +"duckdb": "b210f8eb26c37b422f786c6b", +"generic": "b210f8eb26c37b422f786c6b", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "b210f8eb26c37b422f786c6b", +"postgres": "b210f8eb26c37b422f786c6b", +"postgresql": "b210f8eb26c37b422f786c6b", +"snowflake": "b210f8eb26c37b422f786c6b", +"tsql": "b210f8eb26c37b422f786c6b" +} +], +[ +"type", +{ +"DuckDB": "279ea7f6f6a3910de04b795b", +"None": "279ea7f6f6a3910de04b795b", +"bigquery": "279ea7f6f6a3910de04b795b", +"databricks": "279ea7f6f6a3910de04b795b", +"duckdb": "279ea7f6f6a3910de04b795b", +"generic": "279ea7f6f6a3910de04b795b", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "279ea7f6f6a3910de04b795b", +"postgres": "279ea7f6f6a3910de04b795b", +"postgresql": "279ea7f6f6a3910de04b795b", +"snowflake": "279ea7f6f6a3910de04b795b", +"tsql": "279ea7f6f6a3910de04b795b" +} +], +[ +"type", +{ +"DuckDB": "92e8caae709d951bb8ed59cb", +"None": "92e8caae709d951bb8ed59cb", +"bigquery": "92e8caae709d951bb8ed59cb", +"databricks": "1758ac00dad1bae84521b3fb", +"duckdb": "92e8caae709d951bb8ed59cb", +"generic": "92e8caae709d951bb8ed59cb", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "1758ac00dad1bae84521b3fb", +"postgres": "92e8caae709d951bb8ed59cb", +"postgresql": "92e8caae709d951bb8ed59cb", +"snowflake": "92e8caae709d951bb8ed59cb", +"tsql": "92e8caae709d951bb8ed59cb" +} +], +[ +"type", +{ +"DuckDB": "1eb7fb4e8cf75773c5573562", +"None": "1eb7fb4e8cf75773c5573562", +"bigquery": "c9b810639795a7bfab91b98d", +"databricks": "1eb7fb4e8cf75773c5573562", +"duckdb": "1eb7fb4e8cf75773c5573562", +"generic": "1eb7fb4e8cf75773c5573562", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "1eb7fb4e8cf75773c5573562", +"postgres": "1eb7fb4e8cf75773c5573562", +"postgresql": "1eb7fb4e8cf75773c5573562", +"snowflake": "97a20344d811fb77c7690863", +"tsql": "1eb7fb4e8cf75773c5573562" +} +], +[ +"type", +{ +"DuckDB": "a686bb6db17ab079cfc79224", +"None": "a686bb6db17ab079cfc79224", +"bigquery": "a686bb6db17ab079cfc79224", +"databricks": "a686bb6db17ab079cfc79224", +"duckdb": "a686bb6db17ab079cfc79224", +"generic": "a686bb6db17ab079cfc79224", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "a686bb6db17ab079cfc79224", +"postgres": "a686bb6db17ab079cfc79224", +"postgresql": "a686bb6db17ab079cfc79224", +"snowflake": "1096c3c8687c8e8eb538ff74", +"tsql": "a686bb6db17ab079cfc79224" +} +], +[ +"type", +{ +"DuckDB": "56f06885daf94b4fcc0a624b", +"None": "56f06885daf94b4fcc0a624b", +"bigquery": "56f06885daf94b4fcc0a624b", +"databricks": "56f06885daf94b4fcc0a624b", +"duckdb": "56f06885daf94b4fcc0a624b", +"generic": "56f06885daf94b4fcc0a624b", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "56f06885daf94b4fcc0a624b", +"postgres": "56f06885daf94b4fcc0a624b", +"postgresql": "56f06885daf94b4fcc0a624b", +"snowflake": "56f06885daf94b4fcc0a624b", +"tsql": "56f06885daf94b4fcc0a624b" +} +], +[ +"type", +{ +"DuckDB": "d61c83ef8bfdf043fa672cb5", +"None": "d61c83ef8bfdf043fa672cb5", +"bigquery": "c9b810639795a7bfab91b98d", +"databricks": "d61c83ef8bfdf043fa672cb5", +"duckdb": "d61c83ef8bfdf043fa672cb5", +"generic": "d61c83ef8bfdf043fa672cb5", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "d61c83ef8bfdf043fa672cb5", +"postgres": "d61c83ef8bfdf043fa672cb5", +"postgresql": "d61c83ef8bfdf043fa672cb5", +"snowflake": "97a20344d811fb77c7690863", +"tsql": "d61c83ef8bfdf043fa672cb5" +} +], +[ +"type", +{ +"DuckDB": "0703bf71a54942bdaa28406e", +"None": "0703bf71a54942bdaa28406e", +"bigquery": "a428302e4848ffe877284c84", +"databricks": "0703bf71a54942bdaa28406e", +"duckdb": "0703bf71a54942bdaa28406e", +"generic": "0703bf71a54942bdaa28406e", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "0703bf71a54942bdaa28406e", +"postgres": "0703bf71a54942bdaa28406e", +"postgresql": "0703bf71a54942bdaa28406e", +"snowflake": "652ff8b21f638eac8fdc46c5", +"tsql": "441f377c46ddc162ec0a5976" +} +], +[ +"type", +{ +"DuckDB": "396b2ce32efb5365b393c230", +"None": "e57ac1541fb51b362cd5b470", +"bigquery": "e57ac1541fb51b362cd5b470", +"databricks": "e57ac1541fb51b362cd5b470", +"duckdb": "396b2ce32efb5365b393c230", +"generic": "e57ac1541fb51b362cd5b470", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "e57ac1541fb51b362cd5b470", +"postgres": "e57ac1541fb51b362cd5b470", +"postgresql": "e57ac1541fb51b362cd5b470", +"snowflake": "4b356542044f1267fcfc487a", +"tsql": "e57ac1541fb51b362cd5b470" +} +], +[ +"type", +{ +"DuckDB": "305aaf0b95cee629dd46380c", +"None": "d61c83ef8bfdf043fa672cb5", +"bigquery": "c9b810639795a7bfab91b98d", +"databricks": "d61c83ef8bfdf043fa672cb5", +"duckdb": "305aaf0b95cee629dd46380c", +"generic": "d61c83ef8bfdf043fa672cb5", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "d61c83ef8bfdf043fa672cb5", +"postgres": "d61c83ef8bfdf043fa672cb5", +"postgresql": "d61c83ef8bfdf043fa672cb5", +"snowflake": "97a20344d811fb77c7690863", +"tsql": "d61c83ef8bfdf043fa672cb5" +} +], +[ +"type", +{ +"DuckDB": "669084d1ea704ae5b8ee05c2", +"None": "669084d1ea704ae5b8ee05c2", +"bigquery": "669084d1ea704ae5b8ee05c2", +"databricks": "669084d1ea704ae5b8ee05c2", +"duckdb": "669084d1ea704ae5b8ee05c2", +"generic": "669084d1ea704ae5b8ee05c2", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "669084d1ea704ae5b8ee05c2", +"postgres": "669084d1ea704ae5b8ee05c2", +"postgresql": "669084d1ea704ae5b8ee05c2", +"snowflake": "669084d1ea704ae5b8ee05c2", +"tsql": "669084d1ea704ae5b8ee05c2" +} +], +[ +"type", +{ +"DuckDB": "f7fca17b74cc50ae3de8c826", +"None": "d2c97d221599d038d9875873", +"bigquery": "d2c97d221599d038d9875873", +"databricks": "d2c97d221599d038d9875873", +"duckdb": "f7fca17b74cc50ae3de8c826", +"generic": "d2c97d221599d038d9875873", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "d2c97d221599d038d9875873", +"postgres": "d2c97d221599d038d9875873", +"postgresql": "d2c97d221599d038d9875873", +"snowflake": "d2c97d221599d038d9875873", +"tsql": "d2c97d221599d038d9875873" +} +], +[ +"type", +{ +"DuckDB": "d1dc9a140dbe2eb1874c6ad7", +"None": "d1dc9a140dbe2eb1874c6ad7", +"bigquery": "d1dc9a140dbe2eb1874c6ad7", +"databricks": "d1dc9a140dbe2eb1874c6ad7", +"duckdb": "d1dc9a140dbe2eb1874c6ad7", +"generic": "d1dc9a140dbe2eb1874c6ad7", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "d1dc9a140dbe2eb1874c6ad7", +"postgres": "d1dc9a140dbe2eb1874c6ad7", +"postgresql": "d1dc9a140dbe2eb1874c6ad7", +"snowflake": "d1dc9a140dbe2eb1874c6ad7", +"tsql": "d1dc9a140dbe2eb1874c6ad7" +} +], +[ +"type", +{ +"DuckDB": "4c78bdde0b2dfd77ab71c9e8", +"None": "4c78bdde0b2dfd77ab71c9e8", +"bigquery": "4c78bdde0b2dfd77ab71c9e8", +"databricks": "4c78bdde0b2dfd77ab71c9e8", +"duckdb": "4c78bdde0b2dfd77ab71c9e8", +"generic": "4c78bdde0b2dfd77ab71c9e8", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "4c78bdde0b2dfd77ab71c9e8", +"postgres": "4c78bdde0b2dfd77ab71c9e8", +"postgresql": "4c78bdde0b2dfd77ab71c9e8", +"snowflake": "4c78bdde0b2dfd77ab71c9e8", +"tsql": "4c78bdde0b2dfd77ab71c9e8" +} +], +[ +"type", +{ +"DuckDB": "3f71ab5f3c1c040da96f2cec", +"None": "3f71ab5f3c1c040da96f2cec", +"bigquery": "3f71ab5f3c1c040da96f2cec", +"databricks": "3f71ab5f3c1c040da96f2cec", +"duckdb": "3f71ab5f3c1c040da96f2cec", +"generic": "3f71ab5f3c1c040da96f2cec", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "3f71ab5f3c1c040da96f2cec", +"postgres": "3f71ab5f3c1c040da96f2cec", +"postgresql": "3f71ab5f3c1c040da96f2cec", +"snowflake": "3f71ab5f3c1c040da96f2cec", +"tsql": "3f71ab5f3c1c040da96f2cec" +} +], +[ +"type", +{ +"DuckDB": "8a3f094f18fb4047f0febf59", +"None": "8a3f094f18fb4047f0febf59", +"bigquery": "5c28019dce48a74708c90a76", +"databricks": "8a3f094f18fb4047f0febf59", +"duckdb": "8a3f094f18fb4047f0febf59", +"generic": "8a3f094f18fb4047f0febf59", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "5c28019dce48a74708c90a76", +"postgres": "8a3f094f18fb4047f0febf59", +"postgresql": "8a3f094f18fb4047f0febf59", +"snowflake": "850deea990b52b82b36a9848", +"tsql": "cc8534b198fe0c225bbffd8d" +} +], +[ +"type", +{ +"DuckDB": "f46cf4b4e131aa122b5b33d6", +"None": "f46cf4b4e131aa122b5b33d6", +"bigquery": "f46cf4b4e131aa122b5b33d6", +"databricks": "f46cf4b4e131aa122b5b33d6", +"duckdb": "f46cf4b4e131aa122b5b33d6", +"generic": "f46cf4b4e131aa122b5b33d6", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "f46cf4b4e131aa122b5b33d6", +"postgres": "f46cf4b4e131aa122b5b33d6", +"postgresql": "f46cf4b4e131aa122b5b33d6", +"snowflake": "f46cf4b4e131aa122b5b33d6", +"tsql": "f46cf4b4e131aa122b5b33d6" +} +], +[ +"type", +{ +"DuckDB": "f43dac38f34a1c0618a3f812", +"None": "f43dac38f34a1c0618a3f812", +"bigquery": "946d5ee30ab7469c57d850df", +"databricks": "f43dac38f34a1c0618a3f812", +"duckdb": "f43dac38f34a1c0618a3f812", +"generic": "f43dac38f34a1c0618a3f812", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "f43dac38f34a1c0618a3f812", +"postgres": "f43dac38f34a1c0618a3f812", +"postgresql": "f43dac38f34a1c0618a3f812", +"snowflake": "f43dac38f34a1c0618a3f812", +"tsql": "f43dac38f34a1c0618a3f812" +} +], +[ +"type", +{ +"DuckDB": "6eb49ceb88fcb2297831ca05", +"None": "6eb49ceb88fcb2297831ca05", +"bigquery": "6eb49ceb88fcb2297831ca05", +"databricks": "6eb49ceb88fcb2297831ca05", +"duckdb": "6eb49ceb88fcb2297831ca05", +"generic": "6eb49ceb88fcb2297831ca05", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "6eb49ceb88fcb2297831ca05", +"postgres": "6eb49ceb88fcb2297831ca05", +"postgresql": "6eb49ceb88fcb2297831ca05", +"snowflake": "6eb49ceb88fcb2297831ca05", +"tsql": "6eb49ceb88fcb2297831ca05" +} +], +[ +"type", +{ +"DuckDB": "853b2c0ad6ea4565b1e301e8", +"None": "853b2c0ad6ea4565b1e301e8", +"bigquery": "853b2c0ad6ea4565b1e301e8", +"databricks": "853b2c0ad6ea4565b1e301e8", +"duckdb": "853b2c0ad6ea4565b1e301e8", +"generic": "853b2c0ad6ea4565b1e301e8", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "853b2c0ad6ea4565b1e301e8", +"postgres": "853b2c0ad6ea4565b1e301e8", +"postgresql": "853b2c0ad6ea4565b1e301e8", +"snowflake": "853b2c0ad6ea4565b1e301e8", +"tsql": "853b2c0ad6ea4565b1e301e8" +} +], +[ +"type", +{ +"DuckDB": "e2879cf4770e7f48d2dd704a", +"None": "e2879cf4770e7f48d2dd704a", +"bigquery": "c9b810639795a7bfab91b98d", +"databricks": "e2879cf4770e7f48d2dd704a", +"duckdb": "e2879cf4770e7f48d2dd704a", +"generic": "e2879cf4770e7f48d2dd704a", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "e2879cf4770e7f48d2dd704a", +"postgres": "e2879cf4770e7f48d2dd704a", +"postgresql": "e2879cf4770e7f48d2dd704a", +"snowflake": "97a20344d811fb77c7690863", +"tsql": "e2879cf4770e7f48d2dd704a" +} +], +[ +"type", +{ +"DuckDB": "1558a2a87f510cca4baaad5b", +"None": "1558a2a87f510cca4baaad5b", +"bigquery": "1558a2a87f510cca4baaad5b", +"databricks": "1558a2a87f510cca4baaad5b", +"duckdb": "1558a2a87f510cca4baaad5b", +"generic": "1558a2a87f510cca4baaad5b", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "1558a2a87f510cca4baaad5b", +"postgres": "1558a2a87f510cca4baaad5b", +"postgresql": "1558a2a87f510cca4baaad5b", +"snowflake": "67b5874a2c569226c490211f", +"tsql": "1558a2a87f510cca4baaad5b" +} +], +[ +"type", +{ +"DuckDB": "8441d00030df06ad6a5534d3", +"None": "8441d00030df06ad6a5534d3", +"bigquery": "c9b810639795a7bfab91b98d", +"databricks": "8441d00030df06ad6a5534d3", +"duckdb": "8441d00030df06ad6a5534d3", +"generic": "8441d00030df06ad6a5534d3", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "8441d00030df06ad6a5534d3", +"postgres": "8441d00030df06ad6a5534d3", +"postgresql": "8441d00030df06ad6a5534d3", +"snowflake": "97a20344d811fb77c7690863", +"tsql": "8441d00030df06ad6a5534d3" +} +], +[ +"type", +{ +"DuckDB": "f43dac38f34a1c0618a3f812", +"None": "f43dac38f34a1c0618a3f812", +"bigquery": "946d5ee30ab7469c57d850df", +"databricks": "f43dac38f34a1c0618a3f812", +"duckdb": "f43dac38f34a1c0618a3f812", +"generic": "f43dac38f34a1c0618a3f812", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "f43dac38f34a1c0618a3f812", +"postgres": "f43dac38f34a1c0618a3f812", +"postgresql": "f43dac38f34a1c0618a3f812", +"snowflake": "f43dac38f34a1c0618a3f812", +"tsql": "f43dac38f34a1c0618a3f812" +} +], +[ +"type", +{ +"DuckDB": "c50a316d091c821866e4bfba", +"None": "c50a316d091c821866e4bfba", +"bigquery": "c50a316d091c821866e4bfba", +"databricks": "c50a316d091c821866e4bfba", +"duckdb": "c50a316d091c821866e4bfba", +"generic": "c50a316d091c821866e4bfba", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "c50a316d091c821866e4bfba", +"postgres": "c50a316d091c821866e4bfba", +"postgresql": "c50a316d091c821866e4bfba", +"snowflake": "c50a316d091c821866e4bfba", +"tsql": "c50a316d091c821866e4bfba" +} +], +[ +"type", +{ +"DuckDB": "d043825e95555167dc033b5f", +"None": "d043825e95555167dc033b5f", +"bigquery": "d043825e95555167dc033b5f", +"databricks": "d043825e95555167dc033b5f", +"duckdb": "d043825e95555167dc033b5f", +"generic": "d043825e95555167dc033b5f", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "d043825e95555167dc033b5f", +"postgres": "d043825e95555167dc033b5f", +"postgresql": "d043825e95555167dc033b5f", +"snowflake": "d043825e95555167dc033b5f", +"tsql": "d043825e95555167dc033b5f" +} +], +[ +"type", +{ +"DuckDB": "6a2162b5abe5a73734c47041", +"None": "6a2162b5abe5a73734c47041", +"bigquery": "266b57bc7351f5093413db07", +"databricks": "84e86bec7646b6ad19ceef59", +"duckdb": "6a2162b5abe5a73734c47041", +"generic": "6a2162b5abe5a73734c47041", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "6a2162b5abe5a73734c47041", +"postgres": "6a2162b5abe5a73734c47041", +"postgresql": "6a2162b5abe5a73734c47041", +"snowflake": "16d902e899040d0c0c9dcf58", +"tsql": "6a2162b5abe5a73734c47041" +} +], +[ +"type", +{ +"DuckDB": "56245289768b0fb155df9ffd", +"None": "56245289768b0fb155df9ffd", +"bigquery": "56245289768b0fb155df9ffd", +"databricks": "56245289768b0fb155df9ffd", +"duckdb": "56245289768b0fb155df9ffd", +"generic": "56245289768b0fb155df9ffd", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "56245289768b0fb155df9ffd", +"postgres": "56245289768b0fb155df9ffd", +"postgresql": "56245289768b0fb155df9ffd", +"snowflake": "56245289768b0fb155df9ffd", +"tsql": "56245289768b0fb155df9ffd" +} +], +[ +"type", +{ +"DuckDB": "5abf4ec799a2ec32fb10da7e", +"None": "5abf4ec799a2ec32fb10da7e", +"bigquery": "5abf4ec799a2ec32fb10da7e", +"databricks": "5abf4ec799a2ec32fb10da7e", +"duckdb": "5abf4ec799a2ec32fb10da7e", +"generic": "5abf4ec799a2ec32fb10da7e", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "5abf4ec799a2ec32fb10da7e", +"postgres": "5abf4ec799a2ec32fb10da7e", +"postgresql": "5abf4ec799a2ec32fb10da7e", +"snowflake": "a5656d70e208254d1d3e9b4f", +"tsql": "5abf4ec799a2ec32fb10da7e" +} +], +[ +"type", +{ +"DuckDB": "362b5422259610d45387d0ab", +"None": "362b5422259610d45387d0ab", +"bigquery": "362b5422259610d45387d0ab", +"databricks": "362b5422259610d45387d0ab", +"duckdb": "362b5422259610d45387d0ab", +"generic": "362b5422259610d45387d0ab", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "362b5422259610d45387d0ab", +"postgres": "362b5422259610d45387d0ab", +"postgresql": "362b5422259610d45387d0ab", +"snowflake": "362b5422259610d45387d0ab", +"tsql": "362b5422259610d45387d0ab" +} +], +[ +"type", +{ +"DuckDB": "b2c9b6ebca6c097f3caa0aa8", +"None": "b2c9b6ebca6c097f3caa0aa8", +"bigquery": "b2c9b6ebca6c097f3caa0aa8", +"databricks": "b2c9b6ebca6c097f3caa0aa8", +"duckdb": "b2c9b6ebca6c097f3caa0aa8", +"generic": "b2c9b6ebca6c097f3caa0aa8", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "b2c9b6ebca6c097f3caa0aa8", +"postgres": "b2c9b6ebca6c097f3caa0aa8", +"postgresql": "b2c9b6ebca6c097f3caa0aa8", +"snowflake": "b2c9b6ebca6c097f3caa0aa8", +"tsql": "b2c9b6ebca6c097f3caa0aa8" +} +], +[ +"type", +{ +"DuckDB": "25f9faed41d5d23ca3fa8175", +"None": "25f9faed41d5d23ca3fa8175", +"bigquery": "122a82cc999a6e522d790b87", +"databricks": "b2c07944c578e7e9c9297bd8", +"duckdb": "25f9faed41d5d23ca3fa8175", +"generic": "25f9faed41d5d23ca3fa8175", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "25f9faed41d5d23ca3fa8175", +"postgres": "25f9faed41d5d23ca3fa8175", +"postgresql": "25f9faed41d5d23ca3fa8175", +"snowflake": "fc6c5aa7025d9a737c71c606", +"tsql": "4b6a4cbc7837ba2c70c2affb" +} +], +[ +"type", +{ +"DuckDB": "19bdd92ea0cc5fb028657510", +"None": "78b2cf275c640af54feeca31", +"bigquery": "78b2cf275c640af54feeca31", +"databricks": "1e75e5227bea0ae294ac7af1", +"duckdb": "19bdd92ea0cc5fb028657510", +"generic": "78b2cf275c640af54feeca31", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "19bdd92ea0cc5fb028657510", +"postgres": "78b2cf275c640af54feeca31", +"postgresql": "78b2cf275c640af54feeca31", +"snowflake": "8ff614b7306c0edbe36ce00b", +"tsql": "78b2cf275c640af54feeca31" +} +], +[ +"type", +{ +"DuckDB": "f7fca17b74cc50ae3de8c826", +"None": "f7fca17b74cc50ae3de8c826", +"bigquery": "f7fca17b74cc50ae3de8c826", +"databricks": "f7fca17b74cc50ae3de8c826", +"duckdb": "f7fca17b74cc50ae3de8c826", +"generic": "f7fca17b74cc50ae3de8c826", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "f7fca17b74cc50ae3de8c826", +"postgres": "f7fca17b74cc50ae3de8c826", +"postgresql": "f7fca17b74cc50ae3de8c826", +"snowflake": "55155766823b6a3a5e882fc2", +"tsql": "f7fca17b74cc50ae3de8c826" +} +], +[ +"type", +{ +"DuckDB": "e7a76004da6461a939ce5fef", +"None": "e7a76004da6461a939ce5fef", +"bigquery": "e7a76004da6461a939ce5fef", +"databricks": "e7a76004da6461a939ce5fef", +"duckdb": "e7a76004da6461a939ce5fef", +"generic": "e7a76004da6461a939ce5fef", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "e7a76004da6461a939ce5fef", +"postgres": "e7a76004da6461a939ce5fef", +"postgresql": "e7a76004da6461a939ce5fef", +"snowflake": "e7a76004da6461a939ce5fef", +"tsql": "e7a76004da6461a939ce5fef" +} +], +[ +"type", +{ +"DuckDB": "60a23b7dcae6c79f4de83068", +"None": "60a23b7dcae6c79f4de83068", +"bigquery": "60a23b7dcae6c79f4de83068", +"databricks": "60a23b7dcae6c79f4de83068", +"duckdb": "60a23b7dcae6c79f4de83068", +"generic": "60a23b7dcae6c79f4de83068", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "60a23b7dcae6c79f4de83068", +"postgres": "60a23b7dcae6c79f4de83068", +"postgresql": "60a23b7dcae6c79f4de83068", +"snowflake": "60a23b7dcae6c79f4de83068", +"tsql": "60a23b7dcae6c79f4de83068" +} +], +[ +"type", +{ +"DuckDB": "a47af75c6582f749e1d2b2e7", +"None": "a47af75c6582f749e1d2b2e7", +"bigquery": "a47af75c6582f749e1d2b2e7", +"databricks": "a47af75c6582f749e1d2b2e7", +"duckdb": "a47af75c6582f749e1d2b2e7", +"generic": "a47af75c6582f749e1d2b2e7", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "a47af75c6582f749e1d2b2e7", +"postgres": "a47af75c6582f749e1d2b2e7", +"postgresql": "a47af75c6582f749e1d2b2e7", +"snowflake": "a47af75c6582f749e1d2b2e7", +"tsql": "a47af75c6582f749e1d2b2e7" +} +], +[ +"type", +{ +"DuckDB": "d61c83ef8bfdf043fa672cb5", +"None": "d61c83ef8bfdf043fa672cb5", +"bigquery": "c9b810639795a7bfab91b98d", +"databricks": "d61c83ef8bfdf043fa672cb5", +"duckdb": "d61c83ef8bfdf043fa672cb5", +"generic": "d61c83ef8bfdf043fa672cb5", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "d61c83ef8bfdf043fa672cb5", +"postgres": "d61c83ef8bfdf043fa672cb5", +"postgresql": "d61c83ef8bfdf043fa672cb5", +"snowflake": "97a20344d811fb77c7690863", +"tsql": "d61c83ef8bfdf043fa672cb5" +} +], +[ +"type", +{ +"DuckDB": "70fb4728c3adcf6dbe4975d5", +"None": "70fb4728c3adcf6dbe4975d5", +"bigquery": "70fb4728c3adcf6dbe4975d5", +"databricks": "70fb4728c3adcf6dbe4975d5", +"duckdb": "70fb4728c3adcf6dbe4975d5", +"generic": "70fb4728c3adcf6dbe4975d5", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "70fb4728c3adcf6dbe4975d5", +"postgres": "70fb4728c3adcf6dbe4975d5", +"postgresql": "70fb4728c3adcf6dbe4975d5", +"snowflake": "70fb4728c3adcf6dbe4975d5", +"tsql": "70fb4728c3adcf6dbe4975d5" +} +], +[ +"type", +{ +"DuckDB": "e1c74d96ac578f9323bf1bbd", +"None": "e1c74d96ac578f9323bf1bbd", +"bigquery": "e1c74d96ac578f9323bf1bbd", +"databricks": "e1c74d96ac578f9323bf1bbd", +"duckdb": "e1c74d96ac578f9323bf1bbd", +"generic": "e1c74d96ac578f9323bf1bbd", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "e1c74d96ac578f9323bf1bbd", +"postgres": "e1c74d96ac578f9323bf1bbd", +"postgresql": "e1c74d96ac578f9323bf1bbd", +"snowflake": "e1c74d96ac578f9323bf1bbd", +"tsql": "e1c74d96ac578f9323bf1bbd" +} +], +[ +"type", +{ +"DuckDB": "200c00626c910f6fd6177bb5", +"None": "200c00626c910f6fd6177bb5", +"bigquery": "200c00626c910f6fd6177bb5", +"databricks": "200c00626c910f6fd6177bb5", +"duckdb": "200c00626c910f6fd6177bb5", +"generic": "200c00626c910f6fd6177bb5", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "200c00626c910f6fd6177bb5", +"postgres": "200c00626c910f6fd6177bb5", +"postgresql": "200c00626c910f6fd6177bb5", +"snowflake": "200c00626c910f6fd6177bb5", +"tsql": "200c00626c910f6fd6177bb5" +} +], +[ +"type", +{ +"DuckDB": "c50a316d091c821866e4bfba", +"None": "c50a316d091c821866e4bfba", +"bigquery": "c50a316d091c821866e4bfba", +"databricks": "c50a316d091c821866e4bfba", +"duckdb": "c50a316d091c821866e4bfba", +"generic": "c50a316d091c821866e4bfba", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "c50a316d091c821866e4bfba", +"postgres": "c50a316d091c821866e4bfba", +"postgresql": "c50a316d091c821866e4bfba", +"snowflake": "c50a316d091c821866e4bfba", +"tsql": "c50a316d091c821866e4bfba" +} +], +[ +"type", +{ +"DuckDB": "fe0bedb7dda0e9247a51fdee", +"None": "fe0bedb7dda0e9247a51fdee", +"bigquery": "fe0bedb7dda0e9247a51fdee", +"databricks": "fe0bedb7dda0e9247a51fdee", +"duckdb": "fe0bedb7dda0e9247a51fdee", +"generic": "fe0bedb7dda0e9247a51fdee", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "fe0bedb7dda0e9247a51fdee", +"postgres": "fe0bedb7dda0e9247a51fdee", +"postgresql": "fe0bedb7dda0e9247a51fdee", +"snowflake": "fe0bedb7dda0e9247a51fdee", +"tsql": "fe0bedb7dda0e9247a51fdee" +} +], +[ +"type", +{ +"DuckDB": "1eb7fb4e8cf75773c5573562", +"None": "1eb7fb4e8cf75773c5573562", +"bigquery": "c9b810639795a7bfab91b98d", +"databricks": "1eb7fb4e8cf75773c5573562", +"duckdb": "1eb7fb4e8cf75773c5573562", +"generic": "1eb7fb4e8cf75773c5573562", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "1eb7fb4e8cf75773c5573562", +"postgres": "1eb7fb4e8cf75773c5573562", +"postgresql": "1eb7fb4e8cf75773c5573562", +"snowflake": "97a20344d811fb77c7690863", +"tsql": "1eb7fb4e8cf75773c5573562" +} +], +[ +"type", +{ +"DuckDB": "c6889f2965db73017be6f6e7", +"None": "c6889f2965db73017be6f6e7", +"bigquery": "a428302e4848ffe877284c84", +"databricks": "c6889f2965db73017be6f6e7", +"duckdb": "c6889f2965db73017be6f6e7", +"generic": "c6889f2965db73017be6f6e7", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "c6889f2965db73017be6f6e7", +"postgres": "c6889f2965db73017be6f6e7", +"postgresql": "c6889f2965db73017be6f6e7", +"snowflake": "652ff8b21f638eac8fdc46c5", +"tsql": "c6889f2965db73017be6f6e7" +} +], +[ +"type", +{ +"DuckDB": "aed0419e7f2ce7c0a8892248", +"None": "aed0419e7f2ce7c0a8892248", +"bigquery": "6f6198e2d2c8a8d6444ef5af", +"databricks": "e3bc1b8bad22d8104417b00f", +"duckdb": "aed0419e7f2ce7c0a8892248", +"generic": "aed0419e7f2ce7c0a8892248", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "aed0419e7f2ce7c0a8892248", +"postgres": "19e127c23b4598727a2d8ceb", +"postgresql": "19e127c23b4598727a2d8ceb", +"snowflake": "aed0419e7f2ce7c0a8892248", +"tsql": "aed0419e7f2ce7c0a8892248" +} +], +[ +"type", +{ +"DuckDB": "55a086bc8305ad303017ae10", +"None": "55a086bc8305ad303017ae10", +"bigquery": "55a086bc8305ad303017ae10", +"databricks": "55a086bc8305ad303017ae10", +"duckdb": "55a086bc8305ad303017ae10", +"generic": "55a086bc8305ad303017ae10", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "55a086bc8305ad303017ae10", +"postgres": "55a086bc8305ad303017ae10", +"postgresql": "55a086bc8305ad303017ae10", +"snowflake": "55a086bc8305ad303017ae10", +"tsql": "55a086bc8305ad303017ae10" +} +], +[ +"type", +{ +"DuckDB": "f7598fbf399afabe1e01a358", +"None": "d08ef9483feed34fc0ee4319", +"bigquery": "d08ef9483feed34fc0ee4319", +"databricks": "d08ef9483feed34fc0ee4319", +"duckdb": "f7598fbf399afabe1e01a358", +"generic": "d08ef9483feed34fc0ee4319", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "d08ef9483feed34fc0ee4319", +"postgres": "d08ef9483feed34fc0ee4319", +"postgresql": "d08ef9483feed34fc0ee4319", +"snowflake": "d08ef9483feed34fc0ee4319", +"tsql": "d08ef9483feed34fc0ee4319" +} +], +[ +"type", +{ +"DuckDB": "d3b6a6835220f9cedfa363c7", +"None": "d3b6a6835220f9cedfa363c7", +"bigquery": "d3b6a6835220f9cedfa363c7", +"databricks": "d3b6a6835220f9cedfa363c7", +"duckdb": "d3b6a6835220f9cedfa363c7", +"generic": "d3b6a6835220f9cedfa363c7", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "d3b6a6835220f9cedfa363c7", +"postgres": "d3b6a6835220f9cedfa363c7", +"postgresql": "d3b6a6835220f9cedfa363c7", +"snowflake": "d3b6a6835220f9cedfa363c7", +"tsql": "d3b6a6835220f9cedfa363c7" +} +], +[ +"type", +{ +"DuckDB": "3d23f811a03db519b598c815", +"None": "3d23f811a03db519b598c815", +"bigquery": "3d23f811a03db519b598c815", +"databricks": "3d23f811a03db519b598c815", +"duckdb": "3d23f811a03db519b598c815", +"generic": "3d23f811a03db519b598c815", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "3d23f811a03db519b598c815", +"postgres": "3d23f811a03db519b598c815", +"postgresql": "3d23f811a03db519b598c815", +"snowflake": "3d23f811a03db519b598c815", +"tsql": "3d23f811a03db519b598c815" +} +], +[ +"type", +{ +"DuckDB": "f816d7b3b97815f308346e20", +"None": "f816d7b3b97815f308346e20", +"bigquery": "f816d7b3b97815f308346e20", +"databricks": "f816d7b3b97815f308346e20", +"duckdb": "f816d7b3b97815f308346e20", +"generic": "f816d7b3b97815f308346e20", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "f816d7b3b97815f308346e20", +"postgres": "f816d7b3b97815f308346e20", +"postgresql": "f816d7b3b97815f308346e20", +"snowflake": "f816d7b3b97815f308346e20", +"tsql": "f816d7b3b97815f308346e20" +} +], +[ +"type", +{ +"DuckDB": "aed0419e7f2ce7c0a8892248", +"None": "aed0419e7f2ce7c0a8892248", +"bigquery": "6f6198e2d2c8a8d6444ef5af", +"databricks": "e3bc1b8bad22d8104417b00f", +"duckdb": "aed0419e7f2ce7c0a8892248", +"generic": "aed0419e7f2ce7c0a8892248", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "aed0419e7f2ce7c0a8892248", +"postgres": "19e127c23b4598727a2d8ceb", +"postgresql": "19e127c23b4598727a2d8ceb", +"snowflake": "aed0419e7f2ce7c0a8892248", +"tsql": "aed0419e7f2ce7c0a8892248" +} +], +[ +"type", +{ +"DuckDB": "57922064a7dc546cbb50e42b", +"None": "57922064a7dc546cbb50e42b", +"bigquery": "57922064a7dc546cbb50e42b", +"databricks": "57922064a7dc546cbb50e42b", +"duckdb": "57922064a7dc546cbb50e42b", +"generic": "57922064a7dc546cbb50e42b", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "57922064a7dc546cbb50e42b", +"postgres": "57922064a7dc546cbb50e42b", +"postgresql": "57922064a7dc546cbb50e42b", +"snowflake": "57922064a7dc546cbb50e42b", +"tsql": "57922064a7dc546cbb50e42b" +} +], +[ +"type", +{ +"DuckDB": "7b2fd741638cbd96bb38d7e0", +"None": "7b2fd741638cbd96bb38d7e0", +"bigquery": "7b2fd741638cbd96bb38d7e0", +"databricks": "4fb572024031cb7631777be1", +"duckdb": "7b2fd741638cbd96bb38d7e0", +"generic": "7b2fd741638cbd96bb38d7e0", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "7b2fd741638cbd96bb38d7e0", +"postgres": "7b2fd741638cbd96bb38d7e0", +"postgresql": "7b2fd741638cbd96bb38d7e0", +"snowflake": "7b2fd741638cbd96bb38d7e0", +"tsql": "7b2fd741638cbd96bb38d7e0" +} +], +[ +"type", +{ +"DuckDB": "a766fea06fc070b352976b0a", +"None": "a766fea06fc070b352976b0a", +"bigquery": "e4f0244beaa01667e80482b6", +"databricks": "e4f0244beaa01667e80482b6", +"duckdb": "a766fea06fc070b352976b0a", +"generic": "a766fea06fc070b352976b0a", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "e4f0244beaa01667e80482b6", +"postgres": "a766fea06fc070b352976b0a", +"postgresql": "a766fea06fc070b352976b0a", +"snowflake": "a766fea06fc070b352976b0a", +"tsql": "a766fea06fc070b352976b0a" +} +], +[ +"type", +{ +"DuckDB": "15b3387f6c4d73bcf113983a", +"None": "15b3387f6c4d73bcf113983a", +"bigquery": "15b3387f6c4d73bcf113983a", +"databricks": "15b3387f6c4d73bcf113983a", +"duckdb": "15b3387f6c4d73bcf113983a", +"generic": "15b3387f6c4d73bcf113983a", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "15b3387f6c4d73bcf113983a", +"postgres": "15b3387f6c4d73bcf113983a", +"postgresql": "15b3387f6c4d73bcf113983a", +"snowflake": "15b3387f6c4d73bcf113983a", +"tsql": "15b3387f6c4d73bcf113983a" +} +], +[ +"type", +{ +"DuckDB": "d34f84c1b71b9c9c0c20abb0", +"None": "d34f84c1b71b9c9c0c20abb0", +"bigquery": "d34f84c1b71b9c9c0c20abb0", +"databricks": "c662d9470aa4255dfb493df1", +"duckdb": "d34f84c1b71b9c9c0c20abb0", +"generic": "d34f84c1b71b9c9c0c20abb0", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "c662d9470aa4255dfb493df1", +"postgres": "d34f84c1b71b9c9c0c20abb0", +"postgresql": "d34f84c1b71b9c9c0c20abb0", +"snowflake": "d34f84c1b71b9c9c0c20abb0", +"tsql": "d34f84c1b71b9c9c0c20abb0" +} +], +[ +"type", +{ +"DuckDB": "14cd6e78d75f61b2bd1bbd71", +"None": "14cd6e78d75f61b2bd1bbd71", +"bigquery": "14cd6e78d75f61b2bd1bbd71", +"databricks": "73504f31156e8e661c1fb26c", +"duckdb": "14cd6e78d75f61b2bd1bbd71", +"generic": "14cd6e78d75f61b2bd1bbd71", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "73504f31156e8e661c1fb26c", +"postgres": "14cd6e78d75f61b2bd1bbd71", +"postgresql": "14cd6e78d75f61b2bd1bbd71", +"snowflake": "14cd6e78d75f61b2bd1bbd71", +"tsql": "14cd6e78d75f61b2bd1bbd71" +} +], +[ +"type", +{ +"DuckDB": "96e8f438bf42d79cd8b1fada", +"None": "96e8f438bf42d79cd8b1fada", +"bigquery": "96e8f438bf42d79cd8b1fada", +"databricks": "96e8f438bf42d79cd8b1fada", +"duckdb": "96e8f438bf42d79cd8b1fada", +"generic": "96e8f438bf42d79cd8b1fada", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "96e8f438bf42d79cd8b1fada", +"postgres": "96e8f438bf42d79cd8b1fada", +"postgresql": "96e8f438bf42d79cd8b1fada", +"snowflake": "96e8f438bf42d79cd8b1fada", +"tsql": "96e8f438bf42d79cd8b1fada" +} +], +[ +"type", +{ +"DuckDB": "260b29f255364b2044abe127", +"None": "260b29f255364b2044abe127", +"bigquery": "260b29f255364b2044abe127", +"databricks": "260b29f255364b2044abe127", +"duckdb": "260b29f255364b2044abe127", +"generic": "260b29f255364b2044abe127", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "260b29f255364b2044abe127", +"postgres": "260b29f255364b2044abe127", +"postgresql": "260b29f255364b2044abe127", +"snowflake": "260b29f255364b2044abe127", +"tsql": "260b29f255364b2044abe127" +} +], +[ +"type", +{ +"DuckDB": "e5199d22ebbd1383c1e821df", +"None": "e5199d22ebbd1383c1e821df", +"bigquery": "e5199d22ebbd1383c1e821df", +"databricks": "e5199d22ebbd1383c1e821df", +"duckdb": "e5199d22ebbd1383c1e821df", +"generic": "e5199d22ebbd1383c1e821df", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "e5199d22ebbd1383c1e821df", +"postgres": "e5199d22ebbd1383c1e821df", +"postgresql": "e5199d22ebbd1383c1e821df", +"snowflake": "e5199d22ebbd1383c1e821df", +"tsql": "e5199d22ebbd1383c1e821df" +} +], +[ +"type", +{ +"DuckDB": "05ebf79d18b2ae4eaa41f450", +"None": "336fd1b7a1f7d8105c29280c", +"bigquery": "aa04c66b4fed5190c90308fd", +"databricks": "336fd1b7a1f7d8105c29280c", +"duckdb": "05ebf79d18b2ae4eaa41f450", +"generic": "336fd1b7a1f7d8105c29280c", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "336fd1b7a1f7d8105c29280c", +"postgres": "336fd1b7a1f7d8105c29280c", +"postgresql": "336fd1b7a1f7d8105c29280c", +"snowflake": "336fd1b7a1f7d8105c29280c", +"tsql": "336fd1b7a1f7d8105c29280c" +} +], +[ +"type", +{ +"DuckDB": "3f71ab5f3c1c040da96f2cec", +"None": "3f71ab5f3c1c040da96f2cec", +"bigquery": "3f71ab5f3c1c040da96f2cec", +"databricks": "3f71ab5f3c1c040da96f2cec", +"duckdb": "3f71ab5f3c1c040da96f2cec", +"generic": "3f71ab5f3c1c040da96f2cec", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "3f71ab5f3c1c040da96f2cec", +"postgres": "3f71ab5f3c1c040da96f2cec", +"postgresql": "3f71ab5f3c1c040da96f2cec", +"snowflake": "3f71ab5f3c1c040da96f2cec", +"tsql": "3f71ab5f3c1c040da96f2cec" +} +], +[ +"type", +{ +"DuckDB": "802f1c1fcb97ddd5679172d2", +"None": "802f1c1fcb97ddd5679172d2", +"bigquery": "a428302e4848ffe877284c84", +"databricks": "802f1c1fcb97ddd5679172d2", +"duckdb": "802f1c1fcb97ddd5679172d2", +"generic": "802f1c1fcb97ddd5679172d2", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "802f1c1fcb97ddd5679172d2", +"postgres": "802f1c1fcb97ddd5679172d2", +"postgresql": "802f1c1fcb97ddd5679172d2", +"snowflake": "652ff8b21f638eac8fdc46c5", +"tsql": "08784560ad78e14a02cc066f" +} +], +[ +"type", +{ +"DuckDB": "d91c8f17eb347629690400c7", +"None": "d91c8f17eb347629690400c7", +"bigquery": "d91c8f17eb347629690400c7", +"databricks": "d91c8f17eb347629690400c7", +"duckdb": "d91c8f17eb347629690400c7", +"generic": "d91c8f17eb347629690400c7", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "d91c8f17eb347629690400c7", +"postgres": "d91c8f17eb347629690400c7", +"postgresql": "d91c8f17eb347629690400c7", +"snowflake": "d91c8f17eb347629690400c7", +"tsql": "d91c8f17eb347629690400c7" +} +], +[ +"type", +{ +"DuckDB": "2bfa352725f9d8a91250f75e", +"None": "2bfa352725f9d8a91250f75e", +"bigquery": "2bfa352725f9d8a91250f75e", +"databricks": "2bfa352725f9d8a91250f75e", +"duckdb": "2bfa352725f9d8a91250f75e", +"generic": "2bfa352725f9d8a91250f75e", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "2bfa352725f9d8a91250f75e", +"postgres": "2bfa352725f9d8a91250f75e", +"postgresql": "2bfa352725f9d8a91250f75e", +"snowflake": "2bfa352725f9d8a91250f75e", +"tsql": "2bfa352725f9d8a91250f75e" +} +], +[ +"type", +{ +"DuckDB": "314ed506f24e92300a425780", +"None": "314ed506f24e92300a425780", +"bigquery": "314ed506f24e92300a425780", +"databricks": "314ed506f24e92300a425780", +"duckdb": "314ed506f24e92300a425780", +"generic": "314ed506f24e92300a425780", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "314ed506f24e92300a425780", +"postgres": "314ed506f24e92300a425780", +"postgresql": "314ed506f24e92300a425780", +"snowflake": "314ed506f24e92300a425780", +"tsql": "314ed506f24e92300a425780" +} +], +[ +"type", +{ +"DuckDB": "2873244018c69d6d42752bdc", +"None": "2873244018c69d6d42752bdc", +"bigquery": "2873244018c69d6d42752bdc", +"databricks": "2873244018c69d6d42752bdc", +"duckdb": "2873244018c69d6d42752bdc", +"generic": "2873244018c69d6d42752bdc", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "2873244018c69d6d42752bdc", +"postgres": "2873244018c69d6d42752bdc", +"postgresql": "2873244018c69d6d42752bdc", +"snowflake": "2873244018c69d6d42752bdc", +"tsql": "2873244018c69d6d42752bdc" +} +], +[ +"type", +{ +"DuckDB": "3d23f811a03db519b598c815", +"None": "3d23f811a03db519b598c815", +"bigquery": "3d23f811a03db519b598c815", +"databricks": "3d23f811a03db519b598c815", +"duckdb": "3d23f811a03db519b598c815", +"generic": "3d23f811a03db519b598c815", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "3d23f811a03db519b598c815", +"postgres": "3d23f811a03db519b598c815", +"postgresql": "3d23f811a03db519b598c815", +"snowflake": "3d23f811a03db519b598c815", +"tsql": "3d23f811a03db519b598c815" +} +], +[ +"type", +{ +"DuckDB": "087a9417cb511ff7bcfd6ccb", +"None": "383f8922f4b6f167d384037d", +"bigquery": "383f8922f4b6f167d384037d", +"databricks": "383f8922f4b6f167d384037d", +"duckdb": "087a9417cb511ff7bcfd6ccb", +"generic": "383f8922f4b6f167d384037d", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "383f8922f4b6f167d384037d", +"postgres": "383f8922f4b6f167d384037d", +"postgresql": "383f8922f4b6f167d384037d", +"snowflake": "383f8922f4b6f167d384037d", +"tsql": "383f8922f4b6f167d384037d" +} +], +[ +"type", +{ +"DuckDB": "19a1a80ffc06169f32694de8", +"None": "19a1a80ffc06169f32694de8", +"bigquery": "19a1a80ffc06169f32694de8", +"databricks": "19a1a80ffc06169f32694de8", +"duckdb": "19a1a80ffc06169f32694de8", +"generic": "19a1a80ffc06169f32694de8", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "19a1a80ffc06169f32694de8", +"postgres": "19a1a80ffc06169f32694de8", +"postgresql": "19a1a80ffc06169f32694de8", +"snowflake": "19a1a80ffc06169f32694de8", +"tsql": "19a1a80ffc06169f32694de8" +} +], +[ +"type", +{ +"DuckDB": "b017fb3c48f125e51b6db123", +"None": "b017fb3c48f125e51b6db123", +"bigquery": "b017fb3c48f125e51b6db123", +"databricks": "b017fb3c48f125e51b6db123", +"duckdb": "b017fb3c48f125e51b6db123", +"generic": "b017fb3c48f125e51b6db123", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "b017fb3c48f125e51b6db123", +"postgres": "b017fb3c48f125e51b6db123", +"postgresql": "b017fb3c48f125e51b6db123", +"snowflake": "b017fb3c48f125e51b6db123", +"tsql": "b017fb3c48f125e51b6db123" +} +], +[ +"type", +{ +"DuckDB": "a7120d1b1abcb844c87a968a", +"None": "a7120d1b1abcb844c87a968a", +"bigquery": "a7120d1b1abcb844c87a968a", +"databricks": "a7120d1b1abcb844c87a968a", +"duckdb": "a7120d1b1abcb844c87a968a", +"generic": "a7120d1b1abcb844c87a968a", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "a7120d1b1abcb844c87a968a", +"postgres": "a7120d1b1abcb844c87a968a", +"postgresql": "a7120d1b1abcb844c87a968a", +"snowflake": "a7120d1b1abcb844c87a968a", +"tsql": "a7120d1b1abcb844c87a968a" +} +], +[ +"type", +{ +"DuckDB": "fd31c8e468772027804119ec", +"None": "fd31c8e468772027804119ec", +"bigquery": "fd31c8e468772027804119ec", +"databricks": "fd31c8e468772027804119ec", +"duckdb": "fd31c8e468772027804119ec", +"generic": "fd31c8e468772027804119ec", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "fd31c8e468772027804119ec", +"postgres": "fd31c8e468772027804119ec", +"postgresql": "fd31c8e468772027804119ec", +"snowflake": "fd31c8e468772027804119ec", +"tsql": "fd31c8e468772027804119ec" +} +], +[ +"type", +{ +"DuckDB": "4169d9651c2a3667fc561f32", +"None": "4169d9651c2a3667fc561f32", +"bigquery": "88f7cced71c11944260bb54a", +"databricks": "4169d9651c2a3667fc561f32", +"duckdb": "4169d9651c2a3667fc561f32", +"generic": "4169d9651c2a3667fc561f32", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "4169d9651c2a3667fc561f32", +"postgres": "4169d9651c2a3667fc561f32", +"postgresql": "4169d9651c2a3667fc561f32", +"snowflake": "b210f8eb26c37b422f786c6b", +"tsql": "4169d9651c2a3667fc561f32" +} +], +[ +"type", +{ +"DuckDB": "3f71ab5f3c1c040da96f2cec", +"None": "3f71ab5f3c1c040da96f2cec", +"bigquery": "3f71ab5f3c1c040da96f2cec", +"databricks": "3f71ab5f3c1c040da96f2cec", +"duckdb": "3f71ab5f3c1c040da96f2cec", +"generic": "3f71ab5f3c1c040da96f2cec", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "3f71ab5f3c1c040da96f2cec", +"postgres": "3f71ab5f3c1c040da96f2cec", +"postgresql": "3f71ab5f3c1c040da96f2cec", +"snowflake": "3f71ab5f3c1c040da96f2cec", +"tsql": "3f71ab5f3c1c040da96f2cec" +} +], +[ +"type", +{ +"DuckDB": "eed0645c1e86fa1a6e35ccaa", +"None": "eed0645c1e86fa1a6e35ccaa", +"bigquery": "013a8446f043affffcf194f8", +"databricks": "eed0645c1e86fa1a6e35ccaa", +"duckdb": "eed0645c1e86fa1a6e35ccaa", +"generic": "eed0645c1e86fa1a6e35ccaa", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "eed0645c1e86fa1a6e35ccaa", +"postgres": "eed0645c1e86fa1a6e35ccaa", +"postgresql": "eed0645c1e86fa1a6e35ccaa", +"snowflake": "97a20344d811fb77c7690863", +"tsql": "eed0645c1e86fa1a6e35ccaa" +} +], +[ +"type", +{ +"DuckDB": "3a7ffeb8f81df6ccd57f3689", +"None": "3a7ffeb8f81df6ccd57f3689", +"bigquery": "3a7ffeb8f81df6ccd57f3689", +"databricks": "3a7ffeb8f81df6ccd57f3689", +"duckdb": "3a7ffeb8f81df6ccd57f3689", +"generic": "3a7ffeb8f81df6ccd57f3689", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "3a7ffeb8f81df6ccd57f3689", +"postgres": "3a7ffeb8f81df6ccd57f3689", +"postgresql": "3a7ffeb8f81df6ccd57f3689", +"snowflake": "3a7ffeb8f81df6ccd57f3689", +"tsql": "3a7ffeb8f81df6ccd57f3689" +} +], +[ +"type", +{ +"DuckDB": "e1c74d96ac578f9323bf1bbd", +"None": "e1c74d96ac578f9323bf1bbd", +"bigquery": "e1c74d96ac578f9323bf1bbd", +"databricks": "e1c74d96ac578f9323bf1bbd", +"duckdb": "e1c74d96ac578f9323bf1bbd", +"generic": "e1c74d96ac578f9323bf1bbd", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "e1c74d96ac578f9323bf1bbd", +"postgres": "e1c74d96ac578f9323bf1bbd", +"postgresql": "e1c74d96ac578f9323bf1bbd", +"snowflake": "e1c74d96ac578f9323bf1bbd", +"tsql": "e1c74d96ac578f9323bf1bbd" +} +], +[ +"type", +{ +"DuckDB": "e69f24e5693aeece1e1a03b8", +"None": "6dd6559eebacf5e375e1cce3", +"bigquery": "3e76afa61378ff263b617c7e", +"databricks": "e4317ab2bb471f29ee3c44be", +"duckdb": "e69f24e5693aeece1e1a03b8", +"generic": "6dd6559eebacf5e375e1cce3", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "6dd6559eebacf5e375e1cce3", +"postgres": "6dd6559eebacf5e375e1cce3", +"postgresql": "6dd6559eebacf5e375e1cce3", +"snowflake": "a4325ee9f4d61463eb81badb", +"tsql": "6f2f02617b722e48d3f365c2" +} +], +[ +"type", +{ +"DuckDB": "c50a316d091c821866e4bfba", +"None": "c50a316d091c821866e4bfba", +"bigquery": "c50a316d091c821866e4bfba", +"databricks": "c50a316d091c821866e4bfba", +"duckdb": "c50a316d091c821866e4bfba", +"generic": "c50a316d091c821866e4bfba", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "c50a316d091c821866e4bfba", +"postgres": "c50a316d091c821866e4bfba", +"postgresql": "c50a316d091c821866e4bfba", +"snowflake": "c50a316d091c821866e4bfba", +"tsql": "c50a316d091c821866e4bfba" +} +], +[ +"type", +{ +"DuckDB": "fe23594c781e79cbb0c8927a", +"None": "fe23594c781e79cbb0c8927a", +"bigquery": "fe23594c781e79cbb0c8927a", +"databricks": "fe23594c781e79cbb0c8927a", +"duckdb": "fe23594c781e79cbb0c8927a", +"generic": "fe23594c781e79cbb0c8927a", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "fe23594c781e79cbb0c8927a", +"postgres": "fe23594c781e79cbb0c8927a", +"postgresql": "fe23594c781e79cbb0c8927a", +"snowflake": "38b2ec94bf02be40007ce525", +"tsql": "fe23594c781e79cbb0c8927a" +} +], +[ +"type", +{ +"DuckDB": "19bdd92ea0cc5fb028657510", +"None": "b8321619b794db091c9e96a1", +"bigquery": "b8321619b794db091c9e96a1", +"databricks": "1e75e5227bea0ae294ac7af1", +"duckdb": "19bdd92ea0cc5fb028657510", +"generic": "b8321619b794db091c9e96a1", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "b8321619b794db091c9e96a1", +"postgres": "b8321619b794db091c9e96a1", +"postgresql": "b8321619b794db091c9e96a1", +"snowflake": "b8321619b794db091c9e96a1", +"tsql": "b8321619b794db091c9e96a1" +} +], +[ +"type", +{ +"DuckDB": "19a1a80ffc06169f32694de8", +"None": "19a1a80ffc06169f32694de8", +"bigquery": "19a1a80ffc06169f32694de8", +"databricks": "19a1a80ffc06169f32694de8", +"duckdb": "19a1a80ffc06169f32694de8", +"generic": "19a1a80ffc06169f32694de8", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "19a1a80ffc06169f32694de8", +"postgres": "19a1a80ffc06169f32694de8", +"postgresql": "19a1a80ffc06169f32694de8", +"snowflake": "19a1a80ffc06169f32694de8", +"tsql": "19a1a80ffc06169f32694de8" +} +], +[ +"type", +{ +"DuckDB": "26e762643db86e7646e57cba", +"None": "26e762643db86e7646e57cba", +"bigquery": "26e762643db86e7646e57cba", +"databricks": "26e762643db86e7646e57cba", +"duckdb": "26e762643db86e7646e57cba", +"generic": "26e762643db86e7646e57cba", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "26e762643db86e7646e57cba", +"postgres": "26e762643db86e7646e57cba", +"postgresql": "26e762643db86e7646e57cba", +"snowflake": "26e762643db86e7646e57cba", +"tsql": "26e762643db86e7646e57cba" +} +], +[ +"type", +{ +"DuckDB": "078c0e4b25cdb89eb4ebd88f", +"None": "078c0e4b25cdb89eb4ebd88f", +"bigquery": "5226d7e2a62c7650a87d6e84", +"databricks": "078c0e4b25cdb89eb4ebd88f", +"duckdb": "078c0e4b25cdb89eb4ebd88f", +"generic": "078c0e4b25cdb89eb4ebd88f", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "078c0e4b25cdb89eb4ebd88f", +"postgres": "078c0e4b25cdb89eb4ebd88f", +"postgresql": "078c0e4b25cdb89eb4ebd88f", +"snowflake": "6306b9e88f7b13dbb6a32c00", +"tsql": "078c0e4b25cdb89eb4ebd88f" +} +], +[ +"type", +{ +"DuckDB": "7cd31289a5b99b5a5e24492d", +"None": "7cd31289a5b99b5a5e24492d", +"bigquery": "7cd31289a5b99b5a5e24492d", +"databricks": "7cd31289a5b99b5a5e24492d", +"duckdb": "7cd31289a5b99b5a5e24492d", +"generic": "7cd31289a5b99b5a5e24492d", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "7cd31289a5b99b5a5e24492d", +"postgres": "7cd31289a5b99b5a5e24492d", +"postgresql": "7cd31289a5b99b5a5e24492d", +"snowflake": "7cd31289a5b99b5a5e24492d", +"tsql": "7cd31289a5b99b5a5e24492d" +} +], +[ +"type", +{ +"DuckDB": "251aba3fef503ce64556c701", +"None": "251aba3fef503ce64556c701", +"bigquery": "c50a316d091c821866e4bfba", +"databricks": "251aba3fef503ce64556c701", +"duckdb": "251aba3fef503ce64556c701", +"generic": "251aba3fef503ce64556c701", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "251aba3fef503ce64556c701", +"postgres": "b7d6fc051a3c1ea6deb29ff4", +"postgresql": "b7d6fc051a3c1ea6deb29ff4", +"snowflake": "251aba3fef503ce64556c701", +"tsql": "e3bc1b8bad22d8104417b00f" +} +], +[ +"type", +{ +"DuckDB": "3eb44072dafa3bef75c97b6a", +"None": "3eb44072dafa3bef75c97b6a", +"bigquery": "3eb44072dafa3bef75c97b6a", +"databricks": "3eb44072dafa3bef75c97b6a", +"duckdb": "3eb44072dafa3bef75c97b6a", +"generic": "3eb44072dafa3bef75c97b6a", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "3eb44072dafa3bef75c97b6a", +"postgres": "3eb44072dafa3bef75c97b6a", +"postgresql": "3eb44072dafa3bef75c97b6a", +"snowflake": "3eb44072dafa3bef75c97b6a", +"tsql": "3eb44072dafa3bef75c97b6a" +} +], +[ +"type", +{ +"DuckDB": "596dafb6039bd1951f03c6a3", +"None": "596dafb6039bd1951f03c6a3", +"bigquery": "73f0a74496572926a274036e", +"databricks": "596dafb6039bd1951f03c6a3", +"duckdb": "596dafb6039bd1951f03c6a3", +"generic": "596dafb6039bd1951f03c6a3", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "596dafb6039bd1951f03c6a3", +"postgres": "0d0c279c483ce8c07a9e7375", +"postgresql": "0d0c279c483ce8c07a9e7375", +"snowflake": "596dafb6039bd1951f03c6a3", +"tsql": "c100cdbd268164cf084295be" +} +], +[ +"type", +{ +"DuckDB": "b2c9b6ebca6c097f3caa0aa8", +"None": "b2c9b6ebca6c097f3caa0aa8", +"bigquery": "b2c9b6ebca6c097f3caa0aa8", +"databricks": "b2c9b6ebca6c097f3caa0aa8", +"duckdb": "b2c9b6ebca6c097f3caa0aa8", +"generic": "b2c9b6ebca6c097f3caa0aa8", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "b2c9b6ebca6c097f3caa0aa8", +"postgres": "b2c9b6ebca6c097f3caa0aa8", +"postgresql": "b2c9b6ebca6c097f3caa0aa8", +"snowflake": "b2c9b6ebca6c097f3caa0aa8", +"tsql": "b2c9b6ebca6c097f3caa0aa8" +} +], +[ +"type", +{ +"DuckDB": "d2c97d221599d038d9875873", +"None": "d2c97d221599d038d9875873", +"bigquery": "d2c97d221599d038d9875873", +"databricks": "d2c97d221599d038d9875873", +"duckdb": "d2c97d221599d038d9875873", +"generic": "d2c97d221599d038d9875873", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "d2c97d221599d038d9875873", +"postgres": "d2c97d221599d038d9875873", +"postgresql": "d2c97d221599d038d9875873", +"snowflake": "d2c97d221599d038d9875873", +"tsql": "d2c97d221599d038d9875873" +} +], +[ +"type", +{ +"DuckDB": "4d90ccac34ef123bb0b2a15c", +"None": "4d90ccac34ef123bb0b2a15c", +"bigquery": "4d90ccac34ef123bb0b2a15c", +"databricks": "4d90ccac34ef123bb0b2a15c", +"duckdb": "4d90ccac34ef123bb0b2a15c", +"generic": "4d90ccac34ef123bb0b2a15c", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "4d90ccac34ef123bb0b2a15c", +"postgres": "4d90ccac34ef123bb0b2a15c", +"postgresql": "4d90ccac34ef123bb0b2a15c", +"snowflake": "4d90ccac34ef123bb0b2a15c", +"tsql": "4d90ccac34ef123bb0b2a15c" +} +], +[ +"type", +{ +"DuckDB": "1ae302067c05dc9ae3a029f2", +"None": "1ae302067c05dc9ae3a029f2", +"bigquery": "1ae302067c05dc9ae3a029f2", +"databricks": "1ae302067c05dc9ae3a029f2", +"duckdb": "1ae302067c05dc9ae3a029f2", +"generic": "1ae302067c05dc9ae3a029f2", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "1ae302067c05dc9ae3a029f2", +"postgres": "1ae302067c05dc9ae3a029f2", +"postgresql": "1ae302067c05dc9ae3a029f2", +"snowflake": "1ae302067c05dc9ae3a029f2", +"tsql": "1ae302067c05dc9ae3a029f2" +} +], +[ +"type", +{ +"DuckDB": "8441d00030df06ad6a5534d3", +"None": "8441d00030df06ad6a5534d3", +"bigquery": "c9b810639795a7bfab91b98d", +"databricks": "8441d00030df06ad6a5534d3", +"duckdb": "8441d00030df06ad6a5534d3", +"generic": "8441d00030df06ad6a5534d3", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "8441d00030df06ad6a5534d3", +"postgres": "8441d00030df06ad6a5534d3", +"postgresql": "8441d00030df06ad6a5534d3", +"snowflake": "97a20344d811fb77c7690863", +"tsql": "8441d00030df06ad6a5534d3" +} +], +[ +"type", +{ +"DuckDB": "b1ec979036647e3f2686cece", +"None": "b1ec979036647e3f2686cece", +"bigquery": "b1ec979036647e3f2686cece", +"databricks": "b1ec979036647e3f2686cece", +"duckdb": "b1ec979036647e3f2686cece", +"generic": "b1ec979036647e3f2686cece", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "b1ec979036647e3f2686cece", +"postgres": "b1ec979036647e3f2686cece", +"postgresql": "b1ec979036647e3f2686cece", +"snowflake": "b1ec979036647e3f2686cece", +"tsql": "b1ec979036647e3f2686cece" +} +], +[ +"type", +{ +"DuckDB": "962ea05bab624c1f8c259a65", +"None": "962ea05bab624c1f8c259a65", +"bigquery": "962ea05bab624c1f8c259a65", +"databricks": "962ea05bab624c1f8c259a65", +"duckdb": "962ea05bab624c1f8c259a65", +"generic": "962ea05bab624c1f8c259a65", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "962ea05bab624c1f8c259a65", +"postgres": "962ea05bab624c1f8c259a65", +"postgresql": "962ea05bab624c1f8c259a65", +"snowflake": "962ea05bab624c1f8c259a65", +"tsql": "962ea05bab624c1f8c259a65" +} +], +[ +"type", +{ +"DuckDB": "f319941cc6ec088f46ecbadb", +"None": "f319941cc6ec088f46ecbadb", +"bigquery": "f319941cc6ec088f46ecbadb", +"databricks": "f319941cc6ec088f46ecbadb", +"duckdb": "f319941cc6ec088f46ecbadb", +"generic": "f319941cc6ec088f46ecbadb", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "f319941cc6ec088f46ecbadb", +"postgres": "f319941cc6ec088f46ecbadb", +"postgresql": "f319941cc6ec088f46ecbadb", +"snowflake": "f319941cc6ec088f46ecbadb", +"tsql": "f319941cc6ec088f46ecbadb" +} +], +[ +"type", +{ +"DuckDB": "79278352c17c9de0f5a28af5", +"None": "79278352c17c9de0f5a28af5", +"bigquery": "c9b810639795a7bfab91b98d", +"databricks": "79278352c17c9de0f5a28af5", +"duckdb": "79278352c17c9de0f5a28af5", +"generic": "79278352c17c9de0f5a28af5", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "79278352c17c9de0f5a28af5", +"postgres": "79278352c17c9de0f5a28af5", +"postgresql": "79278352c17c9de0f5a28af5", +"snowflake": "97a20344d811fb77c7690863", +"tsql": "79278352c17c9de0f5a28af5" +} +], +[ +"type", +{ +"DuckDB": "717cf79ef777823eb3576deb", +"None": "717cf79ef777823eb3576deb", +"bigquery": "717cf79ef777823eb3576deb", +"databricks": "717cf79ef777823eb3576deb", +"duckdb": "717cf79ef777823eb3576deb", +"generic": "717cf79ef777823eb3576deb", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "717cf79ef777823eb3576deb", +"postgres": "717cf79ef777823eb3576deb", +"postgresql": "717cf79ef777823eb3576deb", +"snowflake": "717cf79ef777823eb3576deb", +"tsql": "717cf79ef777823eb3576deb" +} +], +[ +"type", +{ +"DuckDB": "8362a1ff79ce7c9350d11210", +"None": "8362a1ff79ce7c9350d11210", +"bigquery": "8362a1ff79ce7c9350d11210", +"databricks": "8362a1ff79ce7c9350d11210", +"duckdb": "8362a1ff79ce7c9350d11210", +"generic": "8362a1ff79ce7c9350d11210", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "8362a1ff79ce7c9350d11210", +"postgres": "8362a1ff79ce7c9350d11210", +"postgresql": "8362a1ff79ce7c9350d11210", +"snowflake": "8362a1ff79ce7c9350d11210", +"tsql": "8362a1ff79ce7c9350d11210" +} +], +[ +"type", +{ +"DuckDB": "688179272da645629077e980", +"None": "688179272da645629077e980", +"bigquery": "688179272da645629077e980", +"databricks": "688179272da645629077e980", +"duckdb": "688179272da645629077e980", +"generic": "688179272da645629077e980", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "688179272da645629077e980", +"postgres": "688179272da645629077e980", +"postgresql": "688179272da645629077e980", +"snowflake": "b210f8eb26c37b422f786c6b", +"tsql": "688179272da645629077e980" +} +], +[ +"type", +{ +"DuckDB": "2e5b1ffe62d65d4d8c389ecd", +"None": "2e5b1ffe62d65d4d8c389ecd", +"bigquery": "2e5b1ffe62d65d4d8c389ecd", +"databricks": "2e5b1ffe62d65d4d8c389ecd", +"duckdb": "2e5b1ffe62d65d4d8c389ecd", +"generic": "2e5b1ffe62d65d4d8c389ecd", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "2e5b1ffe62d65d4d8c389ecd", +"postgres": "2e5b1ffe62d65d4d8c389ecd", +"postgresql": "2e5b1ffe62d65d4d8c389ecd", +"snowflake": "2e5b1ffe62d65d4d8c389ecd", +"tsql": "2e5b1ffe62d65d4d8c389ecd" +} +], +[ +"type", +{ +"DuckDB": "e6badc927d1adf4563b4f3a5", +"None": "e6badc927d1adf4563b4f3a5", +"bigquery": "e6badc927d1adf4563b4f3a5", +"databricks": "e6badc927d1adf4563b4f3a5", +"duckdb": "e6badc927d1adf4563b4f3a5", +"generic": "e6badc927d1adf4563b4f3a5", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "e6badc927d1adf4563b4f3a5", +"postgres": "e6badc927d1adf4563b4f3a5", +"postgresql": "e6badc927d1adf4563b4f3a5", +"snowflake": "e6badc927d1adf4563b4f3a5", +"tsql": "e6badc927d1adf4563b4f3a5" +} +], +[ +"type", +{ +"DuckDB": "9070740b5c7f7fb5d091ad05", +"None": "9070740b5c7f7fb5d091ad05", +"bigquery": "9070740b5c7f7fb5d091ad05", +"databricks": "9070740b5c7f7fb5d091ad05", +"duckdb": "9070740b5c7f7fb5d091ad05", +"generic": "9070740b5c7f7fb5d091ad05", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "9070740b5c7f7fb5d091ad05", +"postgres": "9070740b5c7f7fb5d091ad05", +"postgresql": "9070740b5c7f7fb5d091ad05", +"snowflake": "9070740b5c7f7fb5d091ad05", +"tsql": "9070740b5c7f7fb5d091ad05" +} +], +[ +"type", +{ +"DuckDB": "607f7c82658f39cce394b124", +"None": "607f7c82658f39cce394b124", +"bigquery": "607f7c82658f39cce394b124", +"databricks": "085a20ac29ebf425cac9e1d7", +"duckdb": "607f7c82658f39cce394b124", +"generic": "607f7c82658f39cce394b124", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "085a20ac29ebf425cac9e1d7", +"postgres": "607f7c82658f39cce394b124", +"postgresql": "607f7c82658f39cce394b124", +"snowflake": "607f7c82658f39cce394b124", +"tsql": "607f7c82658f39cce394b124" +} +], +[ +"type", +{ +"DuckDB": "b3d92948d21d50dcbeb5f80b", +"None": "b3d92948d21d50dcbeb5f80b", +"bigquery": "b3d92948d21d50dcbeb5f80b", +"databricks": "b3d92948d21d50dcbeb5f80b", +"duckdb": "b3d92948d21d50dcbeb5f80b", +"generic": "b3d92948d21d50dcbeb5f80b", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "b3d92948d21d50dcbeb5f80b", +"postgres": "b3d92948d21d50dcbeb5f80b", +"postgresql": "b3d92948d21d50dcbeb5f80b", +"snowflake": "b3d92948d21d50dcbeb5f80b", +"tsql": "b3d92948d21d50dcbeb5f80b" +} +], +[ +"type", +{ +"DuckDB": "c50a316d091c821866e4bfba", +"None": "c50a316d091c821866e4bfba", +"bigquery": "c50a316d091c821866e4bfba", +"databricks": "c50a316d091c821866e4bfba", +"duckdb": "c50a316d091c821866e4bfba", +"generic": "c50a316d091c821866e4bfba", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "c50a316d091c821866e4bfba", +"postgres": "c50a316d091c821866e4bfba", +"postgresql": "c50a316d091c821866e4bfba", +"snowflake": "c50a316d091c821866e4bfba", +"tsql": "c50a316d091c821866e4bfba" +} +], +[ +"type", +{ +"DuckDB": "f4c43a87a78970bca1f88b09", +"None": "f4c43a87a78970bca1f88b09", +"bigquery": "f4c43a87a78970bca1f88b09", +"databricks": "f4c43a87a78970bca1f88b09", +"duckdb": "f4c43a87a78970bca1f88b09", +"generic": "f4c43a87a78970bca1f88b09", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "f4c43a87a78970bca1f88b09", +"postgres": "f4c43a87a78970bca1f88b09", +"postgresql": "f4c43a87a78970bca1f88b09", +"snowflake": "652ff8b21f638eac8fdc46c5", +"tsql": "f4c43a87a78970bca1f88b09" +} +], +[ +"type", +{ +"DuckDB": "2279ed9a279f48d8451671cf", +"None": "2279ed9a279f48d8451671cf", +"bigquery": "2279ed9a279f48d8451671cf", +"databricks": "2279ed9a279f48d8451671cf", +"duckdb": "2279ed9a279f48d8451671cf", +"generic": "2279ed9a279f48d8451671cf", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "2279ed9a279f48d8451671cf", +"postgres": "2279ed9a279f48d8451671cf", +"postgresql": "2279ed9a279f48d8451671cf", +"snowflake": "2279ed9a279f48d8451671cf", +"tsql": "2279ed9a279f48d8451671cf" +} +], +[ +"type", +{ +"DuckDB": "881106a4a0d2de0ff7c56373", +"None": "881106a4a0d2de0ff7c56373", +"bigquery": "881106a4a0d2de0ff7c56373", +"databricks": "881106a4a0d2de0ff7c56373", +"duckdb": "881106a4a0d2de0ff7c56373", +"generic": "881106a4a0d2de0ff7c56373", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "881106a4a0d2de0ff7c56373", +"postgres": "881106a4a0d2de0ff7c56373", +"postgresql": "881106a4a0d2de0ff7c56373", +"snowflake": "881106a4a0d2de0ff7c56373", +"tsql": "881106a4a0d2de0ff7c56373" +} +], +[ +"type", +{ +"DuckDB": "f46cf4b4e131aa122b5b33d6", +"None": "f46cf4b4e131aa122b5b33d6", +"bigquery": "f46cf4b4e131aa122b5b33d6", +"databricks": "f46cf4b4e131aa122b5b33d6", +"duckdb": "f46cf4b4e131aa122b5b33d6", +"generic": "f46cf4b4e131aa122b5b33d6", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "f46cf4b4e131aa122b5b33d6", +"postgres": "f46cf4b4e131aa122b5b33d6", +"postgresql": "f46cf4b4e131aa122b5b33d6", +"snowflake": "f46cf4b4e131aa122b5b33d6", +"tsql": "f46cf4b4e131aa122b5b33d6" +} +], +[ +"type", +{ +"DuckDB": "8441d00030df06ad6a5534d3", +"None": "8441d00030df06ad6a5534d3", +"bigquery": "c9b810639795a7bfab91b98d", +"databricks": "8441d00030df06ad6a5534d3", +"duckdb": "8441d00030df06ad6a5534d3", +"generic": "8441d00030df06ad6a5534d3", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "8441d00030df06ad6a5534d3", +"postgres": "8441d00030df06ad6a5534d3", +"postgresql": "8441d00030df06ad6a5534d3", +"snowflake": "97a20344d811fb77c7690863", +"tsql": "8441d00030df06ad6a5534d3" +} +], +[ +"type", +{ +"DuckDB": "0475b57e9e9da81e87fa09ba", +"None": "0475b57e9e9da81e87fa09ba", +"bigquery": "0475b57e9e9da81e87fa09ba", +"databricks": "0475b57e9e9da81e87fa09ba", +"duckdb": "0475b57e9e9da81e87fa09ba", +"generic": "0475b57e9e9da81e87fa09ba", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "0475b57e9e9da81e87fa09ba", +"postgres": "0475b57e9e9da81e87fa09ba", +"postgresql": "0475b57e9e9da81e87fa09ba", +"snowflake": "0475b57e9e9da81e87fa09ba", +"tsql": "0475b57e9e9da81e87fa09ba" +} +], +[ +"type", +{ +"DuckDB": "43e3e82e80c9c1580eb61a1d", +"None": "43e3e82e80c9c1580eb61a1d", +"bigquery": "43e3e82e80c9c1580eb61a1d", +"databricks": "43e3e82e80c9c1580eb61a1d", +"duckdb": "43e3e82e80c9c1580eb61a1d", +"generic": "43e3e82e80c9c1580eb61a1d", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "43e3e82e80c9c1580eb61a1d", +"postgres": "43e3e82e80c9c1580eb61a1d", +"postgresql": "43e3e82e80c9c1580eb61a1d", +"snowflake": "43e3e82e80c9c1580eb61a1d", +"tsql": "43e3e82e80c9c1580eb61a1d" +} +], +[ +"type", +{ +"DuckDB": "51b0e597909858f7f7aa4571", +"None": "51b0e597909858f7f7aa4571", +"bigquery": "109f87d65cfb16897db6a7a6", +"databricks": "846f4ee64c34aab0cdabb9a0", +"duckdb": "51b0e597909858f7f7aa4571", +"generic": "51b0e597909858f7f7aa4571", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "51b0e597909858f7f7aa4571", +"postgres": "51b0e597909858f7f7aa4571", +"postgresql": "51b0e597909858f7f7aa4571", +"snowflake": "4d94d72d93a870dcc1521bee", +"tsql": "51b0e597909858f7f7aa4571" +} +], +[ +"type", +{ +"DuckDB": "962ea05bab624c1f8c259a65", +"None": "962ea05bab624c1f8c259a65", +"bigquery": "962ea05bab624c1f8c259a65", +"databricks": "962ea05bab624c1f8c259a65", +"duckdb": "962ea05bab624c1f8c259a65", +"generic": "962ea05bab624c1f8c259a65", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "962ea05bab624c1f8c259a65", +"postgres": "962ea05bab624c1f8c259a65", +"postgresql": "962ea05bab624c1f8c259a65", +"snowflake": "962ea05bab624c1f8c259a65", +"tsql": "962ea05bab624c1f8c259a65" +} +], +[ +"type", +{ +"DuckDB": "1275b5b0c52f69cf592c004b", +"None": "1275b5b0c52f69cf592c004b", +"bigquery": "1275b5b0c52f69cf592c004b", +"databricks": "1275b5b0c52f69cf592c004b", +"duckdb": "1275b5b0c52f69cf592c004b", +"generic": "1275b5b0c52f69cf592c004b", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "1275b5b0c52f69cf592c004b", +"postgres": "1275b5b0c52f69cf592c004b", +"postgresql": "1275b5b0c52f69cf592c004b", +"snowflake": "1275b5b0c52f69cf592c004b", +"tsql": "1275b5b0c52f69cf592c004b" +} +], +[ +"type", +{ +"DuckDB": "a01889d0707cf6b364efb5f9", +"None": "94834ae92073b4606184619b", +"bigquery": "11d9e4471b50590a198e94a1", +"databricks": "11d9e4471b50590a198e94a1", +"duckdb": "a01889d0707cf6b364efb5f9", +"generic": "94834ae92073b4606184619b", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "11d9e4471b50590a198e94a1", +"postgres": "a01889d0707cf6b364efb5f9", +"postgresql": "a01889d0707cf6b364efb5f9", +"snowflake": "5bc09c1a33ccb4bd2e4075e5", +"tsql": "d1dc9a140dbe2eb1874c6ad7" +} +], +[ +"type", +{ +"DuckDB": "19a1a80ffc06169f32694de8", +"None": "19a1a80ffc06169f32694de8", +"bigquery": "19a1a80ffc06169f32694de8", +"databricks": "19a1a80ffc06169f32694de8", +"duckdb": "19a1a80ffc06169f32694de8", +"generic": "19a1a80ffc06169f32694de8", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "19a1a80ffc06169f32694de8", +"postgres": "19a1a80ffc06169f32694de8", +"postgresql": "19a1a80ffc06169f32694de8", +"snowflake": "19a1a80ffc06169f32694de8", +"tsql": "19a1a80ffc06169f32694de8" +} +], +[ +"type", +{ +"DuckDB": "c43574432afc90bcba6944b2", +"None": "bf431bf304d57dd7b16797df", +"bigquery": "bf431bf304d57dd7b16797df", +"databricks": "bf431bf304d57dd7b16797df", +"duckdb": "c43574432afc90bcba6944b2", +"generic": "bf431bf304d57dd7b16797df", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "6c03a3450ea4742ee7396e3c", +"postgres": "b462303a5e5a209df5a75e4b", +"postgresql": "b462303a5e5a209df5a75e4b", +"snowflake": "26094c8570001998e247761e", +"tsql": "ba3896413716dbcd432e62dd" +} +], +[ +"type", +{ +"DuckDB": "66f7ca02161349d637fa7d4e", +"None": "66f7ca02161349d637fa7d4e", +"bigquery": "d90a78129f7050a540984f6f", +"databricks": "d90a78129f7050a540984f6f", +"duckdb": "66f7ca02161349d637fa7d4e", +"generic": "66f7ca02161349d637fa7d4e", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "d90a78129f7050a540984f6f", +"postgres": "66f7ca02161349d637fa7d4e", +"postgresql": "66f7ca02161349d637fa7d4e", +"snowflake": "66f7ca02161349d637fa7d4e", +"tsql": "66f7ca02161349d637fa7d4e" +} +], +[ +"type", +{ +"DuckDB": "83fdbd1f0a6ee4e72faa4d94", +"None": "83fdbd1f0a6ee4e72faa4d94", +"bigquery": "83fdbd1f0a6ee4e72faa4d94", +"databricks": "83fdbd1f0a6ee4e72faa4d94", +"duckdb": "83fdbd1f0a6ee4e72faa4d94", +"generic": "83fdbd1f0a6ee4e72faa4d94", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "83fdbd1f0a6ee4e72faa4d94", +"postgres": "83fdbd1f0a6ee4e72faa4d94", +"postgresql": "83fdbd1f0a6ee4e72faa4d94", +"snowflake": "83fdbd1f0a6ee4e72faa4d94", +"tsql": "83fdbd1f0a6ee4e72faa4d94" +} +], +[ +"type", +{ +"DuckDB": "e2879cf4770e7f48d2dd704a", +"None": "e2879cf4770e7f48d2dd704a", +"bigquery": "c9b810639795a7bfab91b98d", +"databricks": "e2879cf4770e7f48d2dd704a", +"duckdb": "e2879cf4770e7f48d2dd704a", +"generic": "e2879cf4770e7f48d2dd704a", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "e2879cf4770e7f48d2dd704a", +"postgres": "e2879cf4770e7f48d2dd704a", +"postgresql": "e2879cf4770e7f48d2dd704a", +"snowflake": "97a20344d811fb77c7690863", +"tsql": "e2879cf4770e7f48d2dd704a" +} +], +[ +"type", +{ +"DuckDB": "7c8df74df226e73b459bfdba", +"None": "7c8df74df226e73b459bfdba", +"bigquery": "7c8df74df226e73b459bfdba", +"databricks": "7c8df74df226e73b459bfdba", +"duckdb": "7c8df74df226e73b459bfdba", +"generic": "7c8df74df226e73b459bfdba", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "7c8df74df226e73b459bfdba", +"postgres": "7c8df74df226e73b459bfdba", +"postgresql": "7c8df74df226e73b459bfdba", +"snowflake": "7c8df74df226e73b459bfdba", +"tsql": "7c8df74df226e73b459bfdba" +} +], +[ +"type", +{ +"DuckDB": "8a3f094f18fb4047f0febf59", +"None": "fe23594c781e79cbb0c8927a", +"bigquery": "fe23594c781e79cbb0c8927a", +"databricks": "fe23594c781e79cbb0c8927a", +"duckdb": "8a3f094f18fb4047f0febf59", +"generic": "fe23594c781e79cbb0c8927a", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "fe23594c781e79cbb0c8927a", +"postgres": "fe23594c781e79cbb0c8927a", +"postgresql": "fe23594c781e79cbb0c8927a", +"snowflake": "38b2ec94bf02be40007ce525", +"tsql": "fe23594c781e79cbb0c8927a" +} +], +[ +"type", +{ +"DuckDB": "38b2ec94bf02be40007ce525", +"None": "38b2ec94bf02be40007ce525", +"bigquery": "38b2ec94bf02be40007ce525", +"databricks": "38b2ec94bf02be40007ce525", +"duckdb": "38b2ec94bf02be40007ce525", +"generic": "38b2ec94bf02be40007ce525", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "38b2ec94bf02be40007ce525", +"postgres": "38b2ec94bf02be40007ce525", +"postgresql": "38b2ec94bf02be40007ce525", +"snowflake": "38b2ec94bf02be40007ce525", +"tsql": "38b2ec94bf02be40007ce525" +} +], +[ +"type", +{ +"DuckDB": "267fe8533e5d50f2cd3eb176", +"None": "8e0e269b33b63f52e24399e2", +"bigquery": "6a9a0937e74ae8ee83e705e4", +"databricks": "6a9a0937e74ae8ee83e705e4", +"duckdb": "267fe8533e5d50f2cd3eb176", +"generic": "8e0e269b33b63f52e24399e2", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "6c03a3450ea4742ee7396e3c", +"postgres": "43767924372e86845ec63bb6", +"postgresql": "43767924372e86845ec63bb6", +"snowflake": "5a7da03d64d9bf65f9984782", +"tsql": "69ccced5b5ccc61253f2656b" +} +], +[ +"type", +{ +"DuckDB": "4920de3b1203a0d66fc1b3cd", +"None": "4920de3b1203a0d66fc1b3cd", +"bigquery": "4920de3b1203a0d66fc1b3cd", +"databricks": "4920de3b1203a0d66fc1b3cd", +"duckdb": "4920de3b1203a0d66fc1b3cd", +"generic": "4920de3b1203a0d66fc1b3cd", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "4920de3b1203a0d66fc1b3cd", +"postgres": "4920de3b1203a0d66fc1b3cd", +"postgresql": "4920de3b1203a0d66fc1b3cd", +"snowflake": "4920de3b1203a0d66fc1b3cd", +"tsql": "4920de3b1203a0d66fc1b3cd" +} +], +[ +"type", +{ +"DuckDB": "7914189ff18b0e70ddf7d042", +"None": "7914189ff18b0e70ddf7d042", +"bigquery": "b0477b36767a62145aa9158c", +"databricks": "7914189ff18b0e70ddf7d042", +"duckdb": "7914189ff18b0e70ddf7d042", +"generic": "7914189ff18b0e70ddf7d042", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "7914189ff18b0e70ddf7d042", +"postgres": "7914189ff18b0e70ddf7d042", +"postgresql": "7914189ff18b0e70ddf7d042", +"snowflake": "652ff8b21f638eac8fdc46c5", +"tsql": "7914189ff18b0e70ddf7d042" +} +], +[ +"type", +{ +"DuckDB": "c6889f2965db73017be6f6e7", +"None": "c6889f2965db73017be6f6e7", +"bigquery": "a428302e4848ffe877284c84", +"databricks": "c6889f2965db73017be6f6e7", +"duckdb": "c6889f2965db73017be6f6e7", +"generic": "c6889f2965db73017be6f6e7", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "c6889f2965db73017be6f6e7", +"postgres": "c6889f2965db73017be6f6e7", +"postgresql": "c6889f2965db73017be6f6e7", +"snowflake": "652ff8b21f638eac8fdc46c5", +"tsql": "c6889f2965db73017be6f6e7" +} +], +[ +"type", +{ +"DuckDB": "4d0f0db1a550ed1e0da1a043", +"None": "4d0f0db1a550ed1e0da1a043", +"bigquery": "4d0f0db1a550ed1e0da1a043", +"databricks": "4d0f0db1a550ed1e0da1a043", +"duckdb": "4d0f0db1a550ed1e0da1a043", +"generic": "4d0f0db1a550ed1e0da1a043", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "4d0f0db1a550ed1e0da1a043", +"postgres": "4d0f0db1a550ed1e0da1a043", +"postgresql": "4d0f0db1a550ed1e0da1a043", +"snowflake": "4d0f0db1a550ed1e0da1a043", +"tsql": "4d0f0db1a550ed1e0da1a043" +} +], +[ +"type", +{ +"DuckDB": "a9d9e03f8e981cec9dca7694", +"None": "a9d9e03f8e981cec9dca7694", +"bigquery": "a9d9e03f8e981cec9dca7694", +"databricks": "a9d9e03f8e981cec9dca7694", +"duckdb": "a9d9e03f8e981cec9dca7694", +"generic": "a9d9e03f8e981cec9dca7694", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "a9d9e03f8e981cec9dca7694", +"postgres": "a9d9e03f8e981cec9dca7694", +"postgresql": "a9d9e03f8e981cec9dca7694", +"snowflake": "a9d9e03f8e981cec9dca7694", +"tsql": "a9d9e03f8e981cec9dca7694" +} +], +[ +"type", +{ +"DuckDB": "95961ec6c293c3d6b6bf65ec", +"None": "95961ec6c293c3d6b6bf65ec", +"bigquery": "95961ec6c293c3d6b6bf65ec", +"databricks": "95961ec6c293c3d6b6bf65ec", +"duckdb": "95961ec6c293c3d6b6bf65ec", +"generic": "95961ec6c293c3d6b6bf65ec", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "95961ec6c293c3d6b6bf65ec", +"postgres": "95961ec6c293c3d6b6bf65ec", +"postgresql": "95961ec6c293c3d6b6bf65ec", +"snowflake": "95961ec6c293c3d6b6bf65ec", +"tsql": "95961ec6c293c3d6b6bf65ec" +} +], +[ +"type", +{ +"DuckDB": "2c5e4442c23cf9e2b37caa7e", +"None": "2c5e4442c23cf9e2b37caa7e", +"bigquery": "2c5e4442c23cf9e2b37caa7e", +"databricks": "2c5e4442c23cf9e2b37caa7e", +"duckdb": "2c5e4442c23cf9e2b37caa7e", +"generic": "2c5e4442c23cf9e2b37caa7e", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "2c5e4442c23cf9e2b37caa7e", +"postgres": "2c5e4442c23cf9e2b37caa7e", +"postgresql": "2c5e4442c23cf9e2b37caa7e", +"snowflake": "2c5e4442c23cf9e2b37caa7e", +"tsql": "2c5e4442c23cf9e2b37caa7e" +} +], +[ +"type", +{ +"DuckDB": "a428302e4848ffe877284c84", +"None": "a428302e4848ffe877284c84", +"bigquery": "a428302e4848ffe877284c84", +"databricks": "a428302e4848ffe877284c84", +"duckdb": "a428302e4848ffe877284c84", +"generic": "a428302e4848ffe877284c84", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "a428302e4848ffe877284c84", +"postgres": "a428302e4848ffe877284c84", +"postgresql": "a428302e4848ffe877284c84", +"snowflake": "652ff8b21f638eac8fdc46c5", +"tsql": "a428302e4848ffe877284c84" +} +], +[ +"type", +{ +"DuckDB": "8702414b6372d27d90111c0d", +"None": "a7fcdf83ba95c5481cac4059", +"bigquery": "1ebb508c9c012fda785eac26", +"databricks": "1ebb508c9c012fda785eac26", +"duckdb": "8702414b6372d27d90111c0d", +"generic": "a7fcdf83ba95c5481cac4059", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "1ebb508c9c012fda785eac26", +"postgres": "8702414b6372d27d90111c0d", +"postgresql": "8702414b6372d27d90111c0d", +"snowflake": "521d89d8efac986351afc368", +"tsql": "1ebb508c9c012fda785eac26" +} +], +[ +"type", +{ +"DuckDB": "38b2ec94bf02be40007ce525", +"None": "38b2ec94bf02be40007ce525", +"bigquery": "38b2ec94bf02be40007ce525", +"databricks": "38b2ec94bf02be40007ce525", +"duckdb": "38b2ec94bf02be40007ce525", +"generic": "38b2ec94bf02be40007ce525", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "38b2ec94bf02be40007ce525", +"postgres": "38b2ec94bf02be40007ce525", +"postgresql": "38b2ec94bf02be40007ce525", +"snowflake": "38b2ec94bf02be40007ce525", +"tsql": "38b2ec94bf02be40007ce525" +} +], +[ +"type", +{ +"DuckDB": "3dbbe73ee4310c73030e8110", +"None": "3dbbe73ee4310c73030e8110", +"bigquery": "3dbbe73ee4310c73030e8110", +"databricks": "3dbbe73ee4310c73030e8110", +"duckdb": "3dbbe73ee4310c73030e8110", +"generic": "3dbbe73ee4310c73030e8110", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "3dbbe73ee4310c73030e8110", +"postgres": "3dbbe73ee4310c73030e8110", +"postgresql": "3dbbe73ee4310c73030e8110", +"snowflake": "f43dac38f34a1c0618a3f812", +"tsql": "3dbbe73ee4310c73030e8110" +} +], +[ +"type", +{ +"DuckDB": "62368fc15cefd5807807b209", +"None": "62368fc15cefd5807807b209", +"bigquery": "e6ffdece2977be55da73b59a", +"databricks": "62368fc15cefd5807807b209", +"duckdb": "62368fc15cefd5807807b209", +"generic": "62368fc15cefd5807807b209", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "62368fc15cefd5807807b209", +"postgres": "62368fc15cefd5807807b209", +"postgresql": "62368fc15cefd5807807b209", +"snowflake": "62368fc15cefd5807807b209", +"tsql": "62368fc15cefd5807807b209" +} +], +[ +"type", +{ +"DuckDB": "72bd5e38b32893397eb51579", +"None": "730d7cf7510ba0934828d971", +"bigquery": "730d7cf7510ba0934828d971", +"databricks": "730d7cf7510ba0934828d971", +"duckdb": "72bd5e38b32893397eb51579", +"generic": "730d7cf7510ba0934828d971", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "1bdf5908ca249b2331a0427c", +"postgres": "1bdf5908ca249b2331a0427c", +"postgresql": "1bdf5908ca249b2331a0427c", +"snowflake": "8ff614b7306c0edbe36ce00b", +"tsql": "1bdf5908ca249b2331a0427c" +} +], +[ +"type", +{ +"DuckDB": "dd061dac05d8a112fce62140", +"None": "dd061dac05d8a112fce62140", +"bigquery": "dd061dac05d8a112fce62140", +"databricks": "dd061dac05d8a112fce62140", +"duckdb": "dd061dac05d8a112fce62140", +"generic": "dd061dac05d8a112fce62140", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "dd061dac05d8a112fce62140", +"postgres": "dd061dac05d8a112fce62140", +"postgresql": "dd061dac05d8a112fce62140", +"snowflake": "dd061dac05d8a112fce62140", +"tsql": "dd061dac05d8a112fce62140" +} +], +[ +"type", +{ +"DuckDB": "d7b4d15e2e3140069c23e6d4", +"None": "d7b4d15e2e3140069c23e6d4", +"bigquery": "ba82290eb0d38f9638b8b0dc", +"databricks": "9ce61cdfd35b2a8b31faa983", +"duckdb": "d7b4d15e2e3140069c23e6d4", +"generic": "d7b4d15e2e3140069c23e6d4", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "d7b4d15e2e3140069c23e6d4", +"postgres": "d7b4d15e2e3140069c23e6d4", +"postgresql": "d7b4d15e2e3140069c23e6d4", +"snowflake": "906644f12c56f91f8767953d", +"tsql": "d7b4d15e2e3140069c23e6d4" +} +], +[ +"type", +{ +"DuckDB": "cd932c5de0731b5ff7bddd24", +"None": "cd932c5de0731b5ff7bddd24", +"bigquery": "cd932c5de0731b5ff7bddd24", +"databricks": "cd932c5de0731b5ff7bddd24", +"duckdb": "cd932c5de0731b5ff7bddd24", +"generic": "cd932c5de0731b5ff7bddd24", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "cd932c5de0731b5ff7bddd24", +"postgres": "cd932c5de0731b5ff7bddd24", +"postgresql": "cd932c5de0731b5ff7bddd24", +"snowflake": "cd932c5de0731b5ff7bddd24", +"tsql": "cd932c5de0731b5ff7bddd24" +} +], +[ +"type", +{ +"DuckDB": "104d3e046c47032c37f947b8", +"None": "104d3e046c47032c37f947b8", +"bigquery": "104d3e046c47032c37f947b8", +"databricks": "104d3e046c47032c37f947b8", +"duckdb": "104d3e046c47032c37f947b8", +"generic": "104d3e046c47032c37f947b8", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "104d3e046c47032c37f947b8", +"postgres": "104d3e046c47032c37f947b8", +"postgresql": "104d3e046c47032c37f947b8", +"snowflake": "104d3e046c47032c37f947b8", +"tsql": "104d3e046c47032c37f947b8" +} +], +[ +"type", +{ +"DuckDB": "f179445103bc721a2dc04002", +"None": "f179445103bc721a2dc04002", +"bigquery": "f179445103bc721a2dc04002", +"databricks": "f179445103bc721a2dc04002", +"duckdb": "f179445103bc721a2dc04002", +"generic": "f179445103bc721a2dc04002", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "f179445103bc721a2dc04002", +"postgres": "f179445103bc721a2dc04002", +"postgresql": "f179445103bc721a2dc04002", +"snowflake": "f179445103bc721a2dc04002", +"tsql": "f179445103bc721a2dc04002" +} +], +[ +"type", +{ +"DuckDB": "7a924f1a13854aa3260f3f57", +"None": "7a924f1a13854aa3260f3f57", +"bigquery": "7a924f1a13854aa3260f3f57", +"databricks": "7a924f1a13854aa3260f3f57", +"duckdb": "7a924f1a13854aa3260f3f57", +"generic": "7a924f1a13854aa3260f3f57", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "7a924f1a13854aa3260f3f57", +"postgres": "7a924f1a13854aa3260f3f57", +"postgresql": "7a924f1a13854aa3260f3f57", +"snowflake": "7a924f1a13854aa3260f3f57", +"tsql": "7a924f1a13854aa3260f3f57" +} +], +[ +"type", +{ +"DuckDB": "3d4143f0295abc5ed5a3d8cc", +"None": "3d4143f0295abc5ed5a3d8cc", +"bigquery": "3d4143f0295abc5ed5a3d8cc", +"databricks": "3d4143f0295abc5ed5a3d8cc", +"duckdb": "3d4143f0295abc5ed5a3d8cc", +"generic": "3d4143f0295abc5ed5a3d8cc", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "3d4143f0295abc5ed5a3d8cc", +"postgres": "3d4143f0295abc5ed5a3d8cc", +"postgresql": "3d4143f0295abc5ed5a3d8cc", +"snowflake": "3d4143f0295abc5ed5a3d8cc", +"tsql": "3d4143f0295abc5ed5a3d8cc" +} +], +[ +"type", +{ +"DuckDB": "3f71ab5f3c1c040da96f2cec", +"None": "3f71ab5f3c1c040da96f2cec", +"bigquery": "3f71ab5f3c1c040da96f2cec", +"databricks": "3f71ab5f3c1c040da96f2cec", +"duckdb": "3f71ab5f3c1c040da96f2cec", +"generic": "3f71ab5f3c1c040da96f2cec", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "3f71ab5f3c1c040da96f2cec", +"postgres": "3f71ab5f3c1c040da96f2cec", +"postgresql": "3f71ab5f3c1c040da96f2cec", +"snowflake": "3f71ab5f3c1c040da96f2cec", +"tsql": "3f71ab5f3c1c040da96f2cec" +} +], +[ +"type", +{ +"DuckDB": "d4a375fcf7c3190951992469", +"None": "d4a375fcf7c3190951992469", +"bigquery": "5226d7e2a62c7650a87d6e84", +"databricks": "d4a375fcf7c3190951992469", +"duckdb": "d4a375fcf7c3190951992469", +"generic": "d4a375fcf7c3190951992469", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "d4a375fcf7c3190951992469", +"postgres": "d4a375fcf7c3190951992469", +"postgresql": "d4a375fcf7c3190951992469", +"snowflake": "6306b9e88f7b13dbb6a32c00", +"tsql": "d4a375fcf7c3190951992469" +} +], +[ +"type", +{ +"DuckDB": "78709b3317abd96cc20340f7", +"None": "78709b3317abd96cc20340f7", +"bigquery": "78709b3317abd96cc20340f7", +"databricks": "78709b3317abd96cc20340f7", +"duckdb": "78709b3317abd96cc20340f7", +"generic": "78709b3317abd96cc20340f7", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "78709b3317abd96cc20340f7", +"postgres": "78709b3317abd96cc20340f7", +"postgresql": "78709b3317abd96cc20340f7", +"snowflake": "78709b3317abd96cc20340f7", +"tsql": "78709b3317abd96cc20340f7" +} +], +[ +"type", +{ +"DuckDB": "652ff8b21f638eac8fdc46c5", +"None": "652ff8b21f638eac8fdc46c5", +"bigquery": "316ab5126bbd68359eedc4d9", +"databricks": "652ff8b21f638eac8fdc46c5", +"duckdb": "652ff8b21f638eac8fdc46c5", +"generic": "652ff8b21f638eac8fdc46c5", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "652ff8b21f638eac8fdc46c5", +"postgres": "652ff8b21f638eac8fdc46c5", +"postgresql": "652ff8b21f638eac8fdc46c5", +"snowflake": "652ff8b21f638eac8fdc46c5", +"tsql": "652ff8b21f638eac8fdc46c5" +} +], +[ +"type", +{ +"DuckDB": "293fdb322059805900912bee", +"None": "293fdb322059805900912bee", +"bigquery": "293fdb322059805900912bee", +"databricks": "293fdb322059805900912bee", +"duckdb": "293fdb322059805900912bee", +"generic": "293fdb322059805900912bee", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "293fdb322059805900912bee", +"postgres": "293fdb322059805900912bee", +"postgresql": "293fdb322059805900912bee", +"snowflake": "293fdb322059805900912bee", +"tsql": "293fdb322059805900912bee" +} +], +[ +"type", +{ +"DuckDB": "3d23f811a03db519b598c815", +"None": "3d23f811a03db519b598c815", +"bigquery": "3d23f811a03db519b598c815", +"databricks": "3d23f811a03db519b598c815", +"duckdb": "3d23f811a03db519b598c815", +"generic": "3d23f811a03db519b598c815", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "3d23f811a03db519b598c815", +"postgres": "3d23f811a03db519b598c815", +"postgresql": "3d23f811a03db519b598c815", +"snowflake": "3d23f811a03db519b598c815", +"tsql": "3d23f811a03db519b598c815" +} +], +[ +"type", +{ +"DuckDB": "9cf8454127727005f919e6fc", +"None": "9a5c2bd43f94970e2d4d2210", +"bigquery": "2cf01a5fea56869633f3f547", +"databricks": "1231fdcee1164056bb998fd8", +"duckdb": "9cf8454127727005f919e6fc", +"generic": "9a5c2bd43f94970e2d4d2210", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "84e2dbd148c2ae9480447652", +"postgres": "eaa1040a087ac34088fbabf6", +"postgresql": "eaa1040a087ac34088fbabf6", +"snowflake": "143732e0372eaf73cb82cfe7", +"tsql": "bb985bf3c283d9246c714eec" +} +], +[ +"type", +{ +"DuckDB": "2166772bfafca596e1de9d10", +"None": "2166772bfafca596e1de9d10", +"bigquery": "2166772bfafca596e1de9d10", +"databricks": "2166772bfafca596e1de9d10", +"duckdb": "2166772bfafca596e1de9d10", +"generic": "2166772bfafca596e1de9d10", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "2166772bfafca596e1de9d10", +"postgres": "2166772bfafca596e1de9d10", +"postgresql": "2166772bfafca596e1de9d10", +"snowflake": "2166772bfafca596e1de9d10", +"tsql": "2166772bfafca596e1de9d10" +} +], +[ +"type", +{ +"DuckDB": "8441d00030df06ad6a5534d3", +"None": "8441d00030df06ad6a5534d3", +"bigquery": "c9b810639795a7bfab91b98d", +"databricks": "8441d00030df06ad6a5534d3", +"duckdb": "8441d00030df06ad6a5534d3", +"generic": "8441d00030df06ad6a5534d3", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "8441d00030df06ad6a5534d3", +"postgres": "8441d00030df06ad6a5534d3", +"postgresql": "8441d00030df06ad6a5534d3", +"snowflake": "97a20344d811fb77c7690863", +"tsql": "8441d00030df06ad6a5534d3" +} +], +[ +"type", +{ +"DuckDB": "013a8446f043affffcf194f8", +"None": "013a8446f043affffcf194f8", +"bigquery": "013a8446f043affffcf194f8", +"databricks": "013a8446f043affffcf194f8", +"duckdb": "013a8446f043affffcf194f8", +"generic": "013a8446f043affffcf194f8", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "013a8446f043affffcf194f8", +"postgres": "013a8446f043affffcf194f8", +"postgresql": "013a8446f043affffcf194f8", +"snowflake": "97a20344d811fb77c7690863", +"tsql": "013a8446f043affffcf194f8" +} +], +[ +"type", +{ +"DuckDB": "461923a0d34defd0c726d6e5", +"None": "461923a0d34defd0c726d6e5", +"bigquery": "b5c4d5044b2a6e70633f0d0a", +"databricks": "461923a0d34defd0c726d6e5", +"duckdb": "461923a0d34defd0c726d6e5", +"generic": "461923a0d34defd0c726d6e5", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "461923a0d34defd0c726d6e5", +"postgres": "461923a0d34defd0c726d6e5", +"postgresql": "461923a0d34defd0c726d6e5", +"snowflake": "461923a0d34defd0c726d6e5", +"tsql": "461923a0d34defd0c726d6e5" +} +], +[ +"type", +{ +"DuckDB": "dcbfb83ead5b0e32e500635b", +"None": "dcbfb83ead5b0e32e500635b", +"bigquery": "dcbfb83ead5b0e32e500635b", +"databricks": "dcbfb83ead5b0e32e500635b", +"duckdb": "dcbfb83ead5b0e32e500635b", +"generic": "dcbfb83ead5b0e32e500635b", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "dcbfb83ead5b0e32e500635b", +"postgres": "dcbfb83ead5b0e32e500635b", +"postgresql": "dcbfb83ead5b0e32e500635b", +"snowflake": "dcbfb83ead5b0e32e500635b", +"tsql": "dcbfb83ead5b0e32e500635b" +} +], +[ +"type", +{ +"DuckDB": "a686bb6db17ab079cfc79224", +"None": "a686bb6db17ab079cfc79224", +"bigquery": "a686bb6db17ab079cfc79224", +"databricks": "a686bb6db17ab079cfc79224", +"duckdb": "a686bb6db17ab079cfc79224", +"generic": "a686bb6db17ab079cfc79224", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "a686bb6db17ab079cfc79224", +"postgres": "a686bb6db17ab079cfc79224", +"postgresql": "a686bb6db17ab079cfc79224", +"snowflake": "1096c3c8687c8e8eb538ff74", +"tsql": "a686bb6db17ab079cfc79224" +} +], +[ +"type", +{ +"DuckDB": "9d006c5299feb04426ce31ac", +"None": "e2879cf4770e7f48d2dd704a", +"bigquery": "c9b810639795a7bfab91b98d", +"databricks": "e2879cf4770e7f48d2dd704a", +"duckdb": "9d006c5299feb04426ce31ac", +"generic": "e2879cf4770e7f48d2dd704a", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "e2879cf4770e7f48d2dd704a", +"postgres": "e2879cf4770e7f48d2dd704a", +"postgresql": "e2879cf4770e7f48d2dd704a", +"snowflake": "97a20344d811fb77c7690863", +"tsql": "e2879cf4770e7f48d2dd704a" +} +], +[ +"type", +{ +"DuckDB": "d2c97d221599d038d9875873", +"None": "d2c97d221599d038d9875873", +"bigquery": "d2c97d221599d038d9875873", +"databricks": "d2c97d221599d038d9875873", +"duckdb": "d2c97d221599d038d9875873", +"generic": "d2c97d221599d038d9875873", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "d2c97d221599d038d9875873", +"postgres": "d2c97d221599d038d9875873", +"postgresql": "d2c97d221599d038d9875873", +"snowflake": "d2c97d221599d038d9875873", +"tsql": "d2c97d221599d038d9875873" +} +], +[ +"type", +{ +"DuckDB": "013a8446f043affffcf194f8", +"None": "013a8446f043affffcf194f8", +"bigquery": "013a8446f043affffcf194f8", +"databricks": "013a8446f043affffcf194f8", +"duckdb": "013a8446f043affffcf194f8", +"generic": "013a8446f043affffcf194f8", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "013a8446f043affffcf194f8", +"postgres": "013a8446f043affffcf194f8", +"postgresql": "013a8446f043affffcf194f8", +"snowflake": "97a20344d811fb77c7690863", +"tsql": "013a8446f043affffcf194f8" +} +], +[ +"type", +{ +"DuckDB": "a428302e4848ffe877284c84", +"None": "a428302e4848ffe877284c84", +"bigquery": "a428302e4848ffe877284c84", +"databricks": "a428302e4848ffe877284c84", +"duckdb": "a428302e4848ffe877284c84", +"generic": "a428302e4848ffe877284c84", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "a428302e4848ffe877284c84", +"postgres": "a428302e4848ffe877284c84", +"postgresql": "a428302e4848ffe877284c84", +"snowflake": "652ff8b21f638eac8fdc46c5", +"tsql": "a428302e4848ffe877284c84" +} +], +[ +"type", +{ +"DuckDB": "8790273499dae4e6cbd2d034", +"None": "8790273499dae4e6cbd2d034", +"bigquery": "f9bb9d0c419201aea072940b", +"databricks": "8790273499dae4e6cbd2d034", +"duckdb": "8790273499dae4e6cbd2d034", +"generic": "8790273499dae4e6cbd2d034", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "8790273499dae4e6cbd2d034", +"postgres": "8790273499dae4e6cbd2d034", +"postgresql": "8790273499dae4e6cbd2d034", +"snowflake": "9aff7fcc7d550e1a8d105471", +"tsql": "8790273499dae4e6cbd2d034" +} +], +[ +"type", +{ +"DuckDB": "19e127c23b4598727a2d8ceb", +"None": "19e127c23b4598727a2d8ceb", +"bigquery": "6f6198e2d2c8a8d6444ef5af", +"databricks": "e3bc1b8bad22d8104417b00f", +"duckdb": "19e127c23b4598727a2d8ceb", +"generic": "19e127c23b4598727a2d8ceb", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "aed0419e7f2ce7c0a8892248", +"postgres": "19e127c23b4598727a2d8ceb", +"postgresql": "19e127c23b4598727a2d8ceb", +"snowflake": "aed0419e7f2ce7c0a8892248", +"tsql": "19e127c23b4598727a2d8ceb" +} +], +[ +"type", +{ +"DuckDB": "19bdd92ea0cc5fb028657510", +"None": "b8321619b794db091c9e96a1", +"bigquery": "b8321619b794db091c9e96a1", +"databricks": "1e75e5227bea0ae294ac7af1", +"duckdb": "19bdd92ea0cc5fb028657510", +"generic": "b8321619b794db091c9e96a1", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "b8321619b794db091c9e96a1", +"postgres": "b8321619b794db091c9e96a1", +"postgresql": "b8321619b794db091c9e96a1", +"snowflake": "b8321619b794db091c9e96a1", +"tsql": "b8321619b794db091c9e96a1" +} +], +[ +"type", +{ +"DuckDB": "bce60580ef3a1dc4ce569fff", +"None": "bce60580ef3a1dc4ce569fff", +"bigquery": "bce60580ef3a1dc4ce569fff", +"databricks": "bce60580ef3a1dc4ce569fff", +"duckdb": "bce60580ef3a1dc4ce569fff", +"generic": "bce60580ef3a1dc4ce569fff", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "bce60580ef3a1dc4ce569fff", +"postgres": "bce60580ef3a1dc4ce569fff", +"postgresql": "bce60580ef3a1dc4ce569fff", +"snowflake": "bce60580ef3a1dc4ce569fff", +"tsql": "bce60580ef3a1dc4ce569fff" +} +], +[ +"type", +{ +"DuckDB": "305aaf0b95cee629dd46380c", +"None": "d61c83ef8bfdf043fa672cb5", +"bigquery": "c9b810639795a7bfab91b98d", +"databricks": "d61c83ef8bfdf043fa672cb5", +"duckdb": "305aaf0b95cee629dd46380c", +"generic": "d61c83ef8bfdf043fa672cb5", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "d61c83ef8bfdf043fa672cb5", +"postgres": "d61c83ef8bfdf043fa672cb5", +"postgresql": "d61c83ef8bfdf043fa672cb5", +"snowflake": "97a20344d811fb77c7690863", +"tsql": "d61c83ef8bfdf043fa672cb5" +} +], +[ +"type", +{ +"DuckDB": "73ed909ac0c80ba48ae6d17c", +"None": "73ed909ac0c80ba48ae6d17c", +"bigquery": "73ed909ac0c80ba48ae6d17c", +"databricks": "73ed909ac0c80ba48ae6d17c", +"duckdb": "73ed909ac0c80ba48ae6d17c", +"generic": "73ed909ac0c80ba48ae6d17c", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "73ed909ac0c80ba48ae6d17c", +"postgres": "73ed909ac0c80ba48ae6d17c", +"postgresql": "73ed909ac0c80ba48ae6d17c", +"snowflake": "73ed909ac0c80ba48ae6d17c", +"tsql": "73ed909ac0c80ba48ae6d17c" +} +], +[ +"type", +{ +"DuckDB": "c6654395c62d21b415299f72", +"None": "c6654395c62d21b415299f72", +"bigquery": "0712c33a016f7dd6a37ee011", +"databricks": "c6654395c62d21b415299f72", +"duckdb": "c6654395c62d21b415299f72", +"generic": "c6654395c62d21b415299f72", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "2978a8fe925c7f93c6e9fcfb", +"postgres": "c6654395c62d21b415299f72", +"postgresql": "c6654395c62d21b415299f72", +"snowflake": "0712c33a016f7dd6a37ee011", +"tsql": "c6654395c62d21b415299f72" +} +], +[ +"type", +{ +"DuckDB": "c50a316d091c821866e4bfba", +"None": "c50a316d091c821866e4bfba", +"bigquery": "c50a316d091c821866e4bfba", +"databricks": "c50a316d091c821866e4bfba", +"duckdb": "c50a316d091c821866e4bfba", +"generic": "c50a316d091c821866e4bfba", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "c50a316d091c821866e4bfba", +"postgres": "c50a316d091c821866e4bfba", +"postgresql": "c50a316d091c821866e4bfba", +"snowflake": "c50a316d091c821866e4bfba", +"tsql": "c50a316d091c821866e4bfba" +} +], +[ +"type", +{ +"DuckDB": "5abf4ec799a2ec32fb10da7e", +"None": "5abf4ec799a2ec32fb10da7e", +"bigquery": "5abf4ec799a2ec32fb10da7e", +"databricks": "5abf4ec799a2ec32fb10da7e", +"duckdb": "5abf4ec799a2ec32fb10da7e", +"generic": "5abf4ec799a2ec32fb10da7e", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "5abf4ec799a2ec32fb10da7e", +"postgres": "5abf4ec799a2ec32fb10da7e", +"postgresql": "5abf4ec799a2ec32fb10da7e", +"snowflake": "a5656d70e208254d1d3e9b4f", +"tsql": "5abf4ec799a2ec32fb10da7e" +} +], +[ +"type", +{ +"DuckDB": "53100c87dc0e46dc31d2c6cc", +"None": "53100c87dc0e46dc31d2c6cc", +"bigquery": "53100c87dc0e46dc31d2c6cc", +"databricks": "53100c87dc0e46dc31d2c6cc", +"duckdb": "53100c87dc0e46dc31d2c6cc", +"generic": "53100c87dc0e46dc31d2c6cc", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "53100c87dc0e46dc31d2c6cc", +"postgres": "53100c87dc0e46dc31d2c6cc", +"postgresql": "53100c87dc0e46dc31d2c6cc", +"snowflake": "53100c87dc0e46dc31d2c6cc", +"tsql": "53100c87dc0e46dc31d2c6cc" +} +], +[ +"type", +{ +"DuckDB": "081a4ec9ca8c1ffbb8c41e4d", +"None": "6992a9c8899f9fe5de26869c", +"bigquery": "6992a9c8899f9fe5de26869c", +"databricks": "6992a9c8899f9fe5de26869c", +"duckdb": "081a4ec9ca8c1ffbb8c41e4d", +"generic": "6992a9c8899f9fe5de26869c", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "6c03a3450ea4742ee7396e3c", +"postgres": "081a4ec9ca8c1ffbb8c41e4d", +"postgresql": "081a4ec9ca8c1ffbb8c41e4d", +"snowflake": "808e51c2deac58e29ecb851e", +"tsql": "8aa3dfa0d32e1cbc68a6e4d3" +} +], +[ +"type", +{ +"DuckDB": "0c4610f182f18bf41d306e01", +"None": "0c4610f182f18bf41d306e01", +"bigquery": "0c4610f182f18bf41d306e01", +"databricks": "0c4610f182f18bf41d306e01", +"duckdb": "0c4610f182f18bf41d306e01", +"generic": "0c4610f182f18bf41d306e01", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "0c4610f182f18bf41d306e01", +"postgres": "0c4610f182f18bf41d306e01", +"postgresql": "0c4610f182f18bf41d306e01", +"snowflake": "0c4610f182f18bf41d306e01", +"tsql": "0c4610f182f18bf41d306e01" +} +], +[ +"type", +{ +"DuckDB": "e068bc199d71601c823bb254", +"None": "e068bc199d71601c823bb254", +"bigquery": "e068bc199d71601c823bb254", +"databricks": "e068bc199d71601c823bb254", +"duckdb": "e068bc199d71601c823bb254", +"generic": "e068bc199d71601c823bb254", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "e068bc199d71601c823bb254", +"postgres": "e068bc199d71601c823bb254", +"postgresql": "e068bc199d71601c823bb254", +"snowflake": "e068bc199d71601c823bb254", +"tsql": "e068bc199d71601c823bb254" +} +], +[ +"type", +{ +"DuckDB": "18036ada4276b0930d870788", +"None": "18036ada4276b0930d870788", +"bigquery": "18036ada4276b0930d870788", +"databricks": "18036ada4276b0930d870788", +"duckdb": "18036ada4276b0930d870788", +"generic": "18036ada4276b0930d870788", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "18036ada4276b0930d870788", +"postgres": "18036ada4276b0930d870788", +"postgresql": "18036ada4276b0930d870788", +"snowflake": "18036ada4276b0930d870788", +"tsql": "18036ada4276b0930d870788" +} +], +[ +"type", +{ +"DuckDB": "3b86998e2968bafafb02d6c0", +"None": "2f6a1345f274f18462c576a9", +"bigquery": "1cf06c90ca1d122a72b1be9f", +"databricks": "360298d6139a1e6f476862de", +"duckdb": "3b86998e2968bafafb02d6c0", +"generic": "2f6a1345f274f18462c576a9", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "6c03a3450ea4742ee7396e3c", +"postgres": "3b86998e2968bafafb02d6c0", +"postgresql": "3b86998e2968bafafb02d6c0", +"snowflake": "f5272904633fd6945c70dc00", +"tsql": "d1dc9a140dbe2eb1874c6ad7" +} +], +[ +"type", +{ +"DuckDB": "c6889f2965db73017be6f6e7", +"None": "c6889f2965db73017be6f6e7", +"bigquery": "a428302e4848ffe877284c84", +"databricks": "c6889f2965db73017be6f6e7", +"duckdb": "c6889f2965db73017be6f6e7", +"generic": "c6889f2965db73017be6f6e7", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "c6889f2965db73017be6f6e7", +"postgres": "c6889f2965db73017be6f6e7", +"postgresql": "c6889f2965db73017be6f6e7", +"snowflake": "652ff8b21f638eac8fdc46c5", +"tsql": "c6889f2965db73017be6f6e7" +} +], +[ +"type", +{ +"DuckDB": "1eb7fb4e8cf75773c5573562", +"None": "1eb7fb4e8cf75773c5573562", +"bigquery": "c9b810639795a7bfab91b98d", +"databricks": "1eb7fb4e8cf75773c5573562", +"duckdb": "1eb7fb4e8cf75773c5573562", +"generic": "1eb7fb4e8cf75773c5573562", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "1eb7fb4e8cf75773c5573562", +"postgres": "1eb7fb4e8cf75773c5573562", +"postgresql": "1eb7fb4e8cf75773c5573562", +"snowflake": "97a20344d811fb77c7690863", +"tsql": "1eb7fb4e8cf75773c5573562" +} +], +[ +"type", +{ +"DuckDB": "93fcb7d3c2979f1531daccf5", +"None": "93fcb7d3c2979f1531daccf5", +"bigquery": "93fcb7d3c2979f1531daccf5", +"databricks": "93fcb7d3c2979f1531daccf5", +"duckdb": "93fcb7d3c2979f1531daccf5", +"generic": "93fcb7d3c2979f1531daccf5", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "93fcb7d3c2979f1531daccf5", +"postgres": "93fcb7d3c2979f1531daccf5", +"postgresql": "93fcb7d3c2979f1531daccf5", +"snowflake": "93fcb7d3c2979f1531daccf5", +"tsql": "93fcb7d3c2979f1531daccf5" +} +], +[ +"type", +{ +"DuckDB": "0475b57e9e9da81e87fa09ba", +"None": "0475b57e9e9da81e87fa09ba", +"bigquery": "0475b57e9e9da81e87fa09ba", +"databricks": "0475b57e9e9da81e87fa09ba", +"duckdb": "0475b57e9e9da81e87fa09ba", +"generic": "0475b57e9e9da81e87fa09ba", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "0475b57e9e9da81e87fa09ba", +"postgres": "0475b57e9e9da81e87fa09ba", +"postgresql": "0475b57e9e9da81e87fa09ba", +"snowflake": "0475b57e9e9da81e87fa09ba", +"tsql": "0475b57e9e9da81e87fa09ba" +} +], +[ +"type", +{ +"DuckDB": "f35059f8984f0ac12ad1dc75", +"None": "f35059f8984f0ac12ad1dc75", +"bigquery": "f35059f8984f0ac12ad1dc75", +"databricks": "f35059f8984f0ac12ad1dc75", +"duckdb": "f35059f8984f0ac12ad1dc75", +"generic": "f35059f8984f0ac12ad1dc75", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "f35059f8984f0ac12ad1dc75", +"postgres": "f35059f8984f0ac12ad1dc75", +"postgresql": "f35059f8984f0ac12ad1dc75", +"snowflake": "f35059f8984f0ac12ad1dc75", +"tsql": "f35059f8984f0ac12ad1dc75" +} +], +[ +"type", +{ +"DuckDB": "6226bc03436ecf8fccd39252", +"None": "46487f079f1382836c406de7", +"bigquery": "46487f079f1382836c406de7", +"databricks": "46487f079f1382836c406de7", +"duckdb": "6226bc03436ecf8fccd39252", +"generic": "46487f079f1382836c406de7", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "5aa51d84ac5e6c7a9306f348", +"postgres": "5aa51d84ac5e6c7a9306f348", +"postgresql": "5aa51d84ac5e6c7a9306f348", +"snowflake": "5aa51d84ac5e6c7a9306f348", +"tsql": "5aa51d84ac5e6c7a9306f348" +} +], +[ +"type", +{ +"DuckDB": "3dbbe73ee4310c73030e8110", +"None": "3dbbe73ee4310c73030e8110", +"bigquery": "3dbbe73ee4310c73030e8110", +"databricks": "3dbbe73ee4310c73030e8110", +"duckdb": "3dbbe73ee4310c73030e8110", +"generic": "3dbbe73ee4310c73030e8110", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "3dbbe73ee4310c73030e8110", +"postgres": "3dbbe73ee4310c73030e8110", +"postgresql": "3dbbe73ee4310c73030e8110", +"snowflake": "f43dac38f34a1c0618a3f812", +"tsql": "3dbbe73ee4310c73030e8110" +} +], +[ +"type", +{ +"DuckDB": "f43dac38f34a1c0618a3f812", +"None": "f43dac38f34a1c0618a3f812", +"bigquery": "946d5ee30ab7469c57d850df", +"databricks": "f43dac38f34a1c0618a3f812", +"duckdb": "f43dac38f34a1c0618a3f812", +"generic": "f43dac38f34a1c0618a3f812", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "f43dac38f34a1c0618a3f812", +"postgres": "f43dac38f34a1c0618a3f812", +"postgresql": "f43dac38f34a1c0618a3f812", +"snowflake": "f43dac38f34a1c0618a3f812", +"tsql": "f43dac38f34a1c0618a3f812" +} +], +[ +"type", +{ +"DuckDB": "42a76d5ff05d0f91911ff368", +"None": "42a76d5ff05d0f91911ff368", +"bigquery": "42a76d5ff05d0f91911ff368", +"databricks": "42a76d5ff05d0f91911ff368", +"duckdb": "42a76d5ff05d0f91911ff368", +"generic": "42a76d5ff05d0f91911ff368", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "42a76d5ff05d0f91911ff368", +"postgres": "42a76d5ff05d0f91911ff368", +"postgresql": "42a76d5ff05d0f91911ff368", +"snowflake": "42a76d5ff05d0f91911ff368", +"tsql": "42a76d5ff05d0f91911ff368" +} +], +[ +"type", +{ +"DuckDB": "7cd31289a5b99b5a5e24492d", +"None": "7cd31289a5b99b5a5e24492d", +"bigquery": "7cd31289a5b99b5a5e24492d", +"databricks": "7cd31289a5b99b5a5e24492d", +"duckdb": "7cd31289a5b99b5a5e24492d", +"generic": "7cd31289a5b99b5a5e24492d", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "7cd31289a5b99b5a5e24492d", +"postgres": "7cd31289a5b99b5a5e24492d", +"postgresql": "7cd31289a5b99b5a5e24492d", +"snowflake": "7cd31289a5b99b5a5e24492d", +"tsql": "7cd31289a5b99b5a5e24492d" +} +], +[ +"type", +{ +"DuckDB": "cbd04e906c540e91d7c8ea88", +"None": "cbd04e906c540e91d7c8ea88", +"bigquery": "b5c4d5044b2a6e70633f0d0a", +"databricks": "cbd04e906c540e91d7c8ea88", +"duckdb": "cbd04e906c540e91d7c8ea88", +"generic": "cbd04e906c540e91d7c8ea88", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "cbd04e906c540e91d7c8ea88", +"postgres": "cbd04e906c540e91d7c8ea88", +"postgresql": "cbd04e906c540e91d7c8ea88", +"snowflake": "cbd04e906c540e91d7c8ea88", +"tsql": "cbd04e906c540e91d7c8ea88" +} +], +[ +"type", +{ +"DuckDB": "7177019d5faf5b3046623257", +"None": "7177019d5faf5b3046623257", +"bigquery": "7177019d5faf5b3046623257", +"databricks": "7177019d5faf5b3046623257", +"duckdb": "7177019d5faf5b3046623257", +"generic": "7177019d5faf5b3046623257", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "7177019d5faf5b3046623257", +"postgres": "7177019d5faf5b3046623257", +"postgresql": "7177019d5faf5b3046623257", +"snowflake": "7177019d5faf5b3046623257", +"tsql": "7177019d5faf5b3046623257" +} +], +[ +"type", +{ +"DuckDB": "277693b7c19b2696f01403ba", +"None": "277693b7c19b2696f01403ba", +"bigquery": "277693b7c19b2696f01403ba", +"databricks": "277693b7c19b2696f01403ba", +"duckdb": "277693b7c19b2696f01403ba", +"generic": "277693b7c19b2696f01403ba", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "277693b7c19b2696f01403ba", +"postgres": "277693b7c19b2696f01403ba", +"postgresql": "277693b7c19b2696f01403ba", +"snowflake": "277693b7c19b2696f01403ba", +"tsql": "277693b7c19b2696f01403ba" +} +], +[ +"type", +{ +"DuckDB": "c50a316d091c821866e4bfba", +"None": "c50a316d091c821866e4bfba", +"bigquery": "c50a316d091c821866e4bfba", +"databricks": "c50a316d091c821866e4bfba", +"duckdb": "c50a316d091c821866e4bfba", +"generic": "c50a316d091c821866e4bfba", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "c50a316d091c821866e4bfba", +"postgres": "c50a316d091c821866e4bfba", +"postgresql": "c50a316d091c821866e4bfba", +"snowflake": "c50a316d091c821866e4bfba", +"tsql": "c50a316d091c821866e4bfba" +} +], +[ +"type", +{ +"DuckDB": "72bd5e38b32893397eb51579", +"None": "730d7cf7510ba0934828d971", +"bigquery": "730d7cf7510ba0934828d971", +"databricks": "730d7cf7510ba0934828d971", +"duckdb": "72bd5e38b32893397eb51579", +"generic": "730d7cf7510ba0934828d971", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "1bdf5908ca249b2331a0427c", +"postgres": "1bdf5908ca249b2331a0427c", +"postgresql": "1bdf5908ca249b2331a0427c", +"snowflake": "8ff614b7306c0edbe36ce00b", +"tsql": "1bdf5908ca249b2331a0427c" +} +], +[ +"type", +{ +"DuckDB": "e1c74d96ac578f9323bf1bbd", +"None": "e1c74d96ac578f9323bf1bbd", +"bigquery": "e1c74d96ac578f9323bf1bbd", +"databricks": "e1c74d96ac578f9323bf1bbd", +"duckdb": "e1c74d96ac578f9323bf1bbd", +"generic": "e1c74d96ac578f9323bf1bbd", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "e1c74d96ac578f9323bf1bbd", +"postgres": "e1c74d96ac578f9323bf1bbd", +"postgresql": "e1c74d96ac578f9323bf1bbd", +"snowflake": "e1c74d96ac578f9323bf1bbd", +"tsql": "e1c74d96ac578f9323bf1bbd" +} +], +[ +"type", +{ +"DuckDB": "cafb5cff5526dd419baad0ed", +"None": "cafb5cff5526dd419baad0ed", +"bigquery": "cafb5cff5526dd419baad0ed", +"databricks": "cafb5cff5526dd419baad0ed", +"duckdb": "cafb5cff5526dd419baad0ed", +"generic": "cafb5cff5526dd419baad0ed", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "cafb5cff5526dd419baad0ed", +"postgres": "cafb5cff5526dd419baad0ed", +"postgresql": "cafb5cff5526dd419baad0ed", +"snowflake": "cafb5cff5526dd419baad0ed", +"tsql": "cafb5cff5526dd419baad0ed" +} +], +[ +"type", +{ +"DuckDB": "e8b6e0bd2ded7b9eec6209e4", +"None": "e8b6e0bd2ded7b9eec6209e4", +"bigquery": "e8b6e0bd2ded7b9eec6209e4", +"databricks": "e8b6e0bd2ded7b9eec6209e4", +"duckdb": "e8b6e0bd2ded7b9eec6209e4", +"generic": "e8b6e0bd2ded7b9eec6209e4", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "e8b6e0bd2ded7b9eec6209e4", +"postgres": "e8b6e0bd2ded7b9eec6209e4", +"postgresql": "e8b6e0bd2ded7b9eec6209e4", +"snowflake": "e8b6e0bd2ded7b9eec6209e4", +"tsql": "e8b6e0bd2ded7b9eec6209e4" +} +], +[ +"type", +{ +"DuckDB": "b2c9b6ebca6c097f3caa0aa8", +"None": "b2c9b6ebca6c097f3caa0aa8", +"bigquery": "b2c9b6ebca6c097f3caa0aa8", +"databricks": "b2c9b6ebca6c097f3caa0aa8", +"duckdb": "b2c9b6ebca6c097f3caa0aa8", +"generic": "b2c9b6ebca6c097f3caa0aa8", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "b2c9b6ebca6c097f3caa0aa8", +"postgres": "b2c9b6ebca6c097f3caa0aa8", +"postgresql": "b2c9b6ebca6c097f3caa0aa8", +"snowflake": "b2c9b6ebca6c097f3caa0aa8", +"tsql": "b2c9b6ebca6c097f3caa0aa8" +} +], +[ +"type", +{ +"DuckDB": "fe23594c781e79cbb0c8927a", +"None": "fe23594c781e79cbb0c8927a", +"bigquery": "fe23594c781e79cbb0c8927a", +"databricks": "fe23594c781e79cbb0c8927a", +"duckdb": "fe23594c781e79cbb0c8927a", +"generic": "fe23594c781e79cbb0c8927a", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "fe23594c781e79cbb0c8927a", +"postgres": "fe23594c781e79cbb0c8927a", +"postgresql": "fe23594c781e79cbb0c8927a", +"snowflake": "38b2ec94bf02be40007ce525", +"tsql": "fe23594c781e79cbb0c8927a" +} +], +[ +"type", +{ +"DuckDB": "18db5afe2c1e80d1ee652b54", +"None": "18db5afe2c1e80d1ee652b54", +"bigquery": "e1c36a5cdd2427ff2b089ac9", +"databricks": "18db5afe2c1e80d1ee652b54", +"duckdb": "18db5afe2c1e80d1ee652b54", +"generic": "18db5afe2c1e80d1ee652b54", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "18db5afe2c1e80d1ee652b54", +"postgres": "18db5afe2c1e80d1ee652b54", +"postgresql": "18db5afe2c1e80d1ee652b54", +"snowflake": "18db5afe2c1e80d1ee652b54", +"tsql": "18db5afe2c1e80d1ee652b54" +} +], +[ +"type", +{ +"DuckDB": "219314eaf94cabfe1c7e559c", +"None": "4aab4bdd20039d5e16058b1b", +"bigquery": "5524945ebcb15c363d317b3c", +"databricks": "5524945ebcb15c363d317b3c", +"duckdb": "219314eaf94cabfe1c7e559c", +"generic": "4aab4bdd20039d5e16058b1b", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "5524945ebcb15c363d317b3c", +"postgres": "219314eaf94cabfe1c7e559c", +"postgresql": "219314eaf94cabfe1c7e559c", +"snowflake": "b767a0334d4c0090a22665f5", +"tsql": "5524945ebcb15c363d317b3c" +} +], +[ +"type", +{ +"DuckDB": "6a2162b5abe5a73734c47041", +"None": "6a2162b5abe5a73734c47041", +"bigquery": "266b57bc7351f5093413db07", +"databricks": "84e86bec7646b6ad19ceef59", +"duckdb": "6a2162b5abe5a73734c47041", +"generic": "6a2162b5abe5a73734c47041", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "6a2162b5abe5a73734c47041", +"postgres": "6a2162b5abe5a73734c47041", +"postgresql": "6a2162b5abe5a73734c47041", +"snowflake": "16d902e899040d0c0c9dcf58", +"tsql": "6a2162b5abe5a73734c47041" +} +], +[ +"type", +{ +"DuckDB": "8790273499dae4e6cbd2d034", +"None": "8790273499dae4e6cbd2d034", +"bigquery": "f9bb9d0c419201aea072940b", +"databricks": "8790273499dae4e6cbd2d034", +"duckdb": "8790273499dae4e6cbd2d034", +"generic": "8790273499dae4e6cbd2d034", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "8790273499dae4e6cbd2d034", +"postgres": "8790273499dae4e6cbd2d034", +"postgresql": "8790273499dae4e6cbd2d034", +"snowflake": "9aff7fcc7d550e1a8d105471", +"tsql": "8790273499dae4e6cbd2d034" +} +], +[ +"type", +{ +"DuckDB": "669084d1ea704ae5b8ee05c2", +"None": "669084d1ea704ae5b8ee05c2", +"bigquery": "669084d1ea704ae5b8ee05c2", +"databricks": "669084d1ea704ae5b8ee05c2", +"duckdb": "669084d1ea704ae5b8ee05c2", +"generic": "669084d1ea704ae5b8ee05c2", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "669084d1ea704ae5b8ee05c2", +"postgres": "669084d1ea704ae5b8ee05c2", +"postgresql": "669084d1ea704ae5b8ee05c2", +"snowflake": "669084d1ea704ae5b8ee05c2", +"tsql": "669084d1ea704ae5b8ee05c2" +} +], +[ +"type", +{ +"DuckDB": "bf74994a132713cd5a93b70b", +"None": "74d4939af66c472f17ecfa08", +"bigquery": "5f4c9cd249f4322bf4d4cfef", +"databricks": "77298ddff3580b41e361ba6d", +"duckdb": "bf74994a132713cd5a93b70b", +"generic": "74d4939af66c472f17ecfa08", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "ce873d09a353281e316461aa", +"postgres": "cf182821f911fadedb1f868d", +"postgresql": "cf182821f911fadedb1f868d", +"snowflake": "5c5b258591d9f7cb305a4220", +"tsql": "5dab25dee7ce9aba4c71c811" +} +], +[ +"type", +{ +"DuckDB": "b66ef401bfc62ea5f67697f0", +"None": "b66ef401bfc62ea5f67697f0", +"bigquery": "b66ef401bfc62ea5f67697f0", +"databricks": "b66ef401bfc62ea5f67697f0", +"duckdb": "b66ef401bfc62ea5f67697f0", +"generic": "b66ef401bfc62ea5f67697f0", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "b66ef401bfc62ea5f67697f0", +"postgres": "b66ef401bfc62ea5f67697f0", +"postgresql": "b66ef401bfc62ea5f67697f0", +"snowflake": "b66ef401bfc62ea5f67697f0", +"tsql": "b66ef401bfc62ea5f67697f0" +} +], +[ +"type", +{ +"DuckDB": "8203bd5901a8ec71ff7c103e", +"None": "8203bd5901a8ec71ff7c103e", +"bigquery": "2a0918be53051fe629d9ff8f", +"databricks": "8203bd5901a8ec71ff7c103e", +"duckdb": "8203bd5901a8ec71ff7c103e", +"generic": "8203bd5901a8ec71ff7c103e", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "8203bd5901a8ec71ff7c103e", +"postgres": "8203bd5901a8ec71ff7c103e", +"postgresql": "8203bd5901a8ec71ff7c103e", +"snowflake": "8203bd5901a8ec71ff7c103e", +"tsql": "8203bd5901a8ec71ff7c103e" +} +], +[ +"type", +{ +"DuckDB": "aab0389e2b5470136660bf8a", +"None": "aab0389e2b5470136660bf8a", +"bigquery": "c9b810639795a7bfab91b98d", +"databricks": "aab0389e2b5470136660bf8a", +"duckdb": "aab0389e2b5470136660bf8a", +"generic": "aab0389e2b5470136660bf8a", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "aab0389e2b5470136660bf8a", +"postgres": "aab0389e2b5470136660bf8a", +"postgresql": "aab0389e2b5470136660bf8a", +"snowflake": "97a20344d811fb77c7690863", +"tsql": "aab0389e2b5470136660bf8a" +} +], +[ +"type", +{ +"DuckDB": "6199046833cb1b5de6e50c1f", +"None": "6199046833cb1b5de6e50c1f", +"bigquery": "6199046833cb1b5de6e50c1f", +"databricks": "6199046833cb1b5de6e50c1f", +"duckdb": "6199046833cb1b5de6e50c1f", +"generic": "6199046833cb1b5de6e50c1f", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "6199046833cb1b5de6e50c1f", +"postgres": "6199046833cb1b5de6e50c1f", +"postgresql": "6199046833cb1b5de6e50c1f", +"snowflake": "6199046833cb1b5de6e50c1f", +"tsql": "6199046833cb1b5de6e50c1f" +} +], +[ +"type", +{ +"DuckDB": "f1158467f7ab7b47d7e993d0", +"None": "f1158467f7ab7b47d7e993d0", +"bigquery": "f1158467f7ab7b47d7e993d0", +"databricks": "f1158467f7ab7b47d7e993d0", +"duckdb": "f1158467f7ab7b47d7e993d0", +"generic": "f1158467f7ab7b47d7e993d0", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "f1158467f7ab7b47d7e993d0", +"postgres": "f1158467f7ab7b47d7e993d0", +"postgresql": "f1158467f7ab7b47d7e993d0", +"snowflake": "f1158467f7ab7b47d7e993d0", +"tsql": "f1158467f7ab7b47d7e993d0" +} +], +[ +"type", +{ +"DuckDB": "23f70cb2333740d79361d52e", +"None": "23f70cb2333740d79361d52e", +"bigquery": "816384049477221b0a4a5b89", +"databricks": "23f70cb2333740d79361d52e", +"duckdb": "23f70cb2333740d79361d52e", +"generic": "23f70cb2333740d79361d52e", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "23f70cb2333740d79361d52e", +"postgres": "23f70cb2333740d79361d52e", +"postgresql": "23f70cb2333740d79361d52e", +"snowflake": "23f70cb2333740d79361d52e", +"tsql": "23f70cb2333740d79361d52e" +} +], +[ +"type", +{ +"DuckDB": "c50a316d091c821866e4bfba", +"None": "c50a316d091c821866e4bfba", +"bigquery": "c50a316d091c821866e4bfba", +"databricks": "c50a316d091c821866e4bfba", +"duckdb": "c50a316d091c821866e4bfba", +"generic": "c50a316d091c821866e4bfba", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "c50a316d091c821866e4bfba", +"postgres": "c50a316d091c821866e4bfba", +"postgresql": "c50a316d091c821866e4bfba", +"snowflake": "c50a316d091c821866e4bfba", +"tsql": "c50a316d091c821866e4bfba" +} +], +[ +"type", +{ +"DuckDB": "669084d1ea704ae5b8ee05c2", +"None": "669084d1ea704ae5b8ee05c2", +"bigquery": "669084d1ea704ae5b8ee05c2", +"databricks": "669084d1ea704ae5b8ee05c2", +"duckdb": "669084d1ea704ae5b8ee05c2", +"generic": "669084d1ea704ae5b8ee05c2", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "669084d1ea704ae5b8ee05c2", +"postgres": "669084d1ea704ae5b8ee05c2", +"postgresql": "669084d1ea704ae5b8ee05c2", +"snowflake": "669084d1ea704ae5b8ee05c2", +"tsql": "669084d1ea704ae5b8ee05c2" +} +], +[ +"type", +{ +"DuckDB": "527932781ba4bab32cb5e881", +"None": "527932781ba4bab32cb5e881", +"bigquery": "527932781ba4bab32cb5e881", +"databricks": "527932781ba4bab32cb5e881", +"duckdb": "527932781ba4bab32cb5e881", +"generic": "527932781ba4bab32cb5e881", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "527932781ba4bab32cb5e881", +"postgres": "527932781ba4bab32cb5e881", +"postgresql": "527932781ba4bab32cb5e881", +"snowflake": "527932781ba4bab32cb5e881", +"tsql": "527932781ba4bab32cb5e881" +} +], +[ +"type", +{ +"DuckDB": "623dbde002b57284f477b0b5", +"None": "623dbde002b57284f477b0b5", +"bigquery": "623dbde002b57284f477b0b5", +"databricks": "623dbde002b57284f477b0b5", +"duckdb": "623dbde002b57284f477b0b5", +"generic": "623dbde002b57284f477b0b5", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "623dbde002b57284f477b0b5", +"postgres": "623dbde002b57284f477b0b5", +"postgresql": "623dbde002b57284f477b0b5", +"snowflake": "623dbde002b57284f477b0b5", +"tsql": "623dbde002b57284f477b0b5" +} +], +[ +"type", +{ +"DuckDB": "a12a2ad8c11bbf6a41794d33", +"None": "a12a2ad8c11bbf6a41794d33", +"bigquery": "a12a2ad8c11bbf6a41794d33", +"databricks": "a12a2ad8c11bbf6a41794d33", +"duckdb": "a12a2ad8c11bbf6a41794d33", +"generic": "a12a2ad8c11bbf6a41794d33", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "a12a2ad8c11bbf6a41794d33", +"postgres": "a12a2ad8c11bbf6a41794d33", +"postgresql": "a12a2ad8c11bbf6a41794d33", +"snowflake": "a12a2ad8c11bbf6a41794d33", +"tsql": "a12a2ad8c11bbf6a41794d33" +} +], +[ +"type", +{ +"DuckDB": "558da38ec4d9d5d6c72f60cf", +"None": "558da38ec4d9d5d6c72f60cf", +"bigquery": "e6ffdece2977be55da73b59a", +"databricks": "558da38ec4d9d5d6c72f60cf", +"duckdb": "558da38ec4d9d5d6c72f60cf", +"generic": "558da38ec4d9d5d6c72f60cf", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "558da38ec4d9d5d6c72f60cf", +"postgres": "558da38ec4d9d5d6c72f60cf", +"postgresql": "558da38ec4d9d5d6c72f60cf", +"snowflake": "558da38ec4d9d5d6c72f60cf", +"tsql": "558da38ec4d9d5d6c72f60cf" +} +], +[ +"type", +{ +"DuckDB": "363159f251e264604338e690", +"None": "363159f251e264604338e690", +"bigquery": "363159f251e264604338e690", +"databricks": "363159f251e264604338e690", +"duckdb": "363159f251e264604338e690", +"generic": "363159f251e264604338e690", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "363159f251e264604338e690", +"postgres": "363159f251e264604338e690", +"postgresql": "363159f251e264604338e690", +"snowflake": "363159f251e264604338e690", +"tsql": "363159f251e264604338e690" +} +], +[ +"type", +{ +"DuckDB": "b6200c25bc3749f5724d237c", +"None": "b6200c25bc3749f5724d237c", +"bigquery": "b6200c25bc3749f5724d237c", +"databricks": "6b1db1e2f94caeb40dbea19b", +"duckdb": "b6200c25bc3749f5724d237c", +"generic": "b6200c25bc3749f5724d237c", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "6c03a3450ea4742ee7396e3c", +"postgres": "b6200c25bc3749f5724d237c", +"postgresql": "b6200c25bc3749f5724d237c", +"snowflake": "b6200c25bc3749f5724d237c", +"tsql": "b6200c25bc3749f5724d237c" +} +], +[ +"type", +{ +"DuckDB": "e57ac1541fb51b362cd5b470", +"None": "e57ac1541fb51b362cd5b470", +"bigquery": "e57ac1541fb51b362cd5b470", +"databricks": "e57ac1541fb51b362cd5b470", +"duckdb": "e57ac1541fb51b362cd5b470", +"generic": "e57ac1541fb51b362cd5b470", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "e57ac1541fb51b362cd5b470", +"postgres": "e57ac1541fb51b362cd5b470", +"postgresql": "e57ac1541fb51b362cd5b470", +"snowflake": "4b356542044f1267fcfc487a", +"tsql": "e57ac1541fb51b362cd5b470" +} +], +[ +"type", +{ +"DuckDB": "2bfa352725f9d8a91250f75e", +"None": "2bfa352725f9d8a91250f75e", +"bigquery": "2bfa352725f9d8a91250f75e", +"databricks": "2bfa352725f9d8a91250f75e", +"duckdb": "2bfa352725f9d8a91250f75e", +"generic": "2bfa352725f9d8a91250f75e", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "2bfa352725f9d8a91250f75e", +"postgres": "2bfa352725f9d8a91250f75e", +"postgresql": "2bfa352725f9d8a91250f75e", +"snowflake": "2bfa352725f9d8a91250f75e", +"tsql": "2bfa352725f9d8a91250f75e" +} +], +[ +"type", +{ +"DuckDB": "129cd0245509c52e0d7ac815", +"None": "8d1119d9033bc544ced02739", +"bigquery": "ef3ab21b1ec5acc43562f6e2", +"databricks": "5b41dbff68938ce2e8a5c35d", +"duckdb": "129cd0245509c52e0d7ac815", +"generic": "8d1119d9033bc544ced02739", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "b9f1a78bcda3bc968346cc10", +"postgres": "129cd0245509c52e0d7ac815", +"postgresql": "129cd0245509c52e0d7ac815", +"snowflake": "24b68111659c8d395da7df6a", +"tsql": "e42dc1c3607e8e3b3c865c3f" +} +], +[ +"type", +{ +"DuckDB": "60bd7daa04bed898e52118ab", +"None": "070c0836fb3402c924b00b0e", +"bigquery": "3aac0f59706540c7a59cbce4", +"databricks": "070c0836fb3402c924b00b0e", +"duckdb": "60bd7daa04bed898e52118ab", +"generic": "070c0836fb3402c924b00b0e", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "6c03a3450ea4742ee7396e3c", +"postgres": "60bd7daa04bed898e52118ab", +"postgresql": "60bd7daa04bed898e52118ab", +"snowflake": "0a5fcaec13e26e3caacd5345", +"tsql": "33f30462ac4f41af4b28bd1a" +} +], +[ +"type", +{ +"DuckDB": "2f6203391b0efaaf0a3c9d00", +"None": "2f6203391b0efaaf0a3c9d00", +"bigquery": "23266be42b7761d5b86b200a", +"databricks": "94006e4eb73bd1f728de7a83", +"duckdb": "2f6203391b0efaaf0a3c9d00", +"generic": "2f6203391b0efaaf0a3c9d00", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "2f6203391b0efaaf0a3c9d00", +"postgres": "2f6203391b0efaaf0a3c9d00", +"postgresql": "2f6203391b0efaaf0a3c9d00", +"snowflake": "dc61037c72b2e7b4730d26cc", +"tsql": "2f6203391b0efaaf0a3c9d00" +} +], +[ +"type", +{ +"DuckDB": "6a534f7a641457b40e35d984", +"None": "6a534f7a641457b40e35d984", +"bigquery": "6a534f7a641457b40e35d984", +"databricks": "6a534f7a641457b40e35d984", +"duckdb": "6a534f7a641457b40e35d984", +"generic": "6a534f7a641457b40e35d984", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "6a534f7a641457b40e35d984", +"postgres": "6a534f7a641457b40e35d984", +"postgresql": "6a534f7a641457b40e35d984", +"snowflake": "6a534f7a641457b40e35d984", +"tsql": "6a534f7a641457b40e35d984" +} +], +[ +"type", +{ +"DuckDB": "60b39a68a18438603dd5496d", +"None": "60b39a68a18438603dd5496d", +"bigquery": "60b39a68a18438603dd5496d", +"databricks": "60b39a68a18438603dd5496d", +"duckdb": "60b39a68a18438603dd5496d", +"generic": "60b39a68a18438603dd5496d", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "60b39a68a18438603dd5496d", +"postgres": "60b39a68a18438603dd5496d", +"postgresql": "60b39a68a18438603dd5496d", +"snowflake": "60b39a68a18438603dd5496d", +"tsql": "60b39a68a18438603dd5496d" +} +], +[ +"type", +{ +"DuckDB": "126765943545b2608ebe7128", +"None": "126765943545b2608ebe7128", +"bigquery": "126765943545b2608ebe7128", +"databricks": "126765943545b2608ebe7128", +"duckdb": "126765943545b2608ebe7128", +"generic": "126765943545b2608ebe7128", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "126765943545b2608ebe7128", +"postgres": "126765943545b2608ebe7128", +"postgresql": "126765943545b2608ebe7128", +"snowflake": "126765943545b2608ebe7128", +"tsql": "126765943545b2608ebe7128" +} +], +[ +"type", +{ +"DuckDB": "1eb7fb4e8cf75773c5573562", +"None": "1eb7fb4e8cf75773c5573562", +"bigquery": "c9b810639795a7bfab91b98d", +"databricks": "1eb7fb4e8cf75773c5573562", +"duckdb": "1eb7fb4e8cf75773c5573562", +"generic": "1eb7fb4e8cf75773c5573562", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "1eb7fb4e8cf75773c5573562", +"postgres": "1eb7fb4e8cf75773c5573562", +"postgresql": "1eb7fb4e8cf75773c5573562", +"snowflake": "97a20344d811fb77c7690863", +"tsql": "1eb7fb4e8cf75773c5573562" +} +], +[ +"type", +{ +"DuckDB": "9c2cff8be7225cf79883ca65", +"None": "9c2cff8be7225cf79883ca65", +"bigquery": "9c2cff8be7225cf79883ca65", +"databricks": "901ac89f8d9ec18bd3a61e4b", +"duckdb": "9c2cff8be7225cf79883ca65", +"generic": "9c2cff8be7225cf79883ca65", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "901ac89f8d9ec18bd3a61e4b", +"postgres": "9c2cff8be7225cf79883ca65", +"postgresql": "9c2cff8be7225cf79883ca65", +"snowflake": "9c2cff8be7225cf79883ca65", +"tsql": "9c2cff8be7225cf79883ca65" +} +], +[ +"type", +{ +"DuckDB": "cf05d378f282d0abe941a82f", +"None": "cf05d378f282d0abe941a82f", +"bigquery": "cf05d378f282d0abe941a82f", +"databricks": "cf05d378f282d0abe941a82f", +"duckdb": "cf05d378f282d0abe941a82f", +"generic": "cf05d378f282d0abe941a82f", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "cf05d378f282d0abe941a82f", +"postgres": "cf05d378f282d0abe941a82f", +"postgresql": "cf05d378f282d0abe941a82f", +"snowflake": "cf05d378f282d0abe941a82f", +"tsql": "cf05d378f282d0abe941a82f" +} +], +[ +"type", +{ +"DuckDB": "5abf4ec799a2ec32fb10da7e", +"None": "4b356542044f1267fcfc487a", +"bigquery": "4b356542044f1267fcfc487a", +"databricks": "4b356542044f1267fcfc487a", +"duckdb": "5abf4ec799a2ec32fb10da7e", +"generic": "4b356542044f1267fcfc487a", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "4b356542044f1267fcfc487a", +"postgres": "4b356542044f1267fcfc487a", +"postgresql": "4b356542044f1267fcfc487a", +"snowflake": "4b356542044f1267fcfc487a", +"tsql": "4b356542044f1267fcfc487a" +} +], +[ +"type", +{ +"DuckDB": "d7b74701deb8b87c32deb7a6", +"None": "d7b74701deb8b87c32deb7a6", +"bigquery": "d7b74701deb8b87c32deb7a6", +"databricks": "d7b74701deb8b87c32deb7a6", +"duckdb": "d7b74701deb8b87c32deb7a6", +"generic": "d7b74701deb8b87c32deb7a6", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "d7b74701deb8b87c32deb7a6", +"postgres": "d7b74701deb8b87c32deb7a6", +"postgresql": "d7b74701deb8b87c32deb7a6", +"snowflake": "d7b74701deb8b87c32deb7a6", +"tsql": "d7b74701deb8b87c32deb7a6" +} +], +[ +"type", +{ +"DuckDB": "078c0e4b25cdb89eb4ebd88f", +"None": "078c0e4b25cdb89eb4ebd88f", +"bigquery": "5226d7e2a62c7650a87d6e84", +"databricks": "078c0e4b25cdb89eb4ebd88f", +"duckdb": "078c0e4b25cdb89eb4ebd88f", +"generic": "078c0e4b25cdb89eb4ebd88f", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "078c0e4b25cdb89eb4ebd88f", +"postgres": "078c0e4b25cdb89eb4ebd88f", +"postgresql": "078c0e4b25cdb89eb4ebd88f", +"snowflake": "6306b9e88f7b13dbb6a32c00", +"tsql": "078c0e4b25cdb89eb4ebd88f" +} +], +[ +"type", +{ +"DuckDB": "e46d4be44ab9e500e9190d26", +"None": "e46d4be44ab9e500e9190d26", +"bigquery": "e6ffdece2977be55da73b59a", +"databricks": "e46d4be44ab9e500e9190d26", +"duckdb": "e46d4be44ab9e500e9190d26", +"generic": "e46d4be44ab9e500e9190d26", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "e46d4be44ab9e500e9190d26", +"postgres": "e46d4be44ab9e500e9190d26", +"postgresql": "e46d4be44ab9e500e9190d26", +"snowflake": "e46d4be44ab9e500e9190d26", +"tsql": "e46d4be44ab9e500e9190d26" +} +], +[ +"type", +{ +"DuckDB": "dcd0570bcd1ca6e7cbe9b206", +"None": "dcd0570bcd1ca6e7cbe9b206", +"bigquery": "3b4c01f94cca3bf195a3fd00", +"databricks": "526d6b30a5f27d05c0a26aa0", +"duckdb": "dcd0570bcd1ca6e7cbe9b206", +"generic": "dcd0570bcd1ca6e7cbe9b206", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "a5a929e25b7d0dae21e9bb65", +"postgres": "dcd0570bcd1ca6e7cbe9b206", +"postgresql": "dcd0570bcd1ca6e7cbe9b206", +"snowflake": "339dae99bd73c126e700c594", +"tsql": "dcd0570bcd1ca6e7cbe9b206" +} +], +[ +"type", +{ +"DuckDB": "00402a032fb29ce84ecc4615", +"None": "00402a032fb29ce84ecc4615", +"bigquery": "00402a032fb29ce84ecc4615", +"databricks": "00402a032fb29ce84ecc4615", +"duckdb": "00402a032fb29ce84ecc4615", +"generic": "00402a032fb29ce84ecc4615", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "00402a032fb29ce84ecc4615", +"postgres": "00402a032fb29ce84ecc4615", +"postgresql": "00402a032fb29ce84ecc4615", +"snowflake": "00402a032fb29ce84ecc4615", +"tsql": "00402a032fb29ce84ecc4615" +} +], +[ +"type", +{ +"DuckDB": "52921fa22fa8a5b698ef368f", +"None": "52921fa22fa8a5b698ef368f", +"bigquery": "52921fa22fa8a5b698ef368f", +"databricks": "52921fa22fa8a5b698ef368f", +"duckdb": "52921fa22fa8a5b698ef368f", +"generic": "52921fa22fa8a5b698ef368f", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "52921fa22fa8a5b698ef368f", +"postgres": "52921fa22fa8a5b698ef368f", +"postgresql": "52921fa22fa8a5b698ef368f", +"snowflake": "52921fa22fa8a5b698ef368f", +"tsql": "52921fa22fa8a5b698ef368f" +} +], +[ +"type", +{ +"DuckDB": "4114b18e7e26d16613331fa7", +"None": "4114b18e7e26d16613331fa7", +"bigquery": "4114b18e7e26d16613331fa7", +"databricks": "4fb572024031cb7631777be1", +"duckdb": "4114b18e7e26d16613331fa7", +"generic": "4114b18e7e26d16613331fa7", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "4114b18e7e26d16613331fa7", +"postgres": "4114b18e7e26d16613331fa7", +"postgresql": "4114b18e7e26d16613331fa7", +"snowflake": "4114b18e7e26d16613331fa7", +"tsql": "4114b18e7e26d16613331fa7" +} +], +[ +"type", +{ +"DuckDB": "6226bc03436ecf8fccd39252", +"None": "5aa51d84ac5e6c7a9306f348", +"bigquery": "5aa51d84ac5e6c7a9306f348", +"databricks": "5aa51d84ac5e6c7a9306f348", +"duckdb": "6226bc03436ecf8fccd39252", +"generic": "5aa51d84ac5e6c7a9306f348", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "5aa51d84ac5e6c7a9306f348", +"postgres": "5aa51d84ac5e6c7a9306f348", +"postgresql": "5aa51d84ac5e6c7a9306f348", +"snowflake": "5aa51d84ac5e6c7a9306f348", +"tsql": "5aa51d84ac5e6c7a9306f348" +} +], +[ +"type", +{ +"DuckDB": "630c8b82ec44c7208a6df405", +"None": "fa5c71c0d2354f76510bf3e7", +"bigquery": "58f6dfd7cabdc84b33dc2a96", +"databricks": "58f6dfd7cabdc84b33dc2a96", +"duckdb": "630c8b82ec44c7208a6df405", +"generic": "fa5c71c0d2354f76510bf3e7", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "58f6dfd7cabdc84b33dc2a96", +"postgres": "630c8b82ec44c7208a6df405", +"postgresql": "630c8b82ec44c7208a6df405", +"snowflake": "8efe0c6c8c4444b8fe68129b", +"tsql": "58f6dfd7cabdc84b33dc2a96" +} +], +[ +"type", +{ +"DuckDB": "aab0389e2b5470136660bf8a", +"None": "aab0389e2b5470136660bf8a", +"bigquery": "c9b810639795a7bfab91b98d", +"databricks": "aab0389e2b5470136660bf8a", +"duckdb": "aab0389e2b5470136660bf8a", +"generic": "aab0389e2b5470136660bf8a", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "aab0389e2b5470136660bf8a", +"postgres": "aab0389e2b5470136660bf8a", +"postgresql": "aab0389e2b5470136660bf8a", +"snowflake": "97a20344d811fb77c7690863", +"tsql": "aab0389e2b5470136660bf8a" +} +], +[ +"type", +{ +"DuckDB": "1eb7fb4e8cf75773c5573562", +"None": "1eb7fb4e8cf75773c5573562", +"bigquery": "c9b810639795a7bfab91b98d", +"databricks": "1eb7fb4e8cf75773c5573562", +"duckdb": "1eb7fb4e8cf75773c5573562", +"generic": "1eb7fb4e8cf75773c5573562", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "1eb7fb4e8cf75773c5573562", +"postgres": "1eb7fb4e8cf75773c5573562", +"postgresql": "1eb7fb4e8cf75773c5573562", +"snowflake": "97a20344d811fb77c7690863", +"tsql": "1eb7fb4e8cf75773c5573562" +} +], +[ +"type", +{ +"DuckDB": "dbd808c57538b7d212ed9a7c", +"None": "dbd808c57538b7d212ed9a7c", +"bigquery": "dbd808c57538b7d212ed9a7c", +"databricks": "dbd808c57538b7d212ed9a7c", +"duckdb": "dbd808c57538b7d212ed9a7c", +"generic": "dbd808c57538b7d212ed9a7c", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "dbd808c57538b7d212ed9a7c", +"postgres": "dbd808c57538b7d212ed9a7c", +"postgresql": "dbd808c57538b7d212ed9a7c", +"snowflake": "dbd808c57538b7d212ed9a7c", +"tsql": "dbd808c57538b7d212ed9a7c" +} +], +[ +"type", +{ +"DuckDB": "ebc821a95b9286e22c2b26d0", +"None": "ebc821a95b9286e22c2b26d0", +"bigquery": "19a1a80ffc06169f32694de8", +"databricks": "ebc821a95b9286e22c2b26d0", +"duckdb": "ebc821a95b9286e22c2b26d0", +"generic": "ebc821a95b9286e22c2b26d0", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "ebc821a95b9286e22c2b26d0", +"postgres": "ebc821a95b9286e22c2b26d0", +"postgresql": "ebc821a95b9286e22c2b26d0", +"snowflake": "ebc821a95b9286e22c2b26d0", +"tsql": "ebc821a95b9286e22c2b26d0" +} +], +[ +"type", +{ +"DuckDB": "79278352c17c9de0f5a28af5", +"None": "79278352c17c9de0f5a28af5", +"bigquery": "c9b810639795a7bfab91b98d", +"databricks": "79278352c17c9de0f5a28af5", +"duckdb": "79278352c17c9de0f5a28af5", +"generic": "79278352c17c9de0f5a28af5", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "79278352c17c9de0f5a28af5", +"postgres": "79278352c17c9de0f5a28af5", +"postgresql": "79278352c17c9de0f5a28af5", +"snowflake": "97a20344d811fb77c7690863", +"tsql": "79278352c17c9de0f5a28af5" +} +], +[ +"type", +{ +"DuckDB": "bbc7d9037d6f0383eb14d7eb", +"None": "bbc7d9037d6f0383eb14d7eb", +"bigquery": "bbc7d9037d6f0383eb14d7eb", +"databricks": "bbc7d9037d6f0383eb14d7eb", +"duckdb": "bbc7d9037d6f0383eb14d7eb", +"generic": "bbc7d9037d6f0383eb14d7eb", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "bbc7d9037d6f0383eb14d7eb", +"postgres": "bbc7d9037d6f0383eb14d7eb", +"postgresql": "bbc7d9037d6f0383eb14d7eb", +"snowflake": "bbc7d9037d6f0383eb14d7eb", +"tsql": "bbc7d9037d6f0383eb14d7eb" +} +], +[ +"type", +{ +"DuckDB": "38b2ec94bf02be40007ce525", +"None": "38b2ec94bf02be40007ce525", +"bigquery": "38b2ec94bf02be40007ce525", +"databricks": "38b2ec94bf02be40007ce525", +"duckdb": "38b2ec94bf02be40007ce525", +"generic": "38b2ec94bf02be40007ce525", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "38b2ec94bf02be40007ce525", +"postgres": "38b2ec94bf02be40007ce525", +"postgresql": "38b2ec94bf02be40007ce525", +"snowflake": "38b2ec94bf02be40007ce525", +"tsql": "38b2ec94bf02be40007ce525" +} +], +[ +"type", +{ +"DuckDB": "cb06a5553de70a4924ed6600", +"None": "cb06a5553de70a4924ed6600", +"bigquery": "cb06a5553de70a4924ed6600", +"databricks": "cb06a5553de70a4924ed6600", +"duckdb": "cb06a5553de70a4924ed6600", +"generic": "cb06a5553de70a4924ed6600", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "cb06a5553de70a4924ed6600", +"postgres": "cb06a5553de70a4924ed6600", +"postgresql": "cb06a5553de70a4924ed6600", +"snowflake": "cb06a5553de70a4924ed6600", +"tsql": "cb06a5553de70a4924ed6600" +} +], +[ +"type", +{ +"DuckDB": "38b2ec94bf02be40007ce525", +"None": "38b2ec94bf02be40007ce525", +"bigquery": "38b2ec94bf02be40007ce525", +"databricks": "38b2ec94bf02be40007ce525", +"duckdb": "38b2ec94bf02be40007ce525", +"generic": "38b2ec94bf02be40007ce525", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "38b2ec94bf02be40007ce525", +"postgres": "38b2ec94bf02be40007ce525", +"postgresql": "38b2ec94bf02be40007ce525", +"snowflake": "38b2ec94bf02be40007ce525", +"tsql": "38b2ec94bf02be40007ce525" +} +], +[ +"type", +{ +"DuckDB": "7cd31289a5b99b5a5e24492d", +"None": "7cd31289a5b99b5a5e24492d", +"bigquery": "7cd31289a5b99b5a5e24492d", +"databricks": "7cd31289a5b99b5a5e24492d", +"duckdb": "7cd31289a5b99b5a5e24492d", +"generic": "7cd31289a5b99b5a5e24492d", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "7cd31289a5b99b5a5e24492d", +"postgres": "7cd31289a5b99b5a5e24492d", +"postgresql": "7cd31289a5b99b5a5e24492d", +"snowflake": "7cd31289a5b99b5a5e24492d", +"tsql": "7cd31289a5b99b5a5e24492d" +} +], +[ +"type", +{ +"DuckDB": "1eb7826ddab37fc01598a8e9", +"None": "4e7908098c87141abb62306c", +"bigquery": "4e7908098c87141abb62306c", +"databricks": "4e7908098c87141abb62306c", +"duckdb": "1eb7826ddab37fc01598a8e9", +"generic": "4e7908098c87141abb62306c", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "6c03a3450ea4742ee7396e3c", +"postgres": "8ca050e9a43027521099ab95", +"postgresql": "8ca050e9a43027521099ab95", +"snowflake": "92f647d5460e4e2e7e25fb6d", +"tsql": "e1389f24bc9993eea233a19e" +} +], +[ +"type", +{ +"DuckDB": "a0131c4099eb4915760bab4a", +"None": "a0131c4099eb4915760bab4a", +"bigquery": "a0131c4099eb4915760bab4a", +"databricks": "a0131c4099eb4915760bab4a", +"duckdb": "a0131c4099eb4915760bab4a", +"generic": "a0131c4099eb4915760bab4a", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "a0131c4099eb4915760bab4a", +"postgres": "a0131c4099eb4915760bab4a", +"postgresql": "a0131c4099eb4915760bab4a", +"snowflake": "a0131c4099eb4915760bab4a", +"tsql": "a0131c4099eb4915760bab4a" +} +], +[ +"type", +{ +"DuckDB": "787213ce6b6e210ded1d752c", +"None": "787213ce6b6e210ded1d752c", +"bigquery": "b1b23029bedaa16e2a6f8516", +"databricks": "787213ce6b6e210ded1d752c", +"duckdb": "787213ce6b6e210ded1d752c", +"generic": "787213ce6b6e210ded1d752c", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "787213ce6b6e210ded1d752c", +"postgres": "787213ce6b6e210ded1d752c", +"postgresql": "787213ce6b6e210ded1d752c", +"snowflake": "b561884132dbe7e42b719110", +"tsql": "787213ce6b6e210ded1d752c" +} +], +[ +"type", +{ +"DuckDB": "5abf4ec799a2ec32fb10da7e", +"None": "de89632e277dbc8c97115419", +"bigquery": "de89632e277dbc8c97115419", +"databricks": "de89632e277dbc8c97115419", +"duckdb": "5abf4ec799a2ec32fb10da7e", +"generic": "de89632e277dbc8c97115419", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "de89632e277dbc8c97115419", +"postgres": "de89632e277dbc8c97115419", +"postgresql": "de89632e277dbc8c97115419", +"snowflake": "4b356542044f1267fcfc487a", +"tsql": "de89632e277dbc8c97115419" +} +], +[ +"type", +{ +"DuckDB": "a428302e4848ffe877284c84", +"None": "a428302e4848ffe877284c84", +"bigquery": "a428302e4848ffe877284c84", +"databricks": "a428302e4848ffe877284c84", +"duckdb": "a428302e4848ffe877284c84", +"generic": "a428302e4848ffe877284c84", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "a428302e4848ffe877284c84", +"postgres": "a428302e4848ffe877284c84", +"postgresql": "a428302e4848ffe877284c84", +"snowflake": "652ff8b21f638eac8fdc46c5", +"tsql": "a428302e4848ffe877284c84" +} +], +[ +"type", +{ +"DuckDB": "1eb7fb4e8cf75773c5573562", +"None": "1eb7fb4e8cf75773c5573562", +"bigquery": "c9b810639795a7bfab91b98d", +"databricks": "1eb7fb4e8cf75773c5573562", +"duckdb": "1eb7fb4e8cf75773c5573562", +"generic": "1eb7fb4e8cf75773c5573562", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "1eb7fb4e8cf75773c5573562", +"postgres": "1eb7fb4e8cf75773c5573562", +"postgresql": "1eb7fb4e8cf75773c5573562", +"snowflake": "97a20344d811fb77c7690863", +"tsql": "1eb7fb4e8cf75773c5573562" +} +], +[ +"type", +{ +"DuckDB": "86b7927f577e56d61eb9f879", +"None": "86b7927f577e56d61eb9f879", +"bigquery": "86b7927f577e56d61eb9f879", +"databricks": "86b7927f577e56d61eb9f879", +"duckdb": "86b7927f577e56d61eb9f879", +"generic": "86b7927f577e56d61eb9f879", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "86b7927f577e56d61eb9f879", +"postgres": "86b7927f577e56d61eb9f879", +"postgresql": "86b7927f577e56d61eb9f879", +"snowflake": "86b7927f577e56d61eb9f879", +"tsql": "86b7927f577e56d61eb9f879" +} +], +[ +"type", +{ +"DuckDB": "c82815abe30b3d099903f838", +"None": "c82815abe30b3d099903f838", +"bigquery": "c82815abe30b3d099903f838", +"databricks": "c82815abe30b3d099903f838", +"duckdb": "c82815abe30b3d099903f838", +"generic": "c82815abe30b3d099903f838", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "c82815abe30b3d099903f838", +"postgres": "c82815abe30b3d099903f838", +"postgresql": "c82815abe30b3d099903f838", +"snowflake": "c82815abe30b3d099903f838", +"tsql": "07ca53fdc57a22a78ad75787" +} +], +[ +"type", +{ +"DuckDB": "7d23077fb72f7bac9a49a632", +"None": "7d23077fb72f7bac9a49a632", +"bigquery": "7d23077fb72f7bac9a49a632", +"databricks": "7d23077fb72f7bac9a49a632", +"duckdb": "7d23077fb72f7bac9a49a632", +"generic": "7d23077fb72f7bac9a49a632", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "7d23077fb72f7bac9a49a632", +"postgres": "7d23077fb72f7bac9a49a632", +"postgresql": "7d23077fb72f7bac9a49a632", +"snowflake": "7d23077fb72f7bac9a49a632", +"tsql": "7d23077fb72f7bac9a49a632" +} +], +[ +"type", +{ +"DuckDB": "177c462b3a0270e894c8111c", +"None": "177c462b3a0270e894c8111c", +"bigquery": "177c462b3a0270e894c8111c", +"databricks": "177c462b3a0270e894c8111c", +"duckdb": "177c462b3a0270e894c8111c", +"generic": "177c462b3a0270e894c8111c", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "177c462b3a0270e894c8111c", +"postgres": "177c462b3a0270e894c8111c", +"postgresql": "177c462b3a0270e894c8111c", +"snowflake": "177c462b3a0270e894c8111c", +"tsql": "177c462b3a0270e894c8111c" +} +], +[ +"type", +{ +"DuckDB": "fe23594c781e79cbb0c8927a", +"None": "fe23594c781e79cbb0c8927a", +"bigquery": "fe23594c781e79cbb0c8927a", +"databricks": "fe23594c781e79cbb0c8927a", +"duckdb": "fe23594c781e79cbb0c8927a", +"generic": "fe23594c781e79cbb0c8927a", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "fe23594c781e79cbb0c8927a", +"postgres": "fe23594c781e79cbb0c8927a", +"postgresql": "fe23594c781e79cbb0c8927a", +"snowflake": "38b2ec94bf02be40007ce525", +"tsql": "fe23594c781e79cbb0c8927a" +} +], +[ +"type", +{ +"DuckDB": "08736485547ba339930697e9", +"None": "08736485547ba339930697e9", +"bigquery": "08736485547ba339930697e9", +"databricks": "08736485547ba339930697e9", +"duckdb": "08736485547ba339930697e9", +"generic": "08736485547ba339930697e9", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "08736485547ba339930697e9", +"postgres": "08736485547ba339930697e9", +"postgresql": "08736485547ba339930697e9", +"snowflake": "08736485547ba339930697e9", +"tsql": "08736485547ba339930697e9" +} +], +[ +"type", +{ +"DuckDB": "8d81e8dacd544a5e07c3b1ea", +"None": "8d81e8dacd544a5e07c3b1ea", +"bigquery": "8d81e8dacd544a5e07c3b1ea", +"databricks": "8d81e8dacd544a5e07c3b1ea", +"duckdb": "8d81e8dacd544a5e07c3b1ea", +"generic": "8d81e8dacd544a5e07c3b1ea", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "8d81e8dacd544a5e07c3b1ea", +"postgres": "8d81e8dacd544a5e07c3b1ea", +"postgresql": "8d81e8dacd544a5e07c3b1ea", +"snowflake": "8d81e8dacd544a5e07c3b1ea", +"tsql": "8d81e8dacd544a5e07c3b1ea" +} +], +[ +"type", +{ +"DuckDB": "2a0918be53051fe629d9ff8f", +"None": "2a0918be53051fe629d9ff8f", +"bigquery": "2a0918be53051fe629d9ff8f", +"databricks": "2a0918be53051fe629d9ff8f", +"duckdb": "2a0918be53051fe629d9ff8f", +"generic": "2a0918be53051fe629d9ff8f", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "2a0918be53051fe629d9ff8f", +"postgres": "2a0918be53051fe629d9ff8f", +"postgresql": "2a0918be53051fe629d9ff8f", +"snowflake": "3e611643f0beab4953c4e09b", +"tsql": "2a0918be53051fe629d9ff8f" +} +], +[ +"type", +{ +"DuckDB": "e2eee356d05f550b28bf85ad", +"None": "e2eee356d05f550b28bf85ad", +"bigquery": "e2eee356d05f550b28bf85ad", +"databricks": "e2eee356d05f550b28bf85ad", +"duckdb": "e2eee356d05f550b28bf85ad", +"generic": "e2eee356d05f550b28bf85ad", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "e2eee356d05f550b28bf85ad", +"postgres": "e2eee356d05f550b28bf85ad", +"postgresql": "e2eee356d05f550b28bf85ad", +"snowflake": "e2eee356d05f550b28bf85ad", +"tsql": "e2eee356d05f550b28bf85ad" +} +], +[ +"type", +{ +"DuckDB": "669084d1ea704ae5b8ee05c2", +"None": "669084d1ea704ae5b8ee05c2", +"bigquery": "669084d1ea704ae5b8ee05c2", +"databricks": "669084d1ea704ae5b8ee05c2", +"duckdb": "669084d1ea704ae5b8ee05c2", +"generic": "669084d1ea704ae5b8ee05c2", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "669084d1ea704ae5b8ee05c2", +"postgres": "669084d1ea704ae5b8ee05c2", +"postgresql": "669084d1ea704ae5b8ee05c2", +"snowflake": "669084d1ea704ae5b8ee05c2", +"tsql": "669084d1ea704ae5b8ee05c2" +} +], +[ +"type", +{ +"DuckDB": "3dbbe73ee4310c73030e8110", +"None": "3dbbe73ee4310c73030e8110", +"bigquery": "3dbbe73ee4310c73030e8110", +"databricks": "3dbbe73ee4310c73030e8110", +"duckdb": "3dbbe73ee4310c73030e8110", +"generic": "3dbbe73ee4310c73030e8110", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "3dbbe73ee4310c73030e8110", +"postgres": "3dbbe73ee4310c73030e8110", +"postgresql": "3dbbe73ee4310c73030e8110", +"snowflake": "f43dac38f34a1c0618a3f812", +"tsql": "3dbbe73ee4310c73030e8110" +} +], +[ +"type", +{ +"DuckDB": "1eb7fb4e8cf75773c5573562", +"None": "1eb7fb4e8cf75773c5573562", +"bigquery": "c9b810639795a7bfab91b98d", +"databricks": "1eb7fb4e8cf75773c5573562", +"duckdb": "1eb7fb4e8cf75773c5573562", +"generic": "1eb7fb4e8cf75773c5573562", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "1eb7fb4e8cf75773c5573562", +"postgres": "1eb7fb4e8cf75773c5573562", +"postgresql": "1eb7fb4e8cf75773c5573562", +"snowflake": "97a20344d811fb77c7690863", +"tsql": "1eb7fb4e8cf75773c5573562" +} +], +[ +"type", +{ +"DuckDB": "6ebf45a787a223241c8d9a47", +"None": "6ebf45a787a223241c8d9a47", +"bigquery": "6ebf45a787a223241c8d9a47", +"databricks": "6ebf45a787a223241c8d9a47", +"duckdb": "6ebf45a787a223241c8d9a47", +"generic": "6ebf45a787a223241c8d9a47", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "6ebf45a787a223241c8d9a47", +"postgres": "6ebf45a787a223241c8d9a47", +"postgresql": "6ebf45a787a223241c8d9a47", +"snowflake": "6ebf45a787a223241c8d9a47", +"tsql": "6ebf45a787a223241c8d9a47" +} +], +[ +"type", +{ +"DuckDB": "cd9c38fc2cf84c8551e29278", +"None": "cd9c38fc2cf84c8551e29278", +"bigquery": "cd9c38fc2cf84c8551e29278", +"databricks": "cd9c38fc2cf84c8551e29278", +"duckdb": "cd9c38fc2cf84c8551e29278", +"generic": "cd9c38fc2cf84c8551e29278", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "cd9c38fc2cf84c8551e29278", +"postgres": "cd9c38fc2cf84c8551e29278", +"postgresql": "cd9c38fc2cf84c8551e29278", +"snowflake": "cd9c38fc2cf84c8551e29278", +"tsql": "cd9c38fc2cf84c8551e29278" +} +], +[ +"type", +{ +"DuckDB": "e57ac1541fb51b362cd5b470", +"None": "e57ac1541fb51b362cd5b470", +"bigquery": "e57ac1541fb51b362cd5b470", +"databricks": "e57ac1541fb51b362cd5b470", +"duckdb": "e57ac1541fb51b362cd5b470", +"generic": "e57ac1541fb51b362cd5b470", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "e57ac1541fb51b362cd5b470", +"postgres": "e57ac1541fb51b362cd5b470", +"postgresql": "e57ac1541fb51b362cd5b470", +"snowflake": "4b356542044f1267fcfc487a", +"tsql": "e57ac1541fb51b362cd5b470" +} +], +[ +"type", +{ +"DuckDB": "944971a819b2498d3ecdc71d", +"None": "90882506184f4f707c46fdea", +"bigquery": "f1cb74b07e7c8c7243c9034b", +"databricks": "37decbb811ce5abeffb05b4e", +"duckdb": "944971a819b2498d3ecdc71d", +"generic": "90882506184f4f707c46fdea", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "90882506184f4f707c46fdea", +"postgres": "61f2d73857de8729b66f99d2", +"postgresql": "61f2d73857de8729b66f99d2", +"snowflake": "225fc4f7b28377ba911e4a47", +"tsql": "5fb4ec49639b38cdf3ccfc38" +} +], +[ +"type", +{ +"DuckDB": "dbf9ebbc7016f5ac5df2817e", +"None": "dbf9ebbc7016f5ac5df2817e", +"bigquery": "dbf9ebbc7016f5ac5df2817e", +"databricks": "dbf9ebbc7016f5ac5df2817e", +"duckdb": "dbf9ebbc7016f5ac5df2817e", +"generic": "dbf9ebbc7016f5ac5df2817e", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "dbf9ebbc7016f5ac5df2817e", +"postgres": "dbf9ebbc7016f5ac5df2817e", +"postgresql": "dbf9ebbc7016f5ac5df2817e", +"snowflake": "dbf9ebbc7016f5ac5df2817e", +"tsql": "dbf9ebbc7016f5ac5df2817e" +} +], +[ +"type", +{ +"DuckDB": "5debd5336e9bc9ec70e731b7", +"None": "5debd5336e9bc9ec70e731b7", +"bigquery": "5debd5336e9bc9ec70e731b7", +"databricks": "5debd5336e9bc9ec70e731b7", +"duckdb": "5debd5336e9bc9ec70e731b7", +"generic": "5debd5336e9bc9ec70e731b7", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "5debd5336e9bc9ec70e731b7", +"postgres": "5debd5336e9bc9ec70e731b7", +"postgresql": "5debd5336e9bc9ec70e731b7", +"snowflake": "5debd5336e9bc9ec70e731b7", +"tsql": "5debd5336e9bc9ec70e731b7" +} +], +[ +"type", +{ +"DuckDB": "d2c97d221599d038d9875873", +"None": "d2c97d221599d038d9875873", +"bigquery": "d2c97d221599d038d9875873", +"databricks": "d2c97d221599d038d9875873", +"duckdb": "d2c97d221599d038d9875873", +"generic": "d2c97d221599d038d9875873", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "d2c97d221599d038d9875873", +"postgres": "d2c97d221599d038d9875873", +"postgresql": "d2c97d221599d038d9875873", +"snowflake": "d2c97d221599d038d9875873", +"tsql": "d2c97d221599d038d9875873" +} +], +[ +"type", +{ +"DuckDB": "1fdc0b9f28b115c175e88d46", +"None": "1fdc0b9f28b115c175e88d46", +"bigquery": "1fdc0b9f28b115c175e88d46", +"databricks": "1fdc0b9f28b115c175e88d46", +"duckdb": "1fdc0b9f28b115c175e88d46", +"generic": "1fdc0b9f28b115c175e88d46", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "1fdc0b9f28b115c175e88d46", +"postgres": "1fdc0b9f28b115c175e88d46", +"postgresql": "1fdc0b9f28b115c175e88d46", +"snowflake": "1fdc0b9f28b115c175e88d46", +"tsql": "1fdc0b9f28b115c175e88d46" +} +], +[ +"type", +{ +"DuckDB": "f38ef32a483f1c4f89ae309e", +"None": "f38ef32a483f1c4f89ae309e", +"bigquery": "a428302e4848ffe877284c84", +"databricks": "f38ef32a483f1c4f89ae309e", +"duckdb": "f38ef32a483f1c4f89ae309e", +"generic": "f38ef32a483f1c4f89ae309e", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "f38ef32a483f1c4f89ae309e", +"postgres": "f38ef32a483f1c4f89ae309e", +"postgresql": "f38ef32a483f1c4f89ae309e", +"snowflake": "652ff8b21f638eac8fdc46c5", +"tsql": "f38ef32a483f1c4f89ae309e" +} +], +[ +"type", +{ +"DuckDB": "5620e893a908c6743b863bf6", +"None": "5620e893a908c6743b863bf6", +"bigquery": "4281b54de06f589b3507035a", +"databricks": "4281b54de06f589b3507035a", +"duckdb": "5620e893a908c6743b863bf6", +"generic": "5620e893a908c6743b863bf6", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "4281b54de06f589b3507035a", +"postgres": "5620e893a908c6743b863bf6", +"postgresql": "5620e893a908c6743b863bf6", +"snowflake": "5620e893a908c6743b863bf6", +"tsql": "5620e893a908c6743b863bf6" +} +], +[ +"type", +{ +"DuckDB": "c0d59e65280108f563dbb04b", +"None": "c0d59e65280108f563dbb04b", +"bigquery": "c0d59e65280108f563dbb04b", +"databricks": "c0d59e65280108f563dbb04b", +"duckdb": "c0d59e65280108f563dbb04b", +"generic": "c0d59e65280108f563dbb04b", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "c0d59e65280108f563dbb04b", +"postgres": "c0d59e65280108f563dbb04b", +"postgresql": "c0d59e65280108f563dbb04b", +"snowflake": "c0d59e65280108f563dbb04b", +"tsql": "c0d59e65280108f563dbb04b" +} +], +[ +"type", +{ +"DuckDB": "d16d75bc8832411932952499", +"None": "d16d75bc8832411932952499", +"bigquery": "d16d75bc8832411932952499", +"databricks": "d16d75bc8832411932952499", +"duckdb": "d16d75bc8832411932952499", +"generic": "d16d75bc8832411932952499", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "d16d75bc8832411932952499", +"postgres": "d16d75bc8832411932952499", +"postgresql": "d16d75bc8832411932952499", +"snowflake": "d16d75bc8832411932952499", +"tsql": "d16d75bc8832411932952499" +} +], +[ +"type", +{ +"DuckDB": "5abf4ec799a2ec32fb10da7e", +"None": "5abf4ec799a2ec32fb10da7e", +"bigquery": "5abf4ec799a2ec32fb10da7e", +"databricks": "5abf4ec799a2ec32fb10da7e", +"duckdb": "5abf4ec799a2ec32fb10da7e", +"generic": "5abf4ec799a2ec32fb10da7e", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "5abf4ec799a2ec32fb10da7e", +"postgres": "5abf4ec799a2ec32fb10da7e", +"postgresql": "5abf4ec799a2ec32fb10da7e", +"snowflake": "a5656d70e208254d1d3e9b4f", +"tsql": "5abf4ec799a2ec32fb10da7e" +} +], +[ +"type", +{ +"DuckDB": "6cffd1617edd6454241ee732", +"None": "6cffd1617edd6454241ee732", +"bigquery": "6cffd1617edd6454241ee732", +"databricks": "6cffd1617edd6454241ee732", +"duckdb": "6cffd1617edd6454241ee732", +"generic": "6cffd1617edd6454241ee732", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "6cffd1617edd6454241ee732", +"postgres": "6cffd1617edd6454241ee732", +"postgresql": "6cffd1617edd6454241ee732", +"snowflake": "6cffd1617edd6454241ee732", +"tsql": "6cffd1617edd6454241ee732" +} +], +[ +"type", +{ +"DuckDB": "a686bb6db17ab079cfc79224", +"None": "a686bb6db17ab079cfc79224", +"bigquery": "a686bb6db17ab079cfc79224", +"databricks": "a686bb6db17ab079cfc79224", +"duckdb": "a686bb6db17ab079cfc79224", +"generic": "a686bb6db17ab079cfc79224", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "a686bb6db17ab079cfc79224", +"postgres": "a686bb6db17ab079cfc79224", +"postgresql": "a686bb6db17ab079cfc79224", +"snowflake": "1096c3c8687c8e8eb538ff74", +"tsql": "a686bb6db17ab079cfc79224" +} +], +[ +"type", +{ +"DuckDB": "c752fd9fe2ad3b86b8b899da", +"None": "c752fd9fe2ad3b86b8b899da", +"bigquery": "c752fd9fe2ad3b86b8b899da", +"databricks": "c752fd9fe2ad3b86b8b899da", +"duckdb": "c752fd9fe2ad3b86b8b899da", +"generic": "c752fd9fe2ad3b86b8b899da", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "c752fd9fe2ad3b86b8b899da", +"postgres": "e998cd8f0f74af0526b75ff0", +"postgresql": "e998cd8f0f74af0526b75ff0", +"snowflake": "652ff8b21f638eac8fdc46c5", +"tsql": "c752fd9fe2ad3b86b8b899da" +} +], +[ +"type", +{ +"DuckDB": "b52d5a83269c4ad64bd3416e", +"None": "b52d5a83269c4ad64bd3416e", +"bigquery": "b52d5a83269c4ad64bd3416e", +"databricks": "b52d5a83269c4ad64bd3416e", +"duckdb": "b52d5a83269c4ad64bd3416e", +"generic": "b52d5a83269c4ad64bd3416e", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "b52d5a83269c4ad64bd3416e", +"postgres": "b52d5a83269c4ad64bd3416e", +"postgresql": "b52d5a83269c4ad64bd3416e", +"snowflake": "b52d5a83269c4ad64bd3416e", +"tsql": "b52d5a83269c4ad64bd3416e" +} +], +[ +"type", +{ +"DuckDB": "aff2599f42411f45ff949ed9", +"None": "be47a14e7523acb3fcbd4b5b", +"bigquery": "f98c7776673323299fbfe6b7", +"databricks": "2ed848a19b2b41fdf76d9a87", +"duckdb": "aff2599f42411f45ff949ed9", +"generic": "be47a14e7523acb3fcbd4b5b", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "6c03a3450ea4742ee7396e3c", +"postgres": "aff2599f42411f45ff949ed9", +"postgresql": "aff2599f42411f45ff949ed9", +"snowflake": "a2a30dfc031641a60ba584fa", +"tsql": "d1dc9a140dbe2eb1874c6ad7" +} +], +[ +"type", +{ +"DuckDB": "d9315b336b73c3d8d4b6e9a3", +"None": "f2ed52f6bf46b4db9343551c", +"bigquery": "f2ed52f6bf46b4db9343551c", +"databricks": "f2ed52f6bf46b4db9343551c", +"duckdb": "d9315b336b73c3d8d4b6e9a3", +"generic": "f2ed52f6bf46b4db9343551c", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "f2ed52f6bf46b4db9343551c", +"postgres": "f2ed52f6bf46b4db9343551c", +"postgresql": "f2ed52f6bf46b4db9343551c", +"snowflake": "f2ed52f6bf46b4db9343551c", +"tsql": "f2ed52f6bf46b4db9343551c" +} +], +[ +"type", +{ +"DuckDB": "de89632e277dbc8c97115419", +"None": "de89632e277dbc8c97115419", +"bigquery": "de89632e277dbc8c97115419", +"databricks": "de89632e277dbc8c97115419", +"duckdb": "de89632e277dbc8c97115419", +"generic": "de89632e277dbc8c97115419", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "de89632e277dbc8c97115419", +"postgres": "de89632e277dbc8c97115419", +"postgresql": "de89632e277dbc8c97115419", +"snowflake": "4b356542044f1267fcfc487a", +"tsql": "de89632e277dbc8c97115419" +} +], +[ +"type", +{ +"DuckDB": "88ee4a69672b4b9b3aa21e3d", +"None": "88ee4a69672b4b9b3aa21e3d", +"bigquery": "88ee4a69672b4b9b3aa21e3d", +"databricks": "88ee4a69672b4b9b3aa21e3d", +"duckdb": "88ee4a69672b4b9b3aa21e3d", +"generic": "88ee4a69672b4b9b3aa21e3d", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "88ee4a69672b4b9b3aa21e3d", +"postgres": "88ee4a69672b4b9b3aa21e3d", +"postgresql": "88ee4a69672b4b9b3aa21e3d", +"snowflake": "88ee4a69672b4b9b3aa21e3d", +"tsql": "88ee4a69672b4b9b3aa21e3d" +} +], +[ +"type", +{ +"DuckDB": "ab5ad6180652b3b00d1f5b01", +"None": "ab5ad6180652b3b00d1f5b01", +"bigquery": "946d5ee30ab7469c57d850df", +"databricks": "ab5ad6180652b3b00d1f5b01", +"duckdb": "ab5ad6180652b3b00d1f5b01", +"generic": "ab5ad6180652b3b00d1f5b01", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "ab5ad6180652b3b00d1f5b01", +"postgres": "ab5ad6180652b3b00d1f5b01", +"postgresql": "ab5ad6180652b3b00d1f5b01", +"snowflake": "226beccc1d430773f4e67b70", +"tsql": "ab5ad6180652b3b00d1f5b01" +} +], +[ +"type", +{ +"DuckDB": "555111267818cbd3d0b07105", +"None": "555111267818cbd3d0b07105", +"bigquery": "555111267818cbd3d0b07105", +"databricks": "555111267818cbd3d0b07105", +"duckdb": "555111267818cbd3d0b07105", +"generic": "555111267818cbd3d0b07105", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "555111267818cbd3d0b07105", +"postgres": "555111267818cbd3d0b07105", +"postgresql": "555111267818cbd3d0b07105", +"snowflake": "555111267818cbd3d0b07105", +"tsql": "555111267818cbd3d0b07105" +} +], +[ +"type", +{ +"DuckDB": "0ca1be8f7d61ca627e620450", +"None": "0ca1be8f7d61ca627e620450", +"bigquery": "e1c36a5cdd2427ff2b089ac9", +"databricks": "0ca1be8f7d61ca627e620450", +"duckdb": "0ca1be8f7d61ca627e620450", +"generic": "0ca1be8f7d61ca627e620450", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "0ca1be8f7d61ca627e620450", +"postgres": "0ca1be8f7d61ca627e620450", +"postgresql": "0ca1be8f7d61ca627e620450", +"snowflake": "18db5afe2c1e80d1ee652b54", +"tsql": "0ca1be8f7d61ca627e620450" +} +], +[ +"type", +{ +"DuckDB": "9aff7fcc7d550e1a8d105471", +"None": "9aff7fcc7d550e1a8d105471", +"bigquery": "f9bb9d0c419201aea072940b", +"databricks": "9aff7fcc7d550e1a8d105471", +"duckdb": "9aff7fcc7d550e1a8d105471", +"generic": "9aff7fcc7d550e1a8d105471", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "9aff7fcc7d550e1a8d105471", +"postgres": "9aff7fcc7d550e1a8d105471", +"postgresql": "9aff7fcc7d550e1a8d105471", +"snowflake": "9aff7fcc7d550e1a8d105471", +"tsql": "9aff7fcc7d550e1a8d105471" +} +], +[ +"type", +{ +"DuckDB": "e8b6e0bd2ded7b9eec6209e4", +"None": "e8b6e0bd2ded7b9eec6209e4", +"bigquery": "e8b6e0bd2ded7b9eec6209e4", +"databricks": "e8b6e0bd2ded7b9eec6209e4", +"duckdb": "e8b6e0bd2ded7b9eec6209e4", +"generic": "e8b6e0bd2ded7b9eec6209e4", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "e8b6e0bd2ded7b9eec6209e4", +"postgres": "e8b6e0bd2ded7b9eec6209e4", +"postgresql": "e8b6e0bd2ded7b9eec6209e4", +"snowflake": "e8b6e0bd2ded7b9eec6209e4", +"tsql": "e8b6e0bd2ded7b9eec6209e4" +} +], +[ +"type", +{ +"DuckDB": "e08a957777bd278f921ca0ee", +"None": "e08a957777bd278f921ca0ee", +"bigquery": "b1b23029bedaa16e2a6f8516", +"databricks": "e08a957777bd278f921ca0ee", +"duckdb": "e08a957777bd278f921ca0ee", +"generic": "e08a957777bd278f921ca0ee", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "e08a957777bd278f921ca0ee", +"postgres": "e08a957777bd278f921ca0ee", +"postgresql": "e08a957777bd278f921ca0ee", +"snowflake": "e08a957777bd278f921ca0ee", +"tsql": "e08a957777bd278f921ca0ee" +} +], +[ +"type", +{ +"DuckDB": "da72f481881cd577b304e9e7", +"None": "da72f481881cd577b304e9e7", +"bigquery": "da72f481881cd577b304e9e7", +"databricks": "da72f481881cd577b304e9e7", +"duckdb": "da72f481881cd577b304e9e7", +"generic": "da72f481881cd577b304e9e7", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "da72f481881cd577b304e9e7", +"postgres": "da72f481881cd577b304e9e7", +"postgresql": "da72f481881cd577b304e9e7", +"snowflake": "da72f481881cd577b304e9e7", +"tsql": "da72f481881cd577b304e9e7" +} +], +[ +"type", +{ +"DuckDB": "b0791eeb8731828818f87f78", +"None": "b0791eeb8731828818f87f78", +"bigquery": "b0791eeb8731828818f87f78", +"databricks": "b0791eeb8731828818f87f78", +"duckdb": "b0791eeb8731828818f87f78", +"generic": "b0791eeb8731828818f87f78", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "b0791eeb8731828818f87f78", +"postgres": "b0791eeb8731828818f87f78", +"postgresql": "b0791eeb8731828818f87f78", +"snowflake": "b0791eeb8731828818f87f78", +"tsql": "b0791eeb8731828818f87f78" +} +], +[ +"type", +{ +"DuckDB": "d4b3585f1e47f5f60a2c28ee", +"None": "d4b3585f1e47f5f60a2c28ee", +"bigquery": "d4b3585f1e47f5f60a2c28ee", +"databricks": "d4b3585f1e47f5f60a2c28ee", +"duckdb": "d4b3585f1e47f5f60a2c28ee", +"generic": "d4b3585f1e47f5f60a2c28ee", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "d4b3585f1e47f5f60a2c28ee", +"postgres": "d4b3585f1e47f5f60a2c28ee", +"postgresql": "d4b3585f1e47f5f60a2c28ee", +"snowflake": "d4b3585f1e47f5f60a2c28ee", +"tsql": "d4b3585f1e47f5f60a2c28ee" +} +], +[ +"type", +{ +"DuckDB": "62368fc15cefd5807807b209", +"None": "62368fc15cefd5807807b209", +"bigquery": "e6ffdece2977be55da73b59a", +"databricks": "62368fc15cefd5807807b209", +"duckdb": "62368fc15cefd5807807b209", +"generic": "62368fc15cefd5807807b209", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "62368fc15cefd5807807b209", +"postgres": "62368fc15cefd5807807b209", +"postgresql": "62368fc15cefd5807807b209", +"snowflake": "62368fc15cefd5807807b209", +"tsql": "62368fc15cefd5807807b209" +} +], +[ +"type", +{ +"DuckDB": "4b356542044f1267fcfc487a", +"None": "4b356542044f1267fcfc487a", +"bigquery": "4b356542044f1267fcfc487a", +"databricks": "4b356542044f1267fcfc487a", +"duckdb": "4b356542044f1267fcfc487a", +"generic": "4b356542044f1267fcfc487a", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "4b356542044f1267fcfc487a", +"postgres": "4b356542044f1267fcfc487a", +"postgresql": "4b356542044f1267fcfc487a", +"snowflake": "4b356542044f1267fcfc487a", +"tsql": "4b356542044f1267fcfc487a" +} +], +[ +"type", +{ +"DuckDB": "5abf4ec799a2ec32fb10da7e", +"None": "5abf4ec799a2ec32fb10da7e", +"bigquery": "5abf4ec799a2ec32fb10da7e", +"databricks": "5abf4ec799a2ec32fb10da7e", +"duckdb": "5abf4ec799a2ec32fb10da7e", +"generic": "5abf4ec799a2ec32fb10da7e", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "5abf4ec799a2ec32fb10da7e", +"postgres": "5abf4ec799a2ec32fb10da7e", +"postgresql": "5abf4ec799a2ec32fb10da7e", +"snowflake": "a5656d70e208254d1d3e9b4f", +"tsql": "5abf4ec799a2ec32fb10da7e" +} +], +[ +"type", +{ +"DuckDB": "7ca149227eff68da5bfa0404", +"None": "7ca149227eff68da5bfa0404", +"bigquery": "7ca149227eff68da5bfa0404", +"databricks": "7ca149227eff68da5bfa0404", +"duckdb": "7ca149227eff68da5bfa0404", +"generic": "7ca149227eff68da5bfa0404", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "7ca149227eff68da5bfa0404", +"postgres": "7ca149227eff68da5bfa0404", +"postgresql": "7ca149227eff68da5bfa0404", +"snowflake": "7ca149227eff68da5bfa0404", +"tsql": "7ca149227eff68da5bfa0404" +} +], +[ +"type", +{ +"DuckDB": "3dbbe73ee4310c73030e8110", +"None": "3dbbe73ee4310c73030e8110", +"bigquery": "3dbbe73ee4310c73030e8110", +"databricks": "3dbbe73ee4310c73030e8110", +"duckdb": "3dbbe73ee4310c73030e8110", +"generic": "3dbbe73ee4310c73030e8110", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "3dbbe73ee4310c73030e8110", +"postgres": "3dbbe73ee4310c73030e8110", +"postgresql": "3dbbe73ee4310c73030e8110", +"snowflake": "f43dac38f34a1c0618a3f812", +"tsql": "3dbbe73ee4310c73030e8110" +} +], +[ +"type", +{ +"DuckDB": "19cc45192479751e55bffbfe", +"None": "19cc45192479751e55bffbfe", +"bigquery": "19cc45192479751e55bffbfe", +"databricks": "19cc45192479751e55bffbfe", +"duckdb": "19cc45192479751e55bffbfe", +"generic": "19cc45192479751e55bffbfe", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "19cc45192479751e55bffbfe", +"postgres": "19cc45192479751e55bffbfe", +"postgresql": "19cc45192479751e55bffbfe", +"snowflake": "19cc45192479751e55bffbfe", +"tsql": "19cc45192479751e55bffbfe" +} +], +[ +"type", +{ +"DuckDB": "300e2b67af892b463d85f9cd", +"None": "300e2b67af892b463d85f9cd", +"bigquery": "300e2b67af892b463d85f9cd", +"databricks": "300e2b67af892b463d85f9cd", +"duckdb": "300e2b67af892b463d85f9cd", +"generic": "300e2b67af892b463d85f9cd", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "300e2b67af892b463d85f9cd", +"postgres": "300e2b67af892b463d85f9cd", +"postgresql": "300e2b67af892b463d85f9cd", +"snowflake": "300e2b67af892b463d85f9cd", +"tsql": "300e2b67af892b463d85f9cd" +} +], +[ +"type", +{ +"DuckDB": "19bdd92ea0cc5fb028657510", +"None": "1e75e5227bea0ae294ac7af1", +"bigquery": "1e75e5227bea0ae294ac7af1", +"databricks": "1e75e5227bea0ae294ac7af1", +"duckdb": "19bdd92ea0cc5fb028657510", +"generic": "1e75e5227bea0ae294ac7af1", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "19bdd92ea0cc5fb028657510", +"postgres": "19bdd92ea0cc5fb028657510", +"postgresql": "19bdd92ea0cc5fb028657510", +"snowflake": "8ff614b7306c0edbe36ce00b", +"tsql": "901e8c830028411846541f65" +} +], +[ +"type", +{ +"DuckDB": "94f6df33eccb97170eccb01b", +"None": "94f6df33eccb97170eccb01b", +"bigquery": "94f6df33eccb97170eccb01b", +"databricks": "94f6df33eccb97170eccb01b", +"duckdb": "94f6df33eccb97170eccb01b", +"generic": "94f6df33eccb97170eccb01b", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "94f6df33eccb97170eccb01b", +"postgres": "94f6df33eccb97170eccb01b", +"postgresql": "94f6df33eccb97170eccb01b", +"snowflake": "94f6df33eccb97170eccb01b", +"tsql": "94f6df33eccb97170eccb01b" +} +], +[ +"type", +{ +"DuckDB": "19a1a80ffc06169f32694de8", +"None": "19a1a80ffc06169f32694de8", +"bigquery": "19a1a80ffc06169f32694de8", +"databricks": "19a1a80ffc06169f32694de8", +"duckdb": "19a1a80ffc06169f32694de8", +"generic": "19a1a80ffc06169f32694de8", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "19a1a80ffc06169f32694de8", +"postgres": "19a1a80ffc06169f32694de8", +"postgresql": "19a1a80ffc06169f32694de8", +"snowflake": "19a1a80ffc06169f32694de8", +"tsql": "19a1a80ffc06169f32694de8" +} +], +[ +"type", +{ +"DuckDB": "1eb7fb4e8cf75773c5573562", +"None": "1eb7fb4e8cf75773c5573562", +"bigquery": "c9b810639795a7bfab91b98d", +"databricks": "1eb7fb4e8cf75773c5573562", +"duckdb": "1eb7fb4e8cf75773c5573562", +"generic": "1eb7fb4e8cf75773c5573562", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "1eb7fb4e8cf75773c5573562", +"postgres": "1eb7fb4e8cf75773c5573562", +"postgresql": "1eb7fb4e8cf75773c5573562", +"snowflake": "97a20344d811fb77c7690863", +"tsql": "1eb7fb4e8cf75773c5573562" +} +], +[ +"type", +{ +"DuckDB": "de89632e277dbc8c97115419", +"None": "de89632e277dbc8c97115419", +"bigquery": "de89632e277dbc8c97115419", +"databricks": "de89632e277dbc8c97115419", +"duckdb": "de89632e277dbc8c97115419", +"generic": "de89632e277dbc8c97115419", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "de89632e277dbc8c97115419", +"postgres": "de89632e277dbc8c97115419", +"postgresql": "de89632e277dbc8c97115419", +"snowflake": "4b356542044f1267fcfc487a", +"tsql": "de89632e277dbc8c97115419" +} +], +[ +"type", +{ +"DuckDB": "2444c03418f9f1b2f23f2ec8", +"None": "2444c03418f9f1b2f23f2ec8", +"bigquery": "2444c03418f9f1b2f23f2ec8", +"databricks": "2444c03418f9f1b2f23f2ec8", +"duckdb": "2444c03418f9f1b2f23f2ec8", +"generic": "2444c03418f9f1b2f23f2ec8", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "2444c03418f9f1b2f23f2ec8", +"postgres": "2444c03418f9f1b2f23f2ec8", +"postgresql": "2444c03418f9f1b2f23f2ec8", +"snowflake": "2444c03418f9f1b2f23f2ec8", +"tsql": "2444c03418f9f1b2f23f2ec8" +} +], +[ +"type", +{ +"DuckDB": "f7fca17b74cc50ae3de8c826", +"None": "d2c97d221599d038d9875873", +"bigquery": "d2c97d221599d038d9875873", +"databricks": "d2c97d221599d038d9875873", +"duckdb": "f7fca17b74cc50ae3de8c826", +"generic": "d2c97d221599d038d9875873", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "d2c97d221599d038d9875873", +"postgres": "d2c97d221599d038d9875873", +"postgresql": "d2c97d221599d038d9875873", +"snowflake": "d2c97d221599d038d9875873", +"tsql": "d2c97d221599d038d9875873" +} +], +[ +"type", +{ +"DuckDB": "fe23594c781e79cbb0c8927a", +"None": "fe23594c781e79cbb0c8927a", +"bigquery": "fe23594c781e79cbb0c8927a", +"databricks": "fe23594c781e79cbb0c8927a", +"duckdb": "fe23594c781e79cbb0c8927a", +"generic": "fe23594c781e79cbb0c8927a", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "fe23594c781e79cbb0c8927a", +"postgres": "fe23594c781e79cbb0c8927a", +"postgresql": "fe23594c781e79cbb0c8927a", +"snowflake": "38b2ec94bf02be40007ce525", +"tsql": "fe23594c781e79cbb0c8927a" +} +], +[ +"type", +{ +"DuckDB": "787213ce6b6e210ded1d752c", +"None": "787213ce6b6e210ded1d752c", +"bigquery": "b1b23029bedaa16e2a6f8516", +"databricks": "787213ce6b6e210ded1d752c", +"duckdb": "787213ce6b6e210ded1d752c", +"generic": "787213ce6b6e210ded1d752c", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "787213ce6b6e210ded1d752c", +"postgres": "787213ce6b6e210ded1d752c", +"postgresql": "787213ce6b6e210ded1d752c", +"snowflake": "b561884132dbe7e42b719110", +"tsql": "787213ce6b6e210ded1d752c" +} +], +[ +"type", +{ +"DuckDB": "63c80b5d8e861216f0c45bfd", +"None": "f8219c960720043f0662a603", +"bigquery": "f8219c960720043f0662a603", +"databricks": "f8219c960720043f0662a603", +"duckdb": "63c80b5d8e861216f0c45bfd", +"generic": "f8219c960720043f0662a603", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "f8219c960720043f0662a603", +"postgres": "f8219c960720043f0662a603", +"postgresql": "f8219c960720043f0662a603", +"snowflake": "f8219c960720043f0662a603", +"tsql": "f8219c960720043f0662a603" +} +], +[ +"type", +{ +"DuckDB": "396b2ce32efb5365b393c230", +"None": "e57ac1541fb51b362cd5b470", +"bigquery": "e57ac1541fb51b362cd5b470", +"databricks": "e57ac1541fb51b362cd5b470", +"duckdb": "396b2ce32efb5365b393c230", +"generic": "e57ac1541fb51b362cd5b470", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "e57ac1541fb51b362cd5b470", +"postgres": "e57ac1541fb51b362cd5b470", +"postgresql": "e57ac1541fb51b362cd5b470", +"snowflake": "4b356542044f1267fcfc487a", +"tsql": "e57ac1541fb51b362cd5b470" +} +], +[ +"type", +{ +"DuckDB": "f16105cbc61d547e6c08efc8", +"None": "f16105cbc61d547e6c08efc8", +"bigquery": "a428302e4848ffe877284c84", +"databricks": "f16105cbc61d547e6c08efc8", +"duckdb": "f16105cbc61d547e6c08efc8", +"generic": "f16105cbc61d547e6c08efc8", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "f16105cbc61d547e6c08efc8", +"postgres": "f16105cbc61d547e6c08efc8", +"postgresql": "f16105cbc61d547e6c08efc8", +"snowflake": "652ff8b21f638eac8fdc46c5", +"tsql": "f16105cbc61d547e6c08efc8" +} +], +[ +"type", +{ +"DuckDB": "f6140be64a327a15b42b923d", +"None": "f6140be64a327a15b42b923d", +"bigquery": "f6140be64a327a15b42b923d", +"databricks": "f6140be64a327a15b42b923d", +"duckdb": "f6140be64a327a15b42b923d", +"generic": "f6140be64a327a15b42b923d", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "f6140be64a327a15b42b923d", +"postgres": "f6140be64a327a15b42b923d", +"postgresql": "f6140be64a327a15b42b923d", +"snowflake": "f6140be64a327a15b42b923d", +"tsql": "f6140be64a327a15b42b923d" +} +], +[ +"type", +{ +"DuckDB": "d61c83ef8bfdf043fa672cb5", +"None": "d61c83ef8bfdf043fa672cb5", +"bigquery": "c9b810639795a7bfab91b98d", +"databricks": "d61c83ef8bfdf043fa672cb5", +"duckdb": "d61c83ef8bfdf043fa672cb5", +"generic": "d61c83ef8bfdf043fa672cb5", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "d61c83ef8bfdf043fa672cb5", +"postgres": "d61c83ef8bfdf043fa672cb5", +"postgresql": "d61c83ef8bfdf043fa672cb5", +"snowflake": "97a20344d811fb77c7690863", +"tsql": "d61c83ef8bfdf043fa672cb5" +} +], +[ +"type", +{ +"DuckDB": "25cdfa949946952336077d37", +"None": "25cdfa949946952336077d37", +"bigquery": "25cdfa949946952336077d37", +"databricks": "25cdfa949946952336077d37", +"duckdb": "25cdfa949946952336077d37", +"generic": "25cdfa949946952336077d37", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "25cdfa949946952336077d37", +"postgres": "25cdfa949946952336077d37", +"postgresql": "25cdfa949946952336077d37", +"snowflake": "25cdfa949946952336077d37", +"tsql": "25cdfa949946952336077d37" +} +], +[ +"type", +{ +"DuckDB": "6d7ab232e65fe8d85c7169ae", +"None": "6d7ab232e65fe8d85c7169ae", +"bigquery": "6f6198e2d2c8a8d6444ef5af", +"databricks": "6d7ab232e65fe8d85c7169ae", +"duckdb": "6d7ab232e65fe8d85c7169ae", +"generic": "6d7ab232e65fe8d85c7169ae", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "6d7ab232e65fe8d85c7169ae", +"postgres": "a6659d96bbfa5da75e69e22d", +"postgresql": "a6659d96bbfa5da75e69e22d", +"snowflake": "6d7ab232e65fe8d85c7169ae", +"tsql": "aed0419e7f2ce7c0a8892248" +} +], +[ +"type", +{ +"DuckDB": "13bc61bc9a039c8b798c5322", +"None": "1509a96170cb94e0a99bbf00", +"bigquery": "9193e8385b52630e5bac3baf", +"databricks": "1509a96170cb94e0a99bbf00", +"duckdb": "13bc61bc9a039c8b798c5322", +"generic": "1509a96170cb94e0a99bbf00", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "6c03a3450ea4742ee7396e3c", +"postgres": "13bc61bc9a039c8b798c5322", +"postgresql": "13bc61bc9a039c8b798c5322", +"snowflake": "d5cc04b4579263e52cd194bb", +"tsql": "29b39772c27728dfa6b9e0b2" +} +], +[ +"type", +{ +"DuckDB": "d6de1c22b8b95cc863db57ba", +"None": "d6de1c22b8b95cc863db57ba", +"bigquery": "d6de1c22b8b95cc863db57ba", +"databricks": "d6de1c22b8b95cc863db57ba", +"duckdb": "d6de1c22b8b95cc863db57ba", +"generic": "d6de1c22b8b95cc863db57ba", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "d6de1c22b8b95cc863db57ba", +"postgres": "d6de1c22b8b95cc863db57ba", +"postgresql": "d6de1c22b8b95cc863db57ba", +"snowflake": "d6de1c22b8b95cc863db57ba", +"tsql": "d6de1c22b8b95cc863db57ba" +} +], +[ +"type", +{ +"DuckDB": "2c6b371b030464f525066893", +"None": "2c6b371b030464f525066893", +"bigquery": "2c6b371b030464f525066893", +"databricks": "2c6b371b030464f525066893", +"duckdb": "2c6b371b030464f525066893", +"generic": "2c6b371b030464f525066893", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "2c6b371b030464f525066893", +"postgres": "2c6b371b030464f525066893", +"postgresql": "2c6b371b030464f525066893", +"snowflake": "2c6b371b030464f525066893", +"tsql": "2c6b371b030464f525066893" +} +], +[ +"type", +{ +"DuckDB": "35e216b6921bf843994f2eea", +"None": "46ec3e19e05a6cb29854ccac", +"bigquery": "46ec3e19e05a6cb29854ccac", +"databricks": "46ec3e19e05a6cb29854ccac", +"duckdb": "35e216b6921bf843994f2eea", +"generic": "46ec3e19e05a6cb29854ccac", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "46ec3e19e05a6cb29854ccac", +"postgres": "46ec3e19e05a6cb29854ccac", +"postgresql": "46ec3e19e05a6cb29854ccac", +"snowflake": "46ec3e19e05a6cb29854ccac", +"tsql": "46ec3e19e05a6cb29854ccac" +} +], +[ +"type", +{ +"DuckDB": "08736485547ba339930697e9", +"None": "08736485547ba339930697e9", +"bigquery": "08736485547ba339930697e9", +"databricks": "08736485547ba339930697e9", +"duckdb": "08736485547ba339930697e9", +"generic": "08736485547ba339930697e9", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "08736485547ba339930697e9", +"postgres": "08736485547ba339930697e9", +"postgresql": "08736485547ba339930697e9", +"snowflake": "08736485547ba339930697e9", +"tsql": "08736485547ba339930697e9" +} +], +[ +"type", +{ +"DuckDB": "2fcd11f2fdbe6c4498c4833e", +"None": "2fcd11f2fdbe6c4498c4833e", +"bigquery": "2fcd11f2fdbe6c4498c4833e", +"databricks": "2fcd11f2fdbe6c4498c4833e", +"duckdb": "2fcd11f2fdbe6c4498c4833e", +"generic": "2fcd11f2fdbe6c4498c4833e", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "2fcd11f2fdbe6c4498c4833e", +"postgres": "2fcd11f2fdbe6c4498c4833e", +"postgresql": "2fcd11f2fdbe6c4498c4833e", +"snowflake": "2fcd11f2fdbe6c4498c4833e", +"tsql": "2fcd11f2fdbe6c4498c4833e" +} +], +[ +"type", +{ +"DuckDB": "fe23594c781e79cbb0c8927a", +"None": "fe23594c781e79cbb0c8927a", +"bigquery": "fe23594c781e79cbb0c8927a", +"databricks": "fe23594c781e79cbb0c8927a", +"duckdb": "fe23594c781e79cbb0c8927a", +"generic": "fe23594c781e79cbb0c8927a", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "fe23594c781e79cbb0c8927a", +"postgres": "fe23594c781e79cbb0c8927a", +"postgresql": "fe23594c781e79cbb0c8927a", +"snowflake": "38b2ec94bf02be40007ce525", +"tsql": "fe23594c781e79cbb0c8927a" +} +], +[ +"type", +{ +"DuckDB": "8a3f094f18fb4047f0febf59", +"None": "c844c96e1e3ffc72d5f90df9", +"bigquery": "5c28019dce48a74708c90a76", +"databricks": "c844c96e1e3ffc72d5f90df9", +"duckdb": "8a3f094f18fb4047f0febf59", +"generic": "c844c96e1e3ffc72d5f90df9", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "28eb0d6de9724959ce5ba43e", +"postgres": "c844c96e1e3ffc72d5f90df9", +"postgresql": "c844c96e1e3ffc72d5f90df9", +"snowflake": "c844c96e1e3ffc72d5f90df9", +"tsql": "a4a176ec3c56e2704a650963" +} +], +[ +"type", +{ +"DuckDB": "5c28019dce48a74708c90a76", +"None": "5c28019dce48a74708c90a76", +"bigquery": "f28a96f0eb38ad8874f6ec5d", +"databricks": "5c28019dce48a74708c90a76", +"duckdb": "5c28019dce48a74708c90a76", +"generic": "5c28019dce48a74708c90a76", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "5c28019dce48a74708c90a76", +"postgres": "5c28019dce48a74708c90a76", +"postgresql": "5c28019dce48a74708c90a76", +"snowflake": "a5656d70e208254d1d3e9b4f", +"tsql": "2a7a7132adc795ca2bc39c37" +} +], +[ +"type", +{ +"DuckDB": "2fcd11f2fdbe6c4498c4833e", +"None": "2fcd11f2fdbe6c4498c4833e", +"bigquery": "2fcd11f2fdbe6c4498c4833e", +"databricks": "2fcd11f2fdbe6c4498c4833e", +"duckdb": "2fcd11f2fdbe6c4498c4833e", +"generic": "2fcd11f2fdbe6c4498c4833e", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "2fcd11f2fdbe6c4498c4833e", +"postgres": "2fcd11f2fdbe6c4498c4833e", +"postgresql": "2fcd11f2fdbe6c4498c4833e", +"snowflake": "2fcd11f2fdbe6c4498c4833e", +"tsql": "2fcd11f2fdbe6c4498c4833e" +} +], +[ +"type", +{ +"DuckDB": "aab0389e2b5470136660bf8a", +"None": "aab0389e2b5470136660bf8a", +"bigquery": "c9b810639795a7bfab91b98d", +"databricks": "aab0389e2b5470136660bf8a", +"duckdb": "aab0389e2b5470136660bf8a", +"generic": "aab0389e2b5470136660bf8a", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "aab0389e2b5470136660bf8a", +"postgres": "aab0389e2b5470136660bf8a", +"postgresql": "aab0389e2b5470136660bf8a", +"snowflake": "97a20344d811fb77c7690863", +"tsql": "aab0389e2b5470136660bf8a" +} +], +[ +"type", +{ +"DuckDB": "6f4372a332076048e56d5076", +"None": "6f4372a332076048e56d5076", +"bigquery": "74a30f6aa9def0b58afc616c", +"databricks": "6f4372a332076048e56d5076", +"duckdb": "6f4372a332076048e56d5076", +"generic": "6f4372a332076048e56d5076", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "6f4372a332076048e56d5076", +"postgres": "6f4372a332076048e56d5076", +"postgresql": "6f4372a332076048e56d5076", +"snowflake": "daeeb0f00b3ee4211b8da00f", +"tsql": "6f4372a332076048e56d5076" +} +], +[ +"type", +{ +"DuckDB": "7a00586f9fdb1d97256bfff8", +"None": "7a00586f9fdb1d97256bfff8", +"bigquery": "7a00586f9fdb1d97256bfff8", +"databricks": "7a00586f9fdb1d97256bfff8", +"duckdb": "7a00586f9fdb1d97256bfff8", +"generic": "7a00586f9fdb1d97256bfff8", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "7a00586f9fdb1d97256bfff8", +"postgres": "7a00586f9fdb1d97256bfff8", +"postgresql": "7a00586f9fdb1d97256bfff8", +"snowflake": "7a00586f9fdb1d97256bfff8", +"tsql": "7a00586f9fdb1d97256bfff8" +} +], +[ +"type", +{ +"DuckDB": "2bfa352725f9d8a91250f75e", +"None": "2bfa352725f9d8a91250f75e", +"bigquery": "2bfa352725f9d8a91250f75e", +"databricks": "2bfa352725f9d8a91250f75e", +"duckdb": "2bfa352725f9d8a91250f75e", +"generic": "2bfa352725f9d8a91250f75e", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "2bfa352725f9d8a91250f75e", +"postgres": "2bfa352725f9d8a91250f75e", +"postgresql": "2bfa352725f9d8a91250f75e", +"snowflake": "2bfa352725f9d8a91250f75e", +"tsql": "2bfa352725f9d8a91250f75e" +} +], +[ +"type", +{ +"DuckDB": "1eb7fb4e8cf75773c5573562", +"None": "1eb7fb4e8cf75773c5573562", +"bigquery": "c9b810639795a7bfab91b98d", +"databricks": "1eb7fb4e8cf75773c5573562", +"duckdb": "1eb7fb4e8cf75773c5573562", +"generic": "1eb7fb4e8cf75773c5573562", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "1eb7fb4e8cf75773c5573562", +"postgres": "1eb7fb4e8cf75773c5573562", +"postgresql": "1eb7fb4e8cf75773c5573562", +"snowflake": "97a20344d811fb77c7690863", +"tsql": "1eb7fb4e8cf75773c5573562" +} +], +[ +"type", +{ +"DuckDB": "2bfa352725f9d8a91250f75e", +"None": "2bfa352725f9d8a91250f75e", +"bigquery": "2bfa352725f9d8a91250f75e", +"databricks": "2bfa352725f9d8a91250f75e", +"duckdb": "2bfa352725f9d8a91250f75e", +"generic": "2bfa352725f9d8a91250f75e", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "2bfa352725f9d8a91250f75e", +"postgres": "2bfa352725f9d8a91250f75e", +"postgresql": "2bfa352725f9d8a91250f75e", +"snowflake": "2bfa352725f9d8a91250f75e", +"tsql": "2bfa352725f9d8a91250f75e" +} +], +[ +"type", +{ +"DuckDB": "aab0389e2b5470136660bf8a", +"None": "aab0389e2b5470136660bf8a", +"bigquery": "c9b810639795a7bfab91b98d", +"databricks": "aab0389e2b5470136660bf8a", +"duckdb": "aab0389e2b5470136660bf8a", +"generic": "aab0389e2b5470136660bf8a", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "aab0389e2b5470136660bf8a", +"postgres": "aab0389e2b5470136660bf8a", +"postgresql": "aab0389e2b5470136660bf8a", +"snowflake": "97a20344d811fb77c7690863", +"tsql": "aab0389e2b5470136660bf8a" +} +], +[ +"type", +{ +"DuckDB": "62368fc15cefd5807807b209", +"None": "62368fc15cefd5807807b209", +"bigquery": "e6ffdece2977be55da73b59a", +"databricks": "62368fc15cefd5807807b209", +"duckdb": "62368fc15cefd5807807b209", +"generic": "62368fc15cefd5807807b209", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "62368fc15cefd5807807b209", +"postgres": "62368fc15cefd5807807b209", +"postgresql": "62368fc15cefd5807807b209", +"snowflake": "62368fc15cefd5807807b209", +"tsql": "62368fc15cefd5807807b209" +} +], +[ +"type", +{ +"DuckDB": "38b2ec94bf02be40007ce525", +"None": "38b2ec94bf02be40007ce525", +"bigquery": "38b2ec94bf02be40007ce525", +"databricks": "38b2ec94bf02be40007ce525", +"duckdb": "38b2ec94bf02be40007ce525", +"generic": "38b2ec94bf02be40007ce525", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "38b2ec94bf02be40007ce525", +"postgres": "38b2ec94bf02be40007ce525", +"postgresql": "38b2ec94bf02be40007ce525", +"snowflake": "38b2ec94bf02be40007ce525", +"tsql": "38b2ec94bf02be40007ce525" +} +], +[ +"type", +{ +"DuckDB": "89cc3662f602a13aef39eb80", +"None": "f2bbf59a9c02f59ca89e66b6", +"bigquery": "f2bbf59a9c02f59ca89e66b6", +"databricks": "f2bbf59a9c02f59ca89e66b6", +"duckdb": "89cc3662f602a13aef39eb80", +"generic": "f2bbf59a9c02f59ca89e66b6", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "6c03a3450ea4742ee7396e3c", +"postgres": "89cc3662f602a13aef39eb80", +"postgresql": "89cc3662f602a13aef39eb80", +"snowflake": "6f88ef12d95c26bf8f0bd9e5", +"tsql": "d1dc9a140dbe2eb1874c6ad7" +} +], +[ +"type", +{ +"DuckDB": "0703bf71a54942bdaa28406e", +"None": "0703bf71a54942bdaa28406e", +"bigquery": "a428302e4848ffe877284c84", +"databricks": "0703bf71a54942bdaa28406e", +"duckdb": "0703bf71a54942bdaa28406e", +"generic": "0703bf71a54942bdaa28406e", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "0703bf71a54942bdaa28406e", +"postgres": "0703bf71a54942bdaa28406e", +"postgresql": "0703bf71a54942bdaa28406e", +"snowflake": "652ff8b21f638eac8fdc46c5", +"tsql": "441f377c46ddc162ec0a5976" +} +], +[ +"type", +{ +"DuckDB": "ef2689646fd9e772e27d2727", +"None": "ef2689646fd9e772e27d2727", +"bigquery": "ef2689646fd9e772e27d2727", +"databricks": "e63b3aab09c82955e2560928", +"duckdb": "ef2689646fd9e772e27d2727", +"generic": "ef2689646fd9e772e27d2727", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "6c03a3450ea4742ee7396e3c", +"postgres": "ef2689646fd9e772e27d2727", +"postgresql": "ef2689646fd9e772e27d2727", +"snowflake": "ef2689646fd9e772e27d2727", +"tsql": "ef2689646fd9e772e27d2727" +} +], +[ +"type", +{ +"DuckDB": "c43574432afc90bcba6944b2", +"None": "7040afbb3a088baf55e328b2", +"bigquery": "7040afbb3a088baf55e328b2", +"databricks": "ba611057434e43344935471b", +"duckdb": "c43574432afc90bcba6944b2", +"generic": "7040afbb3a088baf55e328b2", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "6c03a3450ea4742ee7396e3c", +"postgres": "1b3243409566f14d81c11fff", +"postgresql": "1b3243409566f14d81c11fff", +"snowflake": "5b6535982c7d4576e34ee7cb", +"tsql": "d1dc9a140dbe2eb1874c6ad7" +} +], +[ +"type", +{ +"DuckDB": "3dbbe73ee4310c73030e8110", +"None": "3dbbe73ee4310c73030e8110", +"bigquery": "3dbbe73ee4310c73030e8110", +"databricks": "3dbbe73ee4310c73030e8110", +"duckdb": "3dbbe73ee4310c73030e8110", +"generic": "3dbbe73ee4310c73030e8110", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "3dbbe73ee4310c73030e8110", +"postgres": "3dbbe73ee4310c73030e8110", +"postgresql": "3dbbe73ee4310c73030e8110", +"snowflake": "f43dac38f34a1c0618a3f812", +"tsql": "3dbbe73ee4310c73030e8110" +} +], +[ +"type", +{ +"DuckDB": "b46dfa976d5ba04f95bea32b", +"None": "b46dfa976d5ba04f95bea32b", +"bigquery": "68d2179839f17f0eb289d1aa", +"databricks": "b46dfa976d5ba04f95bea32b", +"duckdb": "b46dfa976d5ba04f95bea32b", +"generic": "b46dfa976d5ba04f95bea32b", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "b46dfa976d5ba04f95bea32b", +"postgres": "34dcdfe3e3afe6140e1353e0", +"postgresql": "34dcdfe3e3afe6140e1353e0", +"snowflake": "b46dfa976d5ba04f95bea32b", +"tsql": "1d8b945fd793ecdcacb90c21" +} +], +[ +"type", +{ +"DuckDB": "bc9875824f2c0eb90fcb5e51", +"None": "0289c868616e51dc348bba36", +"bigquery": "9255d53d9bcd9cb04141e55f", +"databricks": "031c4b14dc8b97fdb38e28b3", +"duckdb": "bc9875824f2c0eb90fcb5e51", +"generic": "0289c868616e51dc348bba36", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "fe2c1943dc029130eda3f066", +"postgres": "fe2c1943dc029130eda3f066", +"postgresql": "fe2c1943dc029130eda3f066", +"snowflake": "ffc35af553194c8ccffc9058", +"tsql": "fe2c1943dc029130eda3f066" +} +], +[ +"type", +{ +"DuckDB": "8a3f094f18fb4047f0febf59", +"None": "c844c96e1e3ffc72d5f90df9", +"bigquery": "5c28019dce48a74708c90a76", +"databricks": "c844c96e1e3ffc72d5f90df9", +"duckdb": "8a3f094f18fb4047f0febf59", +"generic": "c844c96e1e3ffc72d5f90df9", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "28eb0d6de9724959ce5ba43e", +"postgres": "c844c96e1e3ffc72d5f90df9", +"postgresql": "c844c96e1e3ffc72d5f90df9", +"snowflake": "c844c96e1e3ffc72d5f90df9", +"tsql": "a4a176ec3c56e2704a650963" +} +], +[ +"type", +{ +"DuckDB": "3dbbe73ee4310c73030e8110", +"None": "3dbbe73ee4310c73030e8110", +"bigquery": "3dbbe73ee4310c73030e8110", +"databricks": "3dbbe73ee4310c73030e8110", +"duckdb": "3dbbe73ee4310c73030e8110", +"generic": "3dbbe73ee4310c73030e8110", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "3dbbe73ee4310c73030e8110", +"postgres": "3dbbe73ee4310c73030e8110", +"postgresql": "3dbbe73ee4310c73030e8110", +"snowflake": "f43dac38f34a1c0618a3f812", +"tsql": "3dbbe73ee4310c73030e8110" +} +], +[ +"type", +{ +"DuckDB": "8f29d402cac8d3b922d1a4e7", +"None": "04d8552335eed867485d59b8", +"bigquery": "04d8552335eed867485d59b8", +"databricks": "04d8552335eed867485d59b8", +"duckdb": "8f29d402cac8d3b922d1a4e7", +"generic": "04d8552335eed867485d59b8", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "6c03a3450ea4742ee7396e3c", +"postgres": "8f29d402cac8d3b922d1a4e7", +"postgresql": "8f29d402cac8d3b922d1a4e7", +"snowflake": "c60d34b521887e82716fd787", +"tsql": "d1dc9a140dbe2eb1874c6ad7" +} +], +[ +"type", +{ +"DuckDB": "d53793d8f8d21c36a117dedb", +"None": "d53793d8f8d21c36a117dedb", +"bigquery": "d53793d8f8d21c36a117dedb", +"databricks": "d53793d8f8d21c36a117dedb", +"duckdb": "d53793d8f8d21c36a117dedb", +"generic": "d53793d8f8d21c36a117dedb", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "d53793d8f8d21c36a117dedb", +"postgres": "d53793d8f8d21c36a117dedb", +"postgresql": "d53793d8f8d21c36a117dedb", +"snowflake": "d53793d8f8d21c36a117dedb", +"tsql": "d53793d8f8d21c36a117dedb" +} +], +[ +"type", +{ +"DuckDB": "251aba3fef503ce64556c701", +"None": "251aba3fef503ce64556c701", +"bigquery": "c50a316d091c821866e4bfba", +"databricks": "251aba3fef503ce64556c701", +"duckdb": "251aba3fef503ce64556c701", +"generic": "251aba3fef503ce64556c701", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "251aba3fef503ce64556c701", +"postgres": "b7d6fc051a3c1ea6deb29ff4", +"postgresql": "b7d6fc051a3c1ea6deb29ff4", +"snowflake": "251aba3fef503ce64556c701", +"tsql": "e3bc1b8bad22d8104417b00f" +} +], +[ +"type", +{ +"DuckDB": "df19c722959a4259621a1e09", +"None": "df19c722959a4259621a1e09", +"bigquery": "df19c722959a4259621a1e09", +"databricks": "df19c722959a4259621a1e09", +"duckdb": "df19c722959a4259621a1e09", +"generic": "df19c722959a4259621a1e09", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "df19c722959a4259621a1e09", +"postgres": "df19c722959a4259621a1e09", +"postgresql": "df19c722959a4259621a1e09", +"snowflake": "df19c722959a4259621a1e09", +"tsql": "df19c722959a4259621a1e09" +} +], +[ +"type", +{ +"DuckDB": "2bfa352725f9d8a91250f75e", +"None": "2bfa352725f9d8a91250f75e", +"bigquery": "2bfa352725f9d8a91250f75e", +"databricks": "2bfa352725f9d8a91250f75e", +"duckdb": "2bfa352725f9d8a91250f75e", +"generic": "2bfa352725f9d8a91250f75e", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "2bfa352725f9d8a91250f75e", +"postgres": "2bfa352725f9d8a91250f75e", +"postgresql": "2bfa352725f9d8a91250f75e", +"snowflake": "2bfa352725f9d8a91250f75e", +"tsql": "2bfa352725f9d8a91250f75e" +} +], +[ +"type", +{ +"DuckDB": "4662a1758442ce44b830269f", +"None": "4662a1758442ce44b830269f", +"bigquery": "4662a1758442ce44b830269f", +"databricks": "4662a1758442ce44b830269f", +"duckdb": "4662a1758442ce44b830269f", +"generic": "4662a1758442ce44b830269f", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "4662a1758442ce44b830269f", +"postgres": "4662a1758442ce44b830269f", +"postgresql": "4662a1758442ce44b830269f", +"snowflake": "4662a1758442ce44b830269f", +"tsql": "4662a1758442ce44b830269f" +} +], +[ +"type", +{ +"DuckDB": "73975a560983dfcdc361f145", +"None": "73975a560983dfcdc361f145", +"bigquery": "73975a560983dfcdc361f145", +"databricks": "73975a560983dfcdc361f145", +"duckdb": "73975a560983dfcdc361f145", +"generic": "73975a560983dfcdc361f145", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "73975a560983dfcdc361f145", +"postgres": "73975a560983dfcdc361f145", +"postgresql": "73975a560983dfcdc361f145", +"snowflake": "73975a560983dfcdc361f145", +"tsql": "73975a560983dfcdc361f145" +} +], +[ +"type", +{ +"DuckDB": "8a3f094f18fb4047f0febf59", +"None": "c844c96e1e3ffc72d5f90df9", +"bigquery": "5c28019dce48a74708c90a76", +"databricks": "c844c96e1e3ffc72d5f90df9", +"duckdb": "8a3f094f18fb4047f0febf59", +"generic": "c844c96e1e3ffc72d5f90df9", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "28eb0d6de9724959ce5ba43e", +"postgres": "c844c96e1e3ffc72d5f90df9", +"postgresql": "c844c96e1e3ffc72d5f90df9", +"snowflake": "c844c96e1e3ffc72d5f90df9", +"tsql": "a4a176ec3c56e2704a650963" +} +], +[ +"type", +{ +"DuckDB": "fedd65248cdf63b24b8c1567", +"None": "fedd65248cdf63b24b8c1567", +"bigquery": "fedd65248cdf63b24b8c1567", +"databricks": "fedd65248cdf63b24b8c1567", +"duckdb": "fedd65248cdf63b24b8c1567", +"generic": "fedd65248cdf63b24b8c1567", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "fedd65248cdf63b24b8c1567", +"postgres": "fedd65248cdf63b24b8c1567", +"postgresql": "fedd65248cdf63b24b8c1567", +"snowflake": "fedd65248cdf63b24b8c1567", +"tsql": "fedd65248cdf63b24b8c1567" +} +], +[ +"type", +{ +"DuckDB": "c50a316d091c821866e4bfba", +"None": "c50a316d091c821866e4bfba", +"bigquery": "c50a316d091c821866e4bfba", +"databricks": "c50a316d091c821866e4bfba", +"duckdb": "c50a316d091c821866e4bfba", +"generic": "c50a316d091c821866e4bfba", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "c50a316d091c821866e4bfba", +"postgres": "c50a316d091c821866e4bfba", +"postgresql": "c50a316d091c821866e4bfba", +"snowflake": "c50a316d091c821866e4bfba", +"tsql": "c50a316d091c821866e4bfba" +} +], +[ +"type", +{ +"DuckDB": "d79c3ac70093cb4cb531e71c", +"None": "d79c3ac70093cb4cb531e71c", +"bigquery": "b0477b36767a62145aa9158c", +"databricks": "d79c3ac70093cb4cb531e71c", +"duckdb": "d79c3ac70093cb4cb531e71c", +"generic": "d79c3ac70093cb4cb531e71c", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "d79c3ac70093cb4cb531e71c", +"postgres": "d79c3ac70093cb4cb531e71c", +"postgresql": "d79c3ac70093cb4cb531e71c", +"snowflake": "652ff8b21f638eac8fdc46c5", +"tsql": "d79c3ac70093cb4cb531e71c" +} +], +[ +"type", +{ +"DuckDB": "3673b4fbbd8a7fed7120ec2b", +"None": "3673b4fbbd8a7fed7120ec2b", +"bigquery": "3673b4fbbd8a7fed7120ec2b", +"databricks": "3673b4fbbd8a7fed7120ec2b", +"duckdb": "3673b4fbbd8a7fed7120ec2b", +"generic": "3673b4fbbd8a7fed7120ec2b", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "3673b4fbbd8a7fed7120ec2b", +"postgres": "3673b4fbbd8a7fed7120ec2b", +"postgresql": "3673b4fbbd8a7fed7120ec2b", +"snowflake": "3673b4fbbd8a7fed7120ec2b", +"tsql": "3673b4fbbd8a7fed7120ec2b" +} +], +[ +"type", +{ +"DuckDB": "d2e8f9f7288b371199b1652e", +"None": "9bca83e64bfacf0a80ca9b34", +"bigquery": "fe1b4290ba0c2395d949643d", +"databricks": "fe1b4290ba0c2395d949643d", +"duckdb": "d2e8f9f7288b371199b1652e", +"generic": "9bca83e64bfacf0a80ca9b34", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "fe1b4290ba0c2395d949643d", +"postgres": "d2e8f9f7288b371199b1652e", +"postgresql": "d2e8f9f7288b371199b1652e", +"snowflake": "c326a07d4a8adffde91e55cd", +"tsql": "fe1b4290ba0c2395d949643d" +} +], +[ +"type", +{ +"DuckDB": "19bdd92ea0cc5fb028657510", +"None": "b8321619b794db091c9e96a1", +"bigquery": "b8321619b794db091c9e96a1", +"databricks": "1e75e5227bea0ae294ac7af1", +"duckdb": "19bdd92ea0cc5fb028657510", +"generic": "b8321619b794db091c9e96a1", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "b8321619b794db091c9e96a1", +"postgres": "b8321619b794db091c9e96a1", +"postgresql": "b8321619b794db091c9e96a1", +"snowflake": "b8321619b794db091c9e96a1", +"tsql": "b8321619b794db091c9e96a1" +} +], +[ +"type", +{ +"DuckDB": "77ffdb80029bd6e2cca768ad", +"None": "77ffdb80029bd6e2cca768ad", +"bigquery": "77ffdb80029bd6e2cca768ad", +"databricks": "77ffdb80029bd6e2cca768ad", +"duckdb": "77ffdb80029bd6e2cca768ad", +"generic": "77ffdb80029bd6e2cca768ad", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "77ffdb80029bd6e2cca768ad", +"postgres": "77ffdb80029bd6e2cca768ad", +"postgresql": "77ffdb80029bd6e2cca768ad", +"snowflake": "77ffdb80029bd6e2cca768ad", +"tsql": "77ffdb80029bd6e2cca768ad" +} +], +[ +"type", +{ +"DuckDB": "b69a57be16780e0a5e4acadb", +"None": "b69a57be16780e0a5e4acadb", +"bigquery": "b69a57be16780e0a5e4acadb", +"databricks": "b69a57be16780e0a5e4acadb", +"duckdb": "b69a57be16780e0a5e4acadb", +"generic": "b69a57be16780e0a5e4acadb", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "b69a57be16780e0a5e4acadb", +"postgres": "b69a57be16780e0a5e4acadb", +"postgresql": "b69a57be16780e0a5e4acadb", +"snowflake": "b69a57be16780e0a5e4acadb", +"tsql": "b69a57be16780e0a5e4acadb" +} +], +[ +"type", +{ +"DuckDB": "c50a316d091c821866e4bfba", +"None": "c50a316d091c821866e4bfba", +"bigquery": "c50a316d091c821866e4bfba", +"databricks": "c50a316d091c821866e4bfba", +"duckdb": "c50a316d091c821866e4bfba", +"generic": "c50a316d091c821866e4bfba", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "c50a316d091c821866e4bfba", +"postgres": "c50a316d091c821866e4bfba", +"postgresql": "c50a316d091c821866e4bfba", +"snowflake": "c50a316d091c821866e4bfba", +"tsql": "c50a316d091c821866e4bfba" +} +], +[ +"type", +{ +"DuckDB": "f1625f38cf20f9627bc717a9", +"None": "f1625f38cf20f9627bc717a9", +"bigquery": "f1625f38cf20f9627bc717a9", +"databricks": "f1625f38cf20f9627bc717a9", +"duckdb": "f1625f38cf20f9627bc717a9", +"generic": "f1625f38cf20f9627bc717a9", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "f1625f38cf20f9627bc717a9", +"postgres": "f1625f38cf20f9627bc717a9", +"postgresql": "f1625f38cf20f9627bc717a9", +"snowflake": "f1625f38cf20f9627bc717a9", +"tsql": "f1625f38cf20f9627bc717a9" +} +], +[ +"type", +{ +"DuckDB": "e998cd8f0f74af0526b75ff0", +"None": "e998cd8f0f74af0526b75ff0", +"bigquery": "a428302e4848ffe877284c84", +"databricks": "e998cd8f0f74af0526b75ff0", +"duckdb": "e998cd8f0f74af0526b75ff0", +"generic": "e998cd8f0f74af0526b75ff0", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "e998cd8f0f74af0526b75ff0", +"postgres": "e998cd8f0f74af0526b75ff0", +"postgresql": "e998cd8f0f74af0526b75ff0", +"snowflake": "652ff8b21f638eac8fdc46c5", +"tsql": "e998cd8f0f74af0526b75ff0" +} +], +[ +"type", +{ +"DuckDB": "fa45b7e4a9ef3b5a9c5781af", +"None": "fa45b7e4a9ef3b5a9c5781af", +"bigquery": "fa45b7e4a9ef3b5a9c5781af", +"databricks": "fa45b7e4a9ef3b5a9c5781af", +"duckdb": "fa45b7e4a9ef3b5a9c5781af", +"generic": "fa45b7e4a9ef3b5a9c5781af", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "fa45b7e4a9ef3b5a9c5781af", +"postgres": "fa45b7e4a9ef3b5a9c5781af", +"postgresql": "fa45b7e4a9ef3b5a9c5781af", +"snowflake": "fa45b7e4a9ef3b5a9c5781af", +"tsql": "fa45b7e4a9ef3b5a9c5781af" +} +], +[ +"type", +{ +"DuckDB": "5abf4ec799a2ec32fb10da7e", +"None": "4b356542044f1267fcfc487a", +"bigquery": "4b356542044f1267fcfc487a", +"databricks": "4b356542044f1267fcfc487a", +"duckdb": "5abf4ec799a2ec32fb10da7e", +"generic": "4b356542044f1267fcfc487a", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "4b356542044f1267fcfc487a", +"postgres": "4b356542044f1267fcfc487a", +"postgresql": "4b356542044f1267fcfc487a", +"snowflake": "4b356542044f1267fcfc487a", +"tsql": "4b356542044f1267fcfc487a" +} +], +[ +"type", +{ +"DuckDB": "1ebac487198b6c90b027faab", +"None": "1ebac487198b6c90b027faab", +"bigquery": "a428302e4848ffe877284c84", +"databricks": "1ebac487198b6c90b027faab", +"duckdb": "1ebac487198b6c90b027faab", +"generic": "1ebac487198b6c90b027faab", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "1ebac487198b6c90b027faab", +"postgres": "1ebac487198b6c90b027faab", +"postgresql": "1ebac487198b6c90b027faab", +"snowflake": "652ff8b21f638eac8fdc46c5", +"tsql": "c692d974ee3f362ecb38f27c" +} +], +[ +"type", +{ +"DuckDB": "1fe8a2d5a41383bd8e502808", +"None": "1fe8a2d5a41383bd8e502808", +"bigquery": "70f3d045595fbd43219efb36", +"databricks": "70f3d045595fbd43219efb36", +"duckdb": "1fe8a2d5a41383bd8e502808", +"generic": "1fe8a2d5a41383bd8e502808", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "70f3d045595fbd43219efb36", +"postgres": "1fe8a2d5a41383bd8e502808", +"postgresql": "1fe8a2d5a41383bd8e502808", +"snowflake": "1fe8a2d5a41383bd8e502808", +"tsql": "1fe8a2d5a41383bd8e502808" +} +], +[ +"type", +{ +"DuckDB": "c50a316d091c821866e4bfba", +"None": "c50a316d091c821866e4bfba", +"bigquery": "c50a316d091c821866e4bfba", +"databricks": "c50a316d091c821866e4bfba", +"duckdb": "c50a316d091c821866e4bfba", +"generic": "c50a316d091c821866e4bfba", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "c50a316d091c821866e4bfba", +"postgres": "c50a316d091c821866e4bfba", +"postgresql": "c50a316d091c821866e4bfba", +"snowflake": "c50a316d091c821866e4bfba", +"tsql": "c50a316d091c821866e4bfba" +} +], +[ +"type", +{ +"DuckDB": "035bb58fd2c7dca585a5899c", +"None": "035bb58fd2c7dca585a5899c", +"bigquery": "035bb58fd2c7dca585a5899c", +"databricks": "958e791772d9007024c889d3", +"duckdb": "035bb58fd2c7dca585a5899c", +"generic": "035bb58fd2c7dca585a5899c", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "770b1d275ab7799c8484f304", +"postgres": "035bb58fd2c7dca585a5899c", +"postgresql": "035bb58fd2c7dca585a5899c", +"snowflake": "035bb58fd2c7dca585a5899c", +"tsql": "035bb58fd2c7dca585a5899c" +} +], +[ +"type", +{ +"DuckDB": "7515c0db413239044adef879", +"None": "7515c0db413239044adef879", +"bigquery": "f276e907770196606577c932", +"databricks": "7515c0db413239044adef879", +"duckdb": "7515c0db413239044adef879", +"generic": "7515c0db413239044adef879", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "7515c0db413239044adef879", +"postgres": "7515c0db413239044adef879", +"postgresql": "7515c0db413239044adef879", +"snowflake": "67b5874a2c569226c490211f", +"tsql": "7515c0db413239044adef879" +} +], +[ +"type", +{ +"DuckDB": "a3b6b25265be330ec52a3322", +"None": "a3b6b25265be330ec52a3322", +"bigquery": "204206d1d1eecf007966cc5b", +"databricks": "e3bc1b8bad22d8104417b00f", +"duckdb": "a3b6b25265be330ec52a3322", +"generic": "a3b6b25265be330ec52a3322", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "919b7ec6a7b49d8527b784cd", +"postgres": "a3b6b25265be330ec52a3322", +"postgresql": "a3b6b25265be330ec52a3322", +"snowflake": "919b7ec6a7b49d8527b784cd", +"tsql": "a3b6b25265be330ec52a3322" +} +], +[ +"type", +{ +"DuckDB": "d61c83ef8bfdf043fa672cb5", +"None": "d61c83ef8bfdf043fa672cb5", +"bigquery": "c9b810639795a7bfab91b98d", +"databricks": "d61c83ef8bfdf043fa672cb5", +"duckdb": "d61c83ef8bfdf043fa672cb5", +"generic": "d61c83ef8bfdf043fa672cb5", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "d61c83ef8bfdf043fa672cb5", +"postgres": "d61c83ef8bfdf043fa672cb5", +"postgresql": "d61c83ef8bfdf043fa672cb5", +"snowflake": "97a20344d811fb77c7690863", +"tsql": "d61c83ef8bfdf043fa672cb5" +} +], +[ +"type", +{ +"DuckDB": "268b9b7c7862c9de6569286a", +"None": "268b9b7c7862c9de6569286a", +"bigquery": "268b9b7c7862c9de6569286a", +"databricks": "268b9b7c7862c9de6569286a", +"duckdb": "268b9b7c7862c9de6569286a", +"generic": "268b9b7c7862c9de6569286a", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "268b9b7c7862c9de6569286a", +"postgres": "268b9b7c7862c9de6569286a", +"postgresql": "268b9b7c7862c9de6569286a", +"snowflake": "268b9b7c7862c9de6569286a", +"tsql": "268b9b7c7862c9de6569286a" +} +], +[ +"type", +{ +"DuckDB": "f6c3d80bfee0ec0b286b82b5", +"None": "b137c998bdaa2555d912e8fa", +"bigquery": "b137c998bdaa2555d912e8fa", +"databricks": "b137c998bdaa2555d912e8fa", +"duckdb": "f6c3d80bfee0ec0b286b82b5", +"generic": "b137c998bdaa2555d912e8fa", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "b137c998bdaa2555d912e8fa", +"postgres": "b137c998bdaa2555d912e8fa", +"postgresql": "b137c998bdaa2555d912e8fa", +"snowflake": "b137c998bdaa2555d912e8fa", +"tsql": "b137c998bdaa2555d912e8fa" +} +], +[ +"type", +{ +"DuckDB": "4ed568ea1adb2c8a7141be20", +"None": "b981394a3f4d961a44e73868", +"bigquery": "f65845aac707b13992e53f87", +"databricks": "b981394a3f4d961a44e73868", +"duckdb": "4ed568ea1adb2c8a7141be20", +"generic": "b981394a3f4d961a44e73868", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "6c03a3450ea4742ee7396e3c", +"postgres": "4ed568ea1adb2c8a7141be20", +"postgresql": "4ed568ea1adb2c8a7141be20", +"snowflake": "311749caf0bd53fee7b23fa1", +"tsql": "8e94482f81cd02e976359898" +} +], +[ +"type", +{ +"DuckDB": "d5b8a68e96a7848f2aa7b2d6", +"None": "d5b8a68e96a7848f2aa7b2d6", +"bigquery": "316ab5126bbd68359eedc4d9", +"databricks": "d5b8a68e96a7848f2aa7b2d6", +"duckdb": "d5b8a68e96a7848f2aa7b2d6", +"generic": "d5b8a68e96a7848f2aa7b2d6", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "d5b8a68e96a7848f2aa7b2d6", +"postgres": "d5b8a68e96a7848f2aa7b2d6", +"postgresql": "d5b8a68e96a7848f2aa7b2d6", +"snowflake": "652ff8b21f638eac8fdc46c5", +"tsql": "d5b8a68e96a7848f2aa7b2d6" +} +], +[ +"type", +{ +"DuckDB": "1fa913156c869f5373066b2b", +"None": "1fa913156c869f5373066b2b", +"bigquery": "1fa913156c869f5373066b2b", +"databricks": "1fa913156c869f5373066b2b", +"duckdb": "1fa913156c869f5373066b2b", +"generic": "1fa913156c869f5373066b2b", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "1fa913156c869f5373066b2b", +"postgres": "1fa913156c869f5373066b2b", +"postgresql": "1fa913156c869f5373066b2b", +"snowflake": "1fa913156c869f5373066b2b", +"tsql": "1fa913156c869f5373066b2b" +} +], +[ +"type", +{ +"DuckDB": "3673b4fbbd8a7fed7120ec2b", +"None": "3673b4fbbd8a7fed7120ec2b", +"bigquery": "3673b4fbbd8a7fed7120ec2b", +"databricks": "3673b4fbbd8a7fed7120ec2b", +"duckdb": "3673b4fbbd8a7fed7120ec2b", +"generic": "3673b4fbbd8a7fed7120ec2b", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "3673b4fbbd8a7fed7120ec2b", +"postgres": "3673b4fbbd8a7fed7120ec2b", +"postgresql": "3673b4fbbd8a7fed7120ec2b", +"snowflake": "3673b4fbbd8a7fed7120ec2b", +"tsql": "3673b4fbbd8a7fed7120ec2b" +} +], +[ +"type", +{ +"DuckDB": "7770c7aba92f1bba835ef3f8", +"None": "7770c7aba92f1bba835ef3f8", +"bigquery": "7770c7aba92f1bba835ef3f8", +"databricks": "7770c7aba92f1bba835ef3f8", +"duckdb": "7770c7aba92f1bba835ef3f8", +"generic": "7770c7aba92f1bba835ef3f8", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "7770c7aba92f1bba835ef3f8", +"postgres": "7770c7aba92f1bba835ef3f8", +"postgresql": "7770c7aba92f1bba835ef3f8", +"snowflake": "7770c7aba92f1bba835ef3f8", +"tsql": "7770c7aba92f1bba835ef3f8" +} +], +[ +"type", +{ +"DuckDB": "70fb4728c3adcf6dbe4975d5", +"None": "70fb4728c3adcf6dbe4975d5", +"bigquery": "70fb4728c3adcf6dbe4975d5", +"databricks": "70fb4728c3adcf6dbe4975d5", +"duckdb": "70fb4728c3adcf6dbe4975d5", +"generic": "70fb4728c3adcf6dbe4975d5", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "70fb4728c3adcf6dbe4975d5", +"postgres": "70fb4728c3adcf6dbe4975d5", +"postgresql": "70fb4728c3adcf6dbe4975d5", +"snowflake": "70fb4728c3adcf6dbe4975d5", +"tsql": "70fb4728c3adcf6dbe4975d5" +} +], +[ +"type", +{ +"DuckDB": "e57ac1541fb51b362cd5b470", +"None": "e57ac1541fb51b362cd5b470", +"bigquery": "e57ac1541fb51b362cd5b470", +"databricks": "e57ac1541fb51b362cd5b470", +"duckdb": "e57ac1541fb51b362cd5b470", +"generic": "e57ac1541fb51b362cd5b470", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "e57ac1541fb51b362cd5b470", +"postgres": "e57ac1541fb51b362cd5b470", +"postgresql": "e57ac1541fb51b362cd5b470", +"snowflake": "4b356542044f1267fcfc487a", +"tsql": "e57ac1541fb51b362cd5b470" +} +], +[ +"type", +{ +"DuckDB": "436bf2624179c536a0157841", +"None": "3c6e55e3040bec9d73dd1bae", +"bigquery": "f1e1c64039c39ec114b5ede6", +"databricks": "21bc62fef8fe5716ed99f7be", +"duckdb": "436bf2624179c536a0157841", +"generic": "3c6e55e3040bec9d73dd1bae", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "3c6e55e3040bec9d73dd1bae", +"postgres": "8141c88dbee0d916c5447a97", +"postgresql": "8141c88dbee0d916c5447a97", +"snowflake": "cfa49b8de6f3939e2701f38d", +"tsql": "28f1e600e17067938d8a74f4" +} +], +[ +"type", +{ +"DuckDB": "431ce1fed4f6ce1e6c2a6479", +"None": "6282d36888b8e0aadda09779", +"bigquery": "9da8d0485dcb32b3b63f0ed3", +"databricks": "6282d36888b8e0aadda09779", +"duckdb": "431ce1fed4f6ce1e6c2a6479", +"generic": "6282d36888b8e0aadda09779", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "6c03a3450ea4742ee7396e3c", +"postgres": "431ce1fed4f6ce1e6c2a6479", +"postgresql": "431ce1fed4f6ce1e6c2a6479", +"snowflake": "4ea9204c46e0ec4e3a94f672", +"tsql": "d1dc9a140dbe2eb1874c6ad7" +} +], +[ +"type", +{ +"DuckDB": "9917d6c8c04307304904313b", +"None": "9917d6c8c04307304904313b", +"bigquery": "9917d6c8c04307304904313b", +"databricks": "9917d6c8c04307304904313b", +"duckdb": "9917d6c8c04307304904313b", +"generic": "9917d6c8c04307304904313b", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "9917d6c8c04307304904313b", +"postgres": "9917d6c8c04307304904313b", +"postgresql": "9917d6c8c04307304904313b", +"snowflake": "9917d6c8c04307304904313b", +"tsql": "9917d6c8c04307304904313b" +} +], +[ +"type", +{ +"DuckDB": "c50a316d091c821866e4bfba", +"None": "c50a316d091c821866e4bfba", +"bigquery": "c50a316d091c821866e4bfba", +"databricks": "c50a316d091c821866e4bfba", +"duckdb": "c50a316d091c821866e4bfba", +"generic": "c50a316d091c821866e4bfba", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "c50a316d091c821866e4bfba", +"postgres": "c50a316d091c821866e4bfba", +"postgresql": "c50a316d091c821866e4bfba", +"snowflake": "c50a316d091c821866e4bfba", +"tsql": "c50a316d091c821866e4bfba" +} +], +[ +"type", +{ +"DuckDB": "0712c33a016f7dd6a37ee011", +"None": "0712c33a016f7dd6a37ee011", +"bigquery": "0712c33a016f7dd6a37ee011", +"databricks": "0712c33a016f7dd6a37ee011", +"duckdb": "0712c33a016f7dd6a37ee011", +"generic": "0712c33a016f7dd6a37ee011", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "0f3f17e0fe13c04b84ded556", +"postgres": "0712c33a016f7dd6a37ee011", +"postgresql": "0712c33a016f7dd6a37ee011", +"snowflake": "0712c33a016f7dd6a37ee011", +"tsql": "0712c33a016f7dd6a37ee011" +} +], +[ +"type", +{ +"DuckDB": "fe23594c781e79cbb0c8927a", +"None": "fe23594c781e79cbb0c8927a", +"bigquery": "fe23594c781e79cbb0c8927a", +"databricks": "fe23594c781e79cbb0c8927a", +"duckdb": "fe23594c781e79cbb0c8927a", +"generic": "fe23594c781e79cbb0c8927a", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "fe23594c781e79cbb0c8927a", +"postgres": "fe23594c781e79cbb0c8927a", +"postgresql": "fe23594c781e79cbb0c8927a", +"snowflake": "38b2ec94bf02be40007ce525", +"tsql": "fe23594c781e79cbb0c8927a" +} +], +[ +"type", +{ +"DuckDB": "7fa8f60977ab1aa305af9d4b", +"None": "8c6ca3f77bf44837655a903e", +"bigquery": "89138ea06a52edf9b7991dd8", +"databricks": "3aa50c38af078e9f02f5a1c8", +"duckdb": "7fa8f60977ab1aa305af9d4b", +"generic": "8c6ca3f77bf44837655a903e", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "8c6ca3f77bf44837655a903e", +"postgres": "8c6ca3f77bf44837655a903e", +"postgresql": "8c6ca3f77bf44837655a903e", +"snowflake": "05188197e056965f895710b0", +"tsql": "8c6ca3f77bf44837655a903e" +} +], +[ +"type", +{ +"DuckDB": "ee47e1424cb01deb0cf51760", +"None": "ee47e1424cb01deb0cf51760", +"bigquery": "ee47e1424cb01deb0cf51760", +"databricks": "ee47e1424cb01deb0cf51760", +"duckdb": "ee47e1424cb01deb0cf51760", +"generic": "ee47e1424cb01deb0cf51760", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "ee47e1424cb01deb0cf51760", +"postgres": "ee47e1424cb01deb0cf51760", +"postgresql": "ee47e1424cb01deb0cf51760", +"snowflake": "ee47e1424cb01deb0cf51760", +"tsql": "ee47e1424cb01deb0cf51760" +} +], +[ +"type", +{ +"DuckDB": "49fdedaa5356fcccaa6f2f38", +"None": "49fdedaa5356fcccaa6f2f38", +"bigquery": "49fdedaa5356fcccaa6f2f38", +"databricks": "49fdedaa5356fcccaa6f2f38", +"duckdb": "49fdedaa5356fcccaa6f2f38", +"generic": "49fdedaa5356fcccaa6f2f38", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "49fdedaa5356fcccaa6f2f38", +"postgres": "49fdedaa5356fcccaa6f2f38", +"postgresql": "49fdedaa5356fcccaa6f2f38", +"snowflake": "49fdedaa5356fcccaa6f2f38", +"tsql": "49fdedaa5356fcccaa6f2f38" +} +], +[ +"type", +{ +"DuckDB": "70fb4728c3adcf6dbe4975d5", +"None": "70fb4728c3adcf6dbe4975d5", +"bigquery": "70fb4728c3adcf6dbe4975d5", +"databricks": "70fb4728c3adcf6dbe4975d5", +"duckdb": "70fb4728c3adcf6dbe4975d5", +"generic": "70fb4728c3adcf6dbe4975d5", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "70fb4728c3adcf6dbe4975d5", +"postgres": "70fb4728c3adcf6dbe4975d5", +"postgresql": "70fb4728c3adcf6dbe4975d5", +"snowflake": "70fb4728c3adcf6dbe4975d5", +"tsql": "70fb4728c3adcf6dbe4975d5" +} +], +[ +"type", +{ +"DuckDB": "19bdd92ea0cc5fb028657510", +"None": "b8321619b794db091c9e96a1", +"bigquery": "b8321619b794db091c9e96a1", +"databricks": "1e75e5227bea0ae294ac7af1", +"duckdb": "19bdd92ea0cc5fb028657510", +"generic": "b8321619b794db091c9e96a1", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "b8321619b794db091c9e96a1", +"postgres": "b8321619b794db091c9e96a1", +"postgresql": "b8321619b794db091c9e96a1", +"snowflake": "b8321619b794db091c9e96a1", +"tsql": "b8321619b794db091c9e96a1" +} +], +[ +"type", +{ +"DuckDB": "9f79ba9960d200f49192fa87", +"None": "46e6767a9ba2cc5fbfdc02d0", +"bigquery": "135a912ea74f76a35d9d0632", +"databricks": "46e6767a9ba2cc5fbfdc02d0", +"duckdb": "9f79ba9960d200f49192fa87", +"generic": "46e6767a9ba2cc5fbfdc02d0", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "6c03a3450ea4742ee7396e3c", +"postgres": "9f79ba9960d200f49192fa87", +"postgresql": "9f79ba9960d200f49192fa87", +"snowflake": "72c40a5d469c974c1952c3c2", +"tsql": "d1dc9a140dbe2eb1874c6ad7" +} +], +[ +"type", +{ +"DuckDB": "c50a316d091c821866e4bfba", +"None": "c50a316d091c821866e4bfba", +"bigquery": "c50a316d091c821866e4bfba", +"databricks": "c50a316d091c821866e4bfba", +"duckdb": "c50a316d091c821866e4bfba", +"generic": "c50a316d091c821866e4bfba", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "c50a316d091c821866e4bfba", +"postgres": "c50a316d091c821866e4bfba", +"postgresql": "c50a316d091c821866e4bfba", +"snowflake": "c50a316d091c821866e4bfba", +"tsql": "c50a316d091c821866e4bfba" +} +], +[ +"type", +{ +"DuckDB": "305aaf0b95cee629dd46380c", +"None": "d61c83ef8bfdf043fa672cb5", +"bigquery": "c9b810639795a7bfab91b98d", +"databricks": "d61c83ef8bfdf043fa672cb5", +"duckdb": "305aaf0b95cee629dd46380c", +"generic": "d61c83ef8bfdf043fa672cb5", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "d61c83ef8bfdf043fa672cb5", +"postgres": "d61c83ef8bfdf043fa672cb5", +"postgresql": "d61c83ef8bfdf043fa672cb5", +"snowflake": "97a20344d811fb77c7690863", +"tsql": "d61c83ef8bfdf043fa672cb5" +} +], +[ +"type", +{ +"DuckDB": "0dc0164f07551711f23943eb", +"None": "0dc0164f07551711f23943eb", +"bigquery": "0dc0164f07551711f23943eb", +"databricks": "0dc0164f07551711f23943eb", +"duckdb": "0dc0164f07551711f23943eb", +"generic": "0dc0164f07551711f23943eb", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "0dc0164f07551711f23943eb", +"postgres": "0dc0164f07551711f23943eb", +"postgresql": "0dc0164f07551711f23943eb", +"snowflake": "0dc0164f07551711f23943eb", +"tsql": "0dc0164f07551711f23943eb" +} +], +[ +"type", +{ +"DuckDB": "a428302e4848ffe877284c84", +"None": "a428302e4848ffe877284c84", +"bigquery": "a428302e4848ffe877284c84", +"databricks": "a428302e4848ffe877284c84", +"duckdb": "a428302e4848ffe877284c84", +"generic": "a428302e4848ffe877284c84", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "a428302e4848ffe877284c84", +"postgres": "a428302e4848ffe877284c84", +"postgresql": "a428302e4848ffe877284c84", +"snowflake": "652ff8b21f638eac8fdc46c5", +"tsql": "a428302e4848ffe877284c84" +} +], +[ +"type", +{ +"DuckDB": "0f799a95a4f5ef502897f02c", +"None": "0f799a95a4f5ef502897f02c", +"bigquery": "b1b23029bedaa16e2a6f8516", +"databricks": "0f799a95a4f5ef502897f02c", +"duckdb": "0f799a95a4f5ef502897f02c", +"generic": "0f799a95a4f5ef502897f02c", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "0f799a95a4f5ef502897f02c", +"postgres": "0f799a95a4f5ef502897f02c", +"postgresql": "0f799a95a4f5ef502897f02c", +"snowflake": "0f799a95a4f5ef502897f02c", +"tsql": "0f799a95a4f5ef502897f02c" +} +], +[ +"type", +{ +"DuckDB": "2bfa352725f9d8a91250f75e", +"None": "2bfa352725f9d8a91250f75e", +"bigquery": "2bfa352725f9d8a91250f75e", +"databricks": "2bfa352725f9d8a91250f75e", +"duckdb": "2bfa352725f9d8a91250f75e", +"generic": "2bfa352725f9d8a91250f75e", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "2bfa352725f9d8a91250f75e", +"postgres": "2bfa352725f9d8a91250f75e", +"postgresql": "2bfa352725f9d8a91250f75e", +"snowflake": "2bfa352725f9d8a91250f75e", +"tsql": "2bfa352725f9d8a91250f75e" +} +], +[ +"type", +{ +"DuckDB": "bda0c90e573c6a01b55627e2", +"None": "bda0c90e573c6a01b55627e2", +"bigquery": "bda0c90e573c6a01b55627e2", +"databricks": "bda0c90e573c6a01b55627e2", +"duckdb": "bda0c90e573c6a01b55627e2", +"generic": "bda0c90e573c6a01b55627e2", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "bda0c90e573c6a01b55627e2", +"postgres": "bda0c90e573c6a01b55627e2", +"postgresql": "bda0c90e573c6a01b55627e2", +"snowflake": "bda0c90e573c6a01b55627e2", +"tsql": "bda0c90e573c6a01b55627e2" +} +], +[ +"type", +{ +"DuckDB": "2705f19942a4194a72576911", +"None": "2705f19942a4194a72576911", +"bigquery": "6f763a99e9c69109526b40c0", +"databricks": "2705f19942a4194a72576911", +"duckdb": "2705f19942a4194a72576911", +"generic": "2705f19942a4194a72576911", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "2705f19942a4194a72576911", +"postgres": "2705f19942a4194a72576911", +"postgresql": "2705f19942a4194a72576911", +"snowflake": "2705f19942a4194a72576911", +"tsql": "2705f19942a4194a72576911" +} +], +[ +"type", +{ +"DuckDB": "558da38ec4d9d5d6c72f60cf", +"None": "558da38ec4d9d5d6c72f60cf", +"bigquery": "e6ffdece2977be55da73b59a", +"databricks": "558da38ec4d9d5d6c72f60cf", +"duckdb": "558da38ec4d9d5d6c72f60cf", +"generic": "558da38ec4d9d5d6c72f60cf", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "558da38ec4d9d5d6c72f60cf", +"postgres": "558da38ec4d9d5d6c72f60cf", +"postgresql": "558da38ec4d9d5d6c72f60cf", +"snowflake": "558da38ec4d9d5d6c72f60cf", +"tsql": "558da38ec4d9d5d6c72f60cf" +} +], +[ +"type", +{ +"DuckDB": "314ed506f24e92300a425780", +"None": "314ed506f24e92300a425780", +"bigquery": "314ed506f24e92300a425780", +"databricks": "314ed506f24e92300a425780", +"duckdb": "314ed506f24e92300a425780", +"generic": "314ed506f24e92300a425780", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "314ed506f24e92300a425780", +"postgres": "314ed506f24e92300a425780", +"postgresql": "314ed506f24e92300a425780", +"snowflake": "314ed506f24e92300a425780", +"tsql": "314ed506f24e92300a425780" +} +], +[ +"type", +{ +"DuckDB": "0b8ad171901cc2b7725617da", +"None": "0b8ad171901cc2b7725617da", +"bigquery": "0b8ad171901cc2b7725617da", +"databricks": "0b8ad171901cc2b7725617da", +"duckdb": "0b8ad171901cc2b7725617da", +"generic": "0b8ad171901cc2b7725617da", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "0b8ad171901cc2b7725617da", +"postgres": "0b8ad171901cc2b7725617da", +"postgresql": "0b8ad171901cc2b7725617da", +"snowflake": "0b8ad171901cc2b7725617da", +"tsql": "0b8ad171901cc2b7725617da" +} +], +[ +"type", +{ +"DuckDB": "363159f251e264604338e690", +"None": "363159f251e264604338e690", +"bigquery": "363159f251e264604338e690", +"databricks": "363159f251e264604338e690", +"duckdb": "363159f251e264604338e690", +"generic": "363159f251e264604338e690", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "363159f251e264604338e690", +"postgres": "363159f251e264604338e690", +"postgresql": "363159f251e264604338e690", +"snowflake": "363159f251e264604338e690", +"tsql": "363159f251e264604338e690" +} +], +[ +"type", +{ +"DuckDB": "1d8b945fd793ecdcacb90c21", +"None": "1d8b945fd793ecdcacb90c21", +"bigquery": "68d2179839f17f0eb289d1aa", +"databricks": "e3bc1b8bad22d8104417b00f", +"duckdb": "1d8b945fd793ecdcacb90c21", +"generic": "1d8b945fd793ecdcacb90c21", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "1d8b945fd793ecdcacb90c21", +"postgres": "3efe8bb57c98fcbe74096b3c", +"postgresql": "3efe8bb57c98fcbe74096b3c", +"snowflake": "1d8b945fd793ecdcacb90c21", +"tsql": "1d8b945fd793ecdcacb90c21" +} +], +[ +"type", +{ +"DuckDB": "52c81331cf7cf6b56395e239", +"None": "52c81331cf7cf6b56395e239", +"bigquery": "52c81331cf7cf6b56395e239", +"databricks": "52c81331cf7cf6b56395e239", +"duckdb": "52c81331cf7cf6b56395e239", +"generic": "52c81331cf7cf6b56395e239", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "52c81331cf7cf6b56395e239", +"postgres": "52c81331cf7cf6b56395e239", +"postgresql": "52c81331cf7cf6b56395e239", +"snowflake": "52c81331cf7cf6b56395e239", +"tsql": "52c81331cf7cf6b56395e239" +} +], +[ +"type", +{ +"DuckDB": "ebc821a95b9286e22c2b26d0", +"None": "ebc821a95b9286e22c2b26d0", +"bigquery": "19a1a80ffc06169f32694de8", +"databricks": "ebc821a95b9286e22c2b26d0", +"duckdb": "ebc821a95b9286e22c2b26d0", +"generic": "ebc821a95b9286e22c2b26d0", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "ebc821a95b9286e22c2b26d0", +"postgres": "ebc821a95b9286e22c2b26d0", +"postgresql": "ebc821a95b9286e22c2b26d0", +"snowflake": "ebc821a95b9286e22c2b26d0", +"tsql": "ebc821a95b9286e22c2b26d0" +} +], +[ +"type", +{ +"DuckDB": "85569b6cabaea71507846025", +"None": "85569b6cabaea71507846025", +"bigquery": "85569b6cabaea71507846025", +"databricks": "85569b6cabaea71507846025", +"duckdb": "85569b6cabaea71507846025", +"generic": "85569b6cabaea71507846025", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "85569b6cabaea71507846025", +"postgres": "85569b6cabaea71507846025", +"postgresql": "85569b6cabaea71507846025", +"snowflake": "85569b6cabaea71507846025", +"tsql": "85569b6cabaea71507846025" +} +], +[ +"type", +{ +"DuckDB": "7f7363467010768b3de8fe05", +"None": "7f7363467010768b3de8fe05", +"bigquery": "7f7363467010768b3de8fe05", +"databricks": "7f7363467010768b3de8fe05", +"duckdb": "7f7363467010768b3de8fe05", +"generic": "7f7363467010768b3de8fe05", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "7f7363467010768b3de8fe05", +"postgres": "7f7363467010768b3de8fe05", +"postgresql": "7f7363467010768b3de8fe05", +"snowflake": "7f7363467010768b3de8fe05", +"tsql": "7f7363467010768b3de8fe05" +} +], +[ +"type", +{ +"DuckDB": "cc5643d29bc94cb1374704e9", +"None": "cc5643d29bc94cb1374704e9", +"bigquery": "cc5643d29bc94cb1374704e9", +"databricks": "cc5643d29bc94cb1374704e9", +"duckdb": "cc5643d29bc94cb1374704e9", +"generic": "cc5643d29bc94cb1374704e9", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "cc5643d29bc94cb1374704e9", +"postgres": "cc5643d29bc94cb1374704e9", +"postgresql": "cc5643d29bc94cb1374704e9", +"snowflake": "cc5643d29bc94cb1374704e9", +"tsql": "cc5643d29bc94cb1374704e9" +} +], +[ +"type", +{ +"DuckDB": "c50a316d091c821866e4bfba", +"None": "c50a316d091c821866e4bfba", +"bigquery": "c50a316d091c821866e4bfba", +"databricks": "c50a316d091c821866e4bfba", +"duckdb": "c50a316d091c821866e4bfba", +"generic": "c50a316d091c821866e4bfba", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "c50a316d091c821866e4bfba", +"postgres": "c50a316d091c821866e4bfba", +"postgresql": "c50a316d091c821866e4bfba", +"snowflake": "c50a316d091c821866e4bfba", +"tsql": "c50a316d091c821866e4bfba" +} +], +[ +"type", +{ +"DuckDB": "c91ea1fc2032c6f196132d1e", +"None": "c91ea1fc2032c6f196132d1e", +"bigquery": "c91ea1fc2032c6f196132d1e", +"databricks": "c91ea1fc2032c6f196132d1e", +"duckdb": "c91ea1fc2032c6f196132d1e", +"generic": "c91ea1fc2032c6f196132d1e", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "c91ea1fc2032c6f196132d1e", +"postgres": "c91ea1fc2032c6f196132d1e", +"postgresql": "c91ea1fc2032c6f196132d1e", +"snowflake": "c91ea1fc2032c6f196132d1e", +"tsql": "c91ea1fc2032c6f196132d1e" +} +], +[ +"type", +{ +"DuckDB": "87496ad15619ba3d233601ad", +"None": "87496ad15619ba3d233601ad", +"bigquery": "87496ad15619ba3d233601ad", +"databricks": "5878645b159a4a60df8c2681", +"duckdb": "87496ad15619ba3d233601ad", +"generic": "87496ad15619ba3d233601ad", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "675e09f896465856e2673811", +"postgres": "87496ad15619ba3d233601ad", +"postgresql": "87496ad15619ba3d233601ad", +"snowflake": "87496ad15619ba3d233601ad", +"tsql": "87496ad15619ba3d233601ad" +} +], +[ +"type", +{ +"DuckDB": "23f70cb2333740d79361d52e", +"None": "23f70cb2333740d79361d52e", +"bigquery": "816384049477221b0a4a5b89", +"databricks": "23f70cb2333740d79361d52e", +"duckdb": "23f70cb2333740d79361d52e", +"generic": "23f70cb2333740d79361d52e", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "23f70cb2333740d79361d52e", +"postgres": "23f70cb2333740d79361d52e", +"postgresql": "23f70cb2333740d79361d52e", +"snowflake": "23f70cb2333740d79361d52e", +"tsql": "23f70cb2333740d79361d52e" +} +], +[ +"type", +{ +"DuckDB": "1eb7fb4e8cf75773c5573562", +"None": "1eb7fb4e8cf75773c5573562", +"bigquery": "c9b810639795a7bfab91b98d", +"databricks": "1eb7fb4e8cf75773c5573562", +"duckdb": "1eb7fb4e8cf75773c5573562", +"generic": "1eb7fb4e8cf75773c5573562", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "1eb7fb4e8cf75773c5573562", +"postgres": "1eb7fb4e8cf75773c5573562", +"postgresql": "1eb7fb4e8cf75773c5573562", +"snowflake": "97a20344d811fb77c7690863", +"tsql": "1eb7fb4e8cf75773c5573562" +} +], +[ +"type", +{ +"DuckDB": "300e2b67af892b463d85f9cd", +"None": "300e2b67af892b463d85f9cd", +"bigquery": "300e2b67af892b463d85f9cd", +"databricks": "300e2b67af892b463d85f9cd", +"duckdb": "300e2b67af892b463d85f9cd", +"generic": "300e2b67af892b463d85f9cd", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "300e2b67af892b463d85f9cd", +"postgres": "300e2b67af892b463d85f9cd", +"postgresql": "300e2b67af892b463d85f9cd", +"snowflake": "300e2b67af892b463d85f9cd", +"tsql": "300e2b67af892b463d85f9cd" +} +], +[ +"type", +{ +"DuckDB": "669084d1ea704ae5b8ee05c2", +"None": "669084d1ea704ae5b8ee05c2", +"bigquery": "669084d1ea704ae5b8ee05c2", +"databricks": "669084d1ea704ae5b8ee05c2", +"duckdb": "669084d1ea704ae5b8ee05c2", +"generic": "669084d1ea704ae5b8ee05c2", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "669084d1ea704ae5b8ee05c2", +"postgres": "669084d1ea704ae5b8ee05c2", +"postgresql": "669084d1ea704ae5b8ee05c2", +"snowflake": "669084d1ea704ae5b8ee05c2", +"tsql": "669084d1ea704ae5b8ee05c2" +} +], +[ +"type", +{ +"DuckDB": "08736485547ba339930697e9", +"None": "08736485547ba339930697e9", +"bigquery": "08736485547ba339930697e9", +"databricks": "08736485547ba339930697e9", +"duckdb": "08736485547ba339930697e9", +"generic": "08736485547ba339930697e9", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "08736485547ba339930697e9", +"postgres": "08736485547ba339930697e9", +"postgresql": "08736485547ba339930697e9", +"snowflake": "08736485547ba339930697e9", +"tsql": "08736485547ba339930697e9" +} +], +[ +"type", +{ +"DuckDB": "0c4610f182f18bf41d306e01", +"None": "0c4610f182f18bf41d306e01", +"bigquery": "0c4610f182f18bf41d306e01", +"databricks": "0c4610f182f18bf41d306e01", +"duckdb": "0c4610f182f18bf41d306e01", +"generic": "0c4610f182f18bf41d306e01", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "0c4610f182f18bf41d306e01", +"postgres": "0c4610f182f18bf41d306e01", +"postgresql": "0c4610f182f18bf41d306e01", +"snowflake": "0c4610f182f18bf41d306e01", +"tsql": "0c4610f182f18bf41d306e01" +} +], +[ +"type", +{ +"DuckDB": "fad6caec1e65529a6edc32df", +"None": "fad6caec1e65529a6edc32df", +"bigquery": "fad6caec1e65529a6edc32df", +"databricks": "fad6caec1e65529a6edc32df", +"duckdb": "fad6caec1e65529a6edc32df", +"generic": "fad6caec1e65529a6edc32df", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "fad6caec1e65529a6edc32df", +"postgres": "fad6caec1e65529a6edc32df", +"postgresql": "fad6caec1e65529a6edc32df", +"snowflake": "fad6caec1e65529a6edc32df", +"tsql": "fad6caec1e65529a6edc32df" +} +], +[ +"type", +{ +"DuckDB": "a428302e4848ffe877284c84", +"None": "a428302e4848ffe877284c84", +"bigquery": "a428302e4848ffe877284c84", +"databricks": "a428302e4848ffe877284c84", +"duckdb": "a428302e4848ffe877284c84", +"generic": "a428302e4848ffe877284c84", +"motherduck": "901c5133ed47d4769286e860", +"mysql": "a428302e4848ffe877284c84", +"postgres": "a428302e4848ffe877284c84", +"postgresql": "a428302e4848ffe877284c84", +"snowflake": "652ff8b21f638eac8fdc46c5", +"tsql": "a428302e4848ffe877284c84" +} +] +] diff --git a/tests/integration/src/sqlbuild/adapter/type_system/_test_types.py b/tests/integration/src/sqlbuild/adapter/type_system/_test_types.py index 1d687c65c5..9ea1033a45 100644 --- a/tests/integration/src/sqlbuild/adapter/type_system/_test_types.py +++ b/tests/integration/src/sqlbuild/adapter/type_system/_test_types.py @@ -1,47 +1,60 @@ -"""Test case types for native type normalization parity.""" +"""Test case types for native type normalization.""" from __future__ import annotations from dataclasses import dataclass +from sqlbuild.adapter.contract.models import NormalizedType +from sqlbuild.adapter.contract.types import TypeFamily + @dataclass(frozen=True) -class GeneratedTypeParityTestCase: +class GeneratedTypeTestCase: """Seeded generated type strings normalized under every dialect.""" description: str seed: int count: int - expected_minimum_native: int + expected_minimum_normalized: int expected_minimum_parse_errors: int - expected_minimum_deferred: int + expected_unknown_dialect_errors: int @dataclass(frozen=True) -class TypeParityTestCase: - """One type string normalized natively and by Python under every dialect.""" +class TypeNormalizationTestCase: + """One type string under one dialect, its normalization and whether a parse error is logged.""" description: str type_sql: str - expected_native_dialects: frozenset[str | None] + dialect: str | None + expected_type: NormalizedType + expected_parse_error_logged: bool + + +@dataclass(frozen=True) +class UnknownDialectTypeTestCase: + """A dialect Polyglot does not know, and the error Python's wheel raised for it.""" + + description: str + dialect: str + expected_error: str @dataclass(frozen=True) class DeepTypeTestCase: - """A type deeper than the wheel can parse, which only native sees.""" + """A deeply nested type the Python wheel normalized.""" description: str type_sql: str - expected_native: None + expected_family: TypeFamily @dataclass(frozen=True) class PublicNativeTypeTestCase: - """Types normalized through the public entry point under the preview engine.""" + """Types normalized through the public entry point under each engine.""" description: str engine: str dialect: str type_strings: tuple[str, ...] expected_native_calls: tuple[tuple[str, str], ...] - expected_answered: int diff --git a/tests/integration/src/sqlbuild/adapter/type_system/helpers.py b/tests/integration/src/sqlbuild/adapter/type_system/helpers.py index 1fbe015ea9..fba51cf622 100644 --- a/tests/integration/src/sqlbuild/adapter/type_system/helpers.py +++ b/tests/integration/src/sqlbuild/adapter/type_system/helpers.py @@ -1,4 +1,4 @@ -"""Generated type strings and Python-versus-native normalization outcomes.""" +"""Generated type strings and their native normalization outcomes.""" from __future__ import annotations @@ -9,14 +9,9 @@ from dataclasses import dataclass from itertools import product -import pytest - from sqlbuild.adapter.contract.models import NormalizedType -from sqlbuild.adapter.type_system._helpers import type_normalization from sqlbuild.adapter.type_system.constants import TYPE_NORMALIZATION_LOGGER_NAME from sqlbuild.adapter.type_system.main._native_normalize_type import normalize_native_type -from sqlbuild.compiler.frontier.constants import COMPILER_ENGINE_ENV_VAR -from sqlbuild.compiler.frontier.types import CompilerEngine DIALECTS: tuple[str | None, ...] = ( None, @@ -125,20 +120,12 @@ @dataclass(frozen=True) class TypeOutcome: - """A normalized type, Python's error, or None where native defers, and the errors logged.""" - - normalized: NormalizedType | str | None - logged_errors: tuple[tuple[str, object, object, object], ...] - - -@dataclass(frozen=True) -class TypeParity: - """One type string and dialect, normalized by Python and natively.""" + """One type string and dialect: its normalization or Python's error, and the errors logged.""" type_sql: str dialect: str | None - python: TypeOutcome - native: TypeOutcome + normalized: NormalizedType | str + logged_errors: tuple[tuple[str, object, object, object], ...] def generated_type(*, rng: random.Random, depth: int = 0) -> str: @@ -151,43 +138,39 @@ def generated_type(*, rng: random.Random, depth: int = 0) -> str: return template.format(*children, scalar=_generated_scalar(rng=rng)) -def type_parities(*, type_strings: list[str], monkeypatch: pytest.MonkeyPatch) -> list[TypeParity]: - """Normalize every type string under every dialect with Python and natively.""" +def type_outcomes(*, type_strings: list[str]) -> list[TypeOutcome]: + """Normalize every type string under every dialect.""" - parities: list[TypeParity] = [] - for type_sql, dialect in product(type_strings, DIALECTS): - parities.append(type_parity(type_sql=type_sql, dialect=dialect, monkeypatch=monkeypatch)) - return parities + return [ + type_outcome(type_sql=type_sql, dialect=dialect) + for type_sql, dialect in product(type_strings, DIALECTS) + ] -def type_parity( - *, type_sql: str, dialect: str | None, monkeypatch: pytest.MonkeyPatch -) -> TypeParity: - """Normalize one type with the Python engine and with the native type system.""" +def type_outcome(*, type_sql: str, dialect: str | None) -> TypeOutcome: + """Normalize one type natively, recording the parse errors it logs.""" - monkeypatch.setenv(COMPILER_ENGINE_ENV_VAR, CompilerEngine.PYTHON.value) - with _logged_errors() as python_errors: - python: NormalizedType | str = _python_normalized(type_sql=type_sql, dialect=dialect) - with _logged_errors() as native_errors: - native: NormalizedType | None = normalize_native_type(type_sql=type_sql, dialect=dialect) - return TypeParity( - type_sql=type_sql, - dialect=dialect, - python=TypeOutcome(normalized=python, logged_errors=tuple(python_errors)), - native=TypeOutcome(normalized=native, logged_errors=tuple(native_errors)), + with _logged_errors() as errors: + normalized: NormalizedType | str + try: + normalized = normalize_native_type(type_sql=type_sql, dialect=dialect) + except ValueError as error: + normalized = f"{type(error).__name__}: {error}" + return TypeOutcome( + type_sql=type_sql, dialect=dialect, normalized=normalized, logged_errors=tuple(errors) ) -def is_native(parity: TypeParity) -> bool: - """Return whether the native type system answered.""" +def is_normalized(outcome: TypeOutcome) -> bool: + """Return whether the type normalized rather than raising.""" - return parity.native.normalized is not None + return isinstance(outcome.normalized, NormalizedType) -def logged_parse_error(parity: TypeParity) -> bool: - """Return whether Python logged a Polyglot parse failure for this type.""" +def logged_parse_error(outcome: TypeOutcome) -> bool: + """Return whether a Polyglot parse failure was logged for this type.""" - return bool(parity.python.logged_errors) + return bool(outcome.logged_errors) def _generated_scalar(*, rng: random.Random) -> str: @@ -197,13 +180,6 @@ def _generated_scalar(*, rng: random.Random) -> str: ) -def _python_normalized(*, type_sql: str, dialect: str | None) -> NormalizedType | str: - try: - return type_normalization.normalize_type.__wrapped__(type_sql=type_sql, dialect=dialect) - except ValueError as error: - return f"{type(error).__name__}: {error}" - - @contextmanager def _logged_errors() -> Iterator[list[tuple[str, object, object, object]]]: records: list[tuple[str, object, object, object]] = [] @@ -233,3 +209,12 @@ def emit(self, record: logging.LogRecord) -> None: getattr(record, "sqlbuild_error", None), ) ) + + +def dialect_outcomes(outcomes: list[TypeOutcome]) -> dict[str, tuple[object, bool]]: + """One type string's normalization and whether it logged errors, by dialect.""" + + return { + str(outcome.dialect): (outcome.normalized, bool(outcome.logged_errors)) + for outcome in outcomes + } diff --git a/tests/integration/src/sqlbuild/adapter/type_system/test_native_type_normalization.py b/tests/integration/src/sqlbuild/adapter/type_system/test_native_type_normalization.py new file mode 100644 index 0000000000..6df3e97bc5 --- /dev/null +++ b/tests/integration/src/sqlbuild/adapter/type_system/test_native_type_normalization.py @@ -0,0 +1,332 @@ +"""Native type normalization: generated types, explicit shapes and Python's errors.""" + +from __future__ import annotations + +import random +from collections.abc import Callable + +import pytest + +import sqlbuild._native as native_module +from sqlbuild.adapter.contract.models import NormalizedType +from sqlbuild.adapter.contract.types import TypeFamily +from sqlbuild.adapter.type_system._helpers.type_normalization import ( + normalize_type as cached_normalize_type, +) +from sqlbuild.adapter.type_system.main.normalize_type import normalize_type +from sqlbuild.compiler.frontier.constants import COMPILER_ENGINE_ENV_VAR +from tests.integration.src.sqlbuild.adapter.type_system._test_types import ( + DeepTypeTestCase, + GeneratedTypeTestCase, + PublicNativeTypeTestCase, + TypeNormalizationTestCase, + UnknownDialectTypeTestCase, +) +from tests.integration.src.sqlbuild.adapter.type_system.helpers import ( + DIALECTS, + TypeOutcome, + dialect_outcomes, + generated_type, + is_normalized, + logged_parse_error, + type_outcome, + type_outcomes, +) +from tests.integration.src.sqlbuild.compiler.helpers import ( + GoldenEntry, + golden_differences, + golden_entry, + golden_name, + read_golden, +) + + +@pytest.mark.parametrize( + "test_case", + [ + GeneratedTypeTestCase( + description="seeded scalar, parameterized, nested, padded and invalid types", + seed=20261008, + count=1500, + expected_minimum_normalized=16000, + expected_minimum_parse_errors=5000, + expected_unknown_dialect_errors=1500, + ), + ], + ids=lambda case: case.description, +) +def test_given_generated_types_when_normalizing_then_every_known_dialect_answers( + test_case: GeneratedTypeTestCase, +) -> None: + rng: random.Random = random.Random(test_case.seed) + type_strings: list[str] = [generated_type(rng=rng) for _ in range(test_case.count)] + outcomes: list[TypeOutcome] = type_outcomes(type_strings=type_strings) + normalized: list[TypeOutcome] = list(filter(is_normalized, outcomes)) + golden: list[GoldenEntry] = [ + golden_entry( + "type", dialect_outcomes(outcomes[index * len(DIALECTS) : (index + 1) * len(DIALECTS)]) + ) + for index in range(len(type_strings)) + ] + + assert ( + golden_differences( + read_golden(golden_name("types_generated", test_case.description)), golden + ) + == [] + ) + assert ( + len(normalized) >= test_case.expected_minimum_normalized, + sum(map(logged_parse_error, normalized)) >= test_case.expected_minimum_parse_errors, + len(outcomes) - len(normalized), + ) == (True, True, test_case.expected_unknown_dialect_errors), test_case.description + + +@pytest.mark.parametrize( + "test_case", + [ + TypeNormalizationTestCase( + description="integer aliases under BigQuery", + type_sql="INTEGER", + dialect="bigquery", + expected_type=NormalizedType(normalized_name="INT64", family=TypeFamily.INTEGER), + expected_parse_error_logged=False, + ), + TypeNormalizationTestCase( + description="snowflake number precision and scale defaults", + type_sql="NUMBER", + dialect="snowflake", + expected_type=NormalizedType( + normalized_name="DECIMAL(38,0)", family=TypeFamily.DECIMAL, precision=38, scale=0 + ), + expected_parse_error_logged=False, + ), + TypeNormalizationTestCase( + description="spaced decimal parameters", + type_sql=" decimal( 10 , 2 ) ", + dialect="duckdb", + expected_type=NormalizedType( + normalized_name="DECIMAL(10,2)", family=TypeFamily.DECIMAL, precision=10, scale=2 + ), + expected_parse_error_logged=False, + ), + TypeNormalizationTestCase( + description="unbounded snowflake text", + type_sql="TEXT", + dialect="snowflake", + expected_type=NormalizedType( + normalized_name="VARCHAR(16777216)", family=TypeFamily.STRING, length=16777216 + ), + expected_parse_error_logged=False, + ), + TypeNormalizationTestCase( + description="nested array of structs", + type_sql="ARRAY>>", + dialect="bigquery", + expected_type=NormalizedType( + normalized_name="ARRAY>>", + family=TypeFamily.OTHER, + ), + expected_parse_error_logged=False, + ), + TypeNormalizationTestCase( + description="map of varchar to decimal", + type_sql="MAP(VARCHAR, DECIMAL(18, 4))", + dialect="duckdb", + expected_type=NormalizedType( + normalized_name="MAP(TEXT,DECIMAL(18,4))", family=TypeFamily.OTHER + ), + expected_parse_error_logged=False, + ), + TypeNormalizationTestCase( + description="quoted custom type", + type_sql='"Order Status"', + dialect="postgres", + expected_type=NormalizedType(normalized_name="ORDERSTATUS", family=TypeFamily.OTHER), + expected_parse_error_logged=False, + ), + TypeNormalizationTestCase( + description="timestamp aliases", + type_sql="timestamp_ntz(9)", + dialect="snowflake", + expected_type=NormalizedType( + normalized_name="TIMESTAMP_NTZ", family=TypeFamily.TIMESTAMP + ), + expected_parse_error_logged=False, + ), + TypeNormalizationTestCase( + description="invalid type falls back after a logged parse error", + type_sql="order status", + dialect="generic", + expected_type=NormalizedType(normalized_name="ORDERSTATUS", family=TypeFamily.OTHER), + expected_parse_error_logged=True, + ), + TypeNormalizationTestCase( + description="parameters beyond i64 stay Python integers", + type_sql="VARCHAR(99999999999999999999)", + dialect="snowflake", + expected_type=NormalizedType( + normalized_name="VARCHAR(99999999999999999999)", + family=TypeFamily.STRING, + length=99999999999999999999, + ), + expected_parse_error_logged=True, + ), + TypeNormalizationTestCase( + description="array suffixes past the old bracket cap", + type_sql="INT" + "[]" * 33 + "", + dialect="duckdb", + expected_type=NormalizedType( + normalized_name="INT" + "[]" * 33, family=TypeFamily.OTHER + ), + expected_parse_error_logged=False, + ), + TypeNormalizationTestCase( + description="non-ASCII text upper-cases as Python does", + type_sql="caf\u00e9", + dialect="generic", + expected_type=NormalizedType(normalized_name="CAF\u00c9", family=TypeFamily.OTHER), + expected_parse_error_logged=False, + ), + TypeNormalizationTestCase( + description="non-ASCII text folds sharp s as Python does", + type_sql="stra\u00dfe", + dialect="snowflake", + expected_type=NormalizedType(normalized_name="STRASSE", family=TypeFamily.OTHER), + expected_parse_error_logged=False, + ), + TypeNormalizationTestCase( + description="Unicode decimal digits are Python integers", + type_sql="VARCHAR(\u0663)", + dialect="snowflake", + expected_type=NormalizedType( + normalized_name="VARCHAR(3)", family=TypeFamily.STRING, length=3 + ), + expected_parse_error_logged=True, + ), + TypeNormalizationTestCase( + description="a dialect outside the old native build", + type_sql="INT", + dialect="mysql", + expected_type=NormalizedType(normalized_name="INT", family=TypeFamily.INTEGER), + expected_parse_error_logged=False, + ), + TypeNormalizationTestCase( + description="a dialect-specific type outside the old native build", + type_sql="UInt8", + dialect="clickhouse", + expected_type=NormalizedType(normalized_name="UINT8", family=TypeFamily.OTHER), + expected_parse_error_logged=False, + ), + ], + ids=lambda case: case.description, +) +def test_given_type_when_normalizing_then_python_shape_is_returned( + test_case: TypeNormalizationTestCase, +) -> None: + outcome: TypeOutcome = type_outcome(type_sql=test_case.type_sql, dialect=test_case.dialect) + + assert (outcome.normalized, logged_parse_error(outcome)) == ( + test_case.expected_type, + test_case.expected_parse_error_logged, + ), test_case.description + + +@pytest.mark.parametrize( + "test_case", + [ + UnknownDialectTypeTestCase( + description="a dialect name Polyglot does not know", + dialect="motherduck", + expected_error="ValueError: Unknown dialect: motherduck", + ), + ], + ids=lambda case: case.description, +) +def test_given_unknown_dialect_when_normalizing_then_python_error_is_raised( + test_case: UnknownDialectTypeTestCase, +) -> None: + outcome: TypeOutcome = type_outcome(type_sql="INT", dialect=test_case.dialect) + + assert outcome.normalized == test_case.expected_error, test_case.description + + +@pytest.mark.parametrize( + "test_case", + [ + DeepTypeTestCase( + description="5,000 array suffixes, a depth the Python wheel normalized", + type_sql="INT" + "[]" * 5_000, + expected_family=TypeFamily.OTHER, + ), + ], + ids=lambda case: case.description, +) +def test_given_deeply_nested_type_when_normalizing_then_python_shape_is_returned( + test_case: DeepTypeTestCase, +) -> None: + outcome: TypeOutcome = type_outcome(type_sql=test_case.type_sql, dialect="duckdb") + + assert outcome.normalized == NormalizedType( + normalized_name=test_case.type_sql, family=test_case.expected_family + ), test_case.description + + +@pytest.mark.parametrize( + "test_case", + [ + PublicNativeTypeTestCase( + description="the public entry point asks native first under the preview engine", + engine="native-preview", + dialect="snowflake", + type_strings=("NUMBER(38, 0)", "VARCHAR", "TIMESTAMP_NTZ(9)"), + expected_native_calls=( + ("NUMBER(38, 0)", "snowflake"), + ("VARCHAR", "snowflake"), + ("TIMESTAMP_NTZ(9)", "snowflake"), + ), + ), + PublicNativeTypeTestCase( + description="the public entry point asks native first under the default engine", + engine="native", + dialect="snowflake", + type_strings=("NUMBER(38, 0)", "VARCHAR", "TIMESTAMP_NTZ(9)"), + expected_native_calls=( + ("NUMBER(38, 0)", "snowflake"), + ("VARCHAR", "snowflake"), + ("TIMESTAMP_NTZ(9)", "snowflake"), + ), + ), + ], + ids=lambda case: case.description, +) +def test_given_native_engine_when_normalizing_publicly_then_native_answers( + test_case: PublicNativeTypeTestCase, monkeypatch: pytest.MonkeyPatch +) -> None: + calls: list[tuple[str, str]] = [] + answers: list[object] = [] + native_normalize: Callable[[str, str], object] = native_module.normalize_type + + def spy(type_sql: str, dialect: str) -> object: + calls.append((type_sql, dialect)) + answers.append(native_normalize(type_sql, dialect)) + return answers[-1] + + monkeypatch.setenv(COMPILER_ENGINE_ENV_VAR, test_case.engine) + monkeypatch.setattr(native_module, "normalize_type", spy) + cached_normalize_type.cache_clear() + normalized: list[NormalizedType] = [ + normalize_type(type_sql=type_sql, dialect=test_case.dialect) + for type_sql in test_case.type_strings + ] + cached_normalize_type.cache_clear() + + assert (tuple(calls), len(answers), len(normalized)) == ( + test_case.expected_native_calls, + len(test_case.type_strings), + len(test_case.type_strings), + ) + + +if __name__ == "__main__": + pytest.main([__file__, "-vv"]) diff --git a/tests/integration/src/sqlbuild/adapter/type_system/test_native_type_parity.py b/tests/integration/src/sqlbuild/adapter/type_system/test_native_type_parity.py deleted file mode 100644 index eb8684d68d..0000000000 --- a/tests/integration/src/sqlbuild/adapter/type_system/test_native_type_parity.py +++ /dev/null @@ -1,240 +0,0 @@ -"""Native type normalization matches Python for every type it answers, or defers.""" - -from __future__ import annotations - -import random -from collections.abc import Callable - -import pytest - -import sqlbuild._native as native_module -from sqlbuild.adapter.contract.models import NormalizedType -from sqlbuild.adapter.type_system._helpers.type_normalization import ( - normalize_type as cached_normalize_type, -) -from sqlbuild.adapter.type_system.main._native_normalize_type import normalize_native_type -from sqlbuild.adapter.type_system.main.normalize_type import normalize_type -from sqlbuild.compiler.frontier.constants import COMPILER_ENGINE_ENV_VAR -from tests.integration.src.sqlbuild.adapter.type_system._test_types import ( - DeepTypeTestCase, - GeneratedTypeParityTestCase, - PublicNativeTypeTestCase, - TypeParityTestCase, -) -from tests.integration.src.sqlbuild.adapter.type_system.helpers import ( - TypeParity, - generated_type, - is_native, - logged_parse_error, - type_parities, -) -from tests.integration.src.sqlbuild.compiler.helpers import mismatches - -_NATIVE_DIALECTS: frozenset[str | None] = frozenset( - {None, "generic", "bigquery", "snowflake", "duckdb", "databricks", "postgres", "tsql"} - | {"postgresql", "DuckDB"} -) - - -@pytest.mark.parametrize( - "test_case", - [ - GeneratedTypeParityTestCase( - description="seeded scalar, parameterized, nested, padded and invalid types", - seed=20261008, - count=1500, - expected_minimum_native=12000, - expected_minimum_parse_errors=5000, - expected_minimum_deferred=3000, - ), - ], - ids=lambda case: case.description, -) -def test_given_generated_types_when_normalizing_natively_then_python_normalization_matches( - test_case: GeneratedTypeParityTestCase, monkeypatch: pytest.MonkeyPatch -) -> None: - rng: random.Random = random.Random(test_case.seed) - type_strings: list[str] = [generated_type(rng=rng) for _ in range(test_case.count)] - parities: list[TypeParity] = type_parities(type_strings=type_strings, monkeypatch=monkeypatch) - - answered: list[TypeParity] = list(filter(is_native, parities)) - assert ( - mismatches( - inputs=[(parity.type_sql, parity.dialect) for parity in answered], - expected=[parity.python for parity in answered], - actual=[parity.native for parity in answered], - ), - len(answered) >= test_case.expected_minimum_native, - sum(map(logged_parse_error, answered)) >= test_case.expected_minimum_parse_errors, - len(parities) - len(answered) >= test_case.expected_minimum_deferred, - ) == ([], True, True, True), test_case.description - - -@pytest.mark.parametrize( - "test_case", - [ - TypeParityTestCase( - description="integer aliases", - type_sql="INTEGER", - expected_native_dialects=_NATIVE_DIALECTS, - ), - TypeParityTestCase( - description="snowflake number precision and scale defaults", - type_sql="NUMBER", - expected_native_dialects=_NATIVE_DIALECTS, - ), - TypeParityTestCase( - description="spaced decimal parameters", - type_sql=" decimal( 10 , 2 ) ", - expected_native_dialects=_NATIVE_DIALECTS, - ), - TypeParityTestCase( - description="unbounded text", - type_sql="TEXT", - expected_native_dialects=_NATIVE_DIALECTS, - ), - TypeParityTestCase( - description="nested array of structs", - type_sql="ARRAY>>", - expected_native_dialects=_NATIVE_DIALECTS, - ), - TypeParityTestCase( - description="map of varchar to decimal", - type_sql="MAP(VARCHAR, DECIMAL(18, 4))", - expected_native_dialects=_NATIVE_DIALECTS, - ), - TypeParityTestCase( - description="quoted custom type", - type_sql='"Order Status"', - expected_native_dialects=_NATIVE_DIALECTS, - ), - TypeParityTestCase( - description="timestamp aliases", - type_sql="timestamp_ntz(9)", - expected_native_dialects=_NATIVE_DIALECTS, - ), - TypeParityTestCase( - description="invalid type falls back after a logged parse error", - type_sql="order status", - expected_native_dialects=_NATIVE_DIALECTS, - ), - TypeParityTestCase( - description="parameters Python keeps as large integers defer", - type_sql="VARCHAR(99999999999999999999)", - expected_native_dialects=frozenset(), - ), - TypeParityTestCase( - description="array suffixes at the bracket cap", - type_sql="INT" + "[]" * 32, - expected_native_dialects=_NATIVE_DIALECTS, - ), - TypeParityTestCase( - description="array suffixes past the bracket cap defer", - type_sql="INT" + "[]" * 33, - expected_native_dialects=frozenset(), - ), - TypeParityTestCase( - description="non-ASCII text defers", - type_sql="caf\u00e9", - expected_native_dialects=frozenset(), - ), - ], - ids=lambda case: case.description, -) -def test_given_type_when_normalizing_under_each_dialect_then_native_answers_match_python( - test_case: TypeParityTestCase, monkeypatch: pytest.MonkeyPatch -) -> None: - parities: list[TypeParity] = type_parities( - type_strings=[test_case.type_sql], monkeypatch=monkeypatch - ) - - answered: list[TypeParity] = list(filter(is_native, parities)) - assert ( - mismatches( - inputs=[parity.dialect for parity in answered], - expected=[parity.python for parity in answered], - actual=[parity.native for parity in answered], - ), - frozenset(parity.dialect for parity in answered), - ) == ([], test_case.expected_native_dialects), test_case.description - - -@pytest.mark.parametrize( - "test_case", - [ - DeepTypeTestCase( - description="100,000 array suffixes, past where the wheel itself overflows", - type_sql="INT" + "[]" * 100_000, - expected_native=None, - ), - ], - ids=lambda case: case.description, -) -def test_given_type_past_the_wheel_depth_when_normalizing_natively_then_it_defers( - test_case: DeepTypeTestCase, -) -> None: - assert normalize_native_type(type_sql=test_case.type_sql, dialect="generic") is ( - test_case.expected_native - ) - - -@pytest.mark.parametrize( - "test_case", - [ - PublicNativeTypeTestCase( - description="the public entry point asks native first under the preview engine", - engine="native-preview", - dialect="snowflake", - type_strings=("NUMBER(38, 0)", "VARCHAR", "TIMESTAMP_NTZ(9)"), - expected_native_calls=( - ("NUMBER(38, 0)", "snowflake"), - ("VARCHAR", "snowflake"), - ("TIMESTAMP_NTZ(9)", "snowflake"), - ), - expected_answered=3, - ), - PublicNativeTypeTestCase( - description="the public entry point asks native first under the default engine", - engine="native", - dialect="snowflake", - type_strings=("NUMBER(38, 0)", "VARCHAR", "TIMESTAMP_NTZ(9)"), - expected_native_calls=( - ("NUMBER(38, 0)", "snowflake"), - ("VARCHAR", "snowflake"), - ("TIMESTAMP_NTZ(9)", "snowflake"), - ), - expected_answered=3, - ), - ], - ids=lambda case: case.description, -) -def test_given_native_engine_when_normalizing_publicly_then_native_answers( - test_case: PublicNativeTypeTestCase, monkeypatch: pytest.MonkeyPatch -) -> None: - calls: list[tuple[str, str]] = [] - answers: list[object] = [] - native_normalize: Callable[[str, str], object] = native_module.normalize_type - - def spy(type_sql: str, dialect: str) -> object: - calls.append((type_sql, dialect)) - answers.append(native_normalize(type_sql, dialect)) - return answers[-1] - - monkeypatch.setenv(COMPILER_ENGINE_ENV_VAR, test_case.engine) - monkeypatch.setattr(native_module, "normalize_type", spy) - cached_normalize_type.cache_clear() - normalized: list[NormalizedType] = [ - normalize_type(type_sql=type_sql, dialect=test_case.dialect) - for type_sql in test_case.type_strings - ] - cached_normalize_type.cache_clear() - - assert ( - tuple(calls), - sum(answer is not None for answer in answers), - len(normalized), - ) == (test_case.expected_native_calls, test_case.expected_answered, len(test_case.type_strings)) - - -if __name__ == "__main__": - pytest.main([__file__, "-vv"]) diff --git a/tests/integration/src/sqlbuild/cli/commands/main/helpers.py b/tests/integration/src/sqlbuild/cli/commands/main/helpers.py index c1df2f1e6b..e5910cb01d 100644 --- a/tests/integration/src/sqlbuild/cli/commands/main/helpers.py +++ b/tests/integration/src/sqlbuild/cli/commands/main/helpers.py @@ -27,8 +27,8 @@ from sqlbuild.cli.commands.classes.prepared_compile_artifacts import PreparedCompileArtifacts from sqlbuild.cli.commands.main.entrypoint.entry import main from sqlbuild.cli.compile.models import PlannedStaticSqlTests +from sqlbuild.compiler.analysis_session.models import NativeQueryColumns from sqlbuild.compiler.compile._helpers.assembly import source_bindings as source_bindings_module -from sqlbuild.compiler.compile.models import PolyglotAnalysisResult from sqlbuild.compiler.discovery._helpers.native import ( model_files as native_model_files_module, ) @@ -174,7 +174,6 @@ def fail_native_planner(monkeypatch: pytest.MonkeyPatch) -> None: def fail(**kwargs: object) -> tuple[NativeSqlTestArtifact, ...]: raise NativeSqlTestPlanningError("native SQL-test planning failed: worker stopped") - monkeypatch.setattr(target_writer, "plan_and_render_sql_test_artifacts", fail) monkeypatch.setattr(target_writer, "plan_native_sql_test_artifacts", fail) @@ -661,17 +660,15 @@ def record_source_rebinding_analyses(monkeypatch: pytest.MonkeyPatch) -> list[st """Record every model query analysed again against inspected source columns.""" analysed: list[str] = [] - original: Callable[..., PolyglotAnalysisResult] = ( - source_bindings_module.analyze_columns_and_lineage_with_polyglot + original: Callable[..., tuple[NativeQueryColumns, ...]] = ( + source_bindings_module.infer_native_query_columns ) - def recording(**kwargs: Any) -> PolyglotAnalysisResult: - analysed.append(str(kwargs["query_sql"])) + def recording(**kwargs: Any) -> tuple[NativeQueryColumns, ...]: + analysed.extend(query.sql for query in kwargs["queries"]) return original(**kwargs) - monkeypatch.setattr( - source_bindings_module, "analyze_columns_and_lineage_with_polyglot", recording - ) + monkeypatch.setattr(source_bindings_module, "infer_native_query_columns", recording) return analysed diff --git a/tests/integration/src/sqlbuild/compiler/analysis_session/_test_helpers.py b/tests/integration/src/sqlbuild/compiler/analysis_session/_test_helpers.py index 7622a8d2bf..6db0951552 100644 --- a/tests/integration/src/sqlbuild/compiler/analysis_session/_test_helpers.py +++ b/tests/integration/src/sqlbuild/compiler/analysis_session/_test_helpers.py @@ -6,10 +6,8 @@ from collections import Counter from collections.abc import Callable from dataclasses import dataclass -from typing import Any import sqlbuild._native as native_module -import sqlbuild.compiler.compile._helpers.analysis.compact as compact_analysis from sqlbuild.adapter.contract.classes.base_adapter import BaseAdapter from sqlbuild.adapter.contract.models import ExpressionInferenceProfile from sqlbuild.adapter.type_system.main.conditional_result_nullability import ( @@ -22,14 +20,7 @@ from sqlbuild.adapters.postgres.classes.postgres_adapter import PostgresAdapter from sqlbuild.adapters.snowflake.classes.snowflake_adapter import SnowflakeAdapter from sqlbuild.adapters.sqlserver.classes.sqlserver_adapter import SqlServerAdapter -from sqlbuild.compiler.analysis_session._helpers.session_rows import nullability_rule_rows -from sqlbuild.compiler.compile._helpers.analysis.cte_facts import ( - _polyglot_cte_passthrough_facts, - _polyglot_filtered_non_null_outputs, -) -from sqlbuild.compiler.compile.models import CteFactResolvers -from sqlbuild.compiler.lineage.types import InferredNullability -from sqlbuild.compiler.sql_analysis.main.import_polyglot import import_polyglot +from sqlbuild.compiler.analysis_session._helpers.profile_rows import nullability_rule_rows type Generate = Callable[[random.Random, list[str], int], str] type CteFactView = ( @@ -49,10 +40,9 @@ class CteFactQuery: @dataclass class CteFactParity: - """Python's and native's recovered facts for every query native answered.""" + """Native's recovered facts for every query it answered.""" queries: list[object] - python: list[object] native: list[object] counts: Counter[str] @@ -86,20 +76,9 @@ class CteFactParity: "Events": {"event_id": "INT", "kind": "VARCHAR(10)"}, "events": {"event_id": "BIGINT", "payload": "JSON"}, } -_INPUT_NULLABILITY: dict[str, dict[str, InferredNullability]] = { - table: dict.fromkeys(columns, InferredNullability.UNKNOWN) - for table, columns in _SCHEMAS.items() -} _INPUT_SHAPES: list[tuple[str, list[tuple[str, str]]]] = [ (table, list(columns.items())) for table, columns in _SCHEMAS.items() ] -_NULL_FILTER_USE: dict[str, str] = {"context": "filter", "expressionSql": "x IS NOT NULL"} -_RESOLVERS: CteFactResolvers = CteFactResolvers( - expression_type=compact_analysis._polyglot_expression_type, - nullability=compact_analysis._infer_polyglot_nullability, - shallow_nullability=compact_analysis._infer_polyglot_shallow_nullability, - alias_nullability=compact_analysis._polyglot_alias_nullability_from_select, -) _ADAPTERS: tuple[BaseAdapter, ...] = ( DuckDbAdapter(), SnowflakeAdapter(), @@ -369,43 +348,6 @@ def generated_cte_fact_query(*, rng: random.Random) -> CteFactQuery: ) -def python_cte_facts(*, query: CteFactQuery) -> CteFactView: - """Python's recovered facts, as enrichment computes them, or what it raises.""" - - analysis: dict[str, Any] = { - "cteFacts": [1][: int(query.recover)], - "columnUses": [_NULL_FILTER_USE][: int(query.null_filter)], - } - dialect: str | None = query.profile.sql_analysis_dialect - try: - types, nullability, direct, parsed = _polyglot_cte_passthrough_facts( - polyglot_module=import_polyglot(), - cleaned_sql=query.sql, - dialect=dialect, - column_types_by_table=_SCHEMAS, - column_nullability_by_table=_INPUT_NULLABILITY, - inference_profile=query.profile, - analysis=analysis, - resolvers=_RESOLVERS, - ) - non_null: frozenset[str] = _polyglot_filtered_non_null_outputs( - polyglot_module=import_polyglot(), - cleaned_sql=query.sql, - dialect=dialect, - analysis=analysis, - column_nullability_by_table=_INPUT_NULLABILITY, - parsed=parsed, - ) - except Exception as error: # noqa: BLE001 - native must not answer where Python raises - return (type(error).__name__, str(error)) - return ( - list(types.items()), - [(name, value.value) for name, value in nullability.items()], - sorted(direct), - sorted(non_null), - ) - - def native_cte_facts(*, query: CteFactQuery) -> tuple[str | None, CteFactView]: """Native recovery's deferral reason, or None and its facts.""" @@ -424,11 +366,10 @@ def native_cte_facts(*, query: CteFactQuery) -> tuple[str | None, CteFactView]: def compare_cte_facts(*, query: CteFactQuery, parity: CteFactParity) -> None: - """Record both recoveries of `query` where native answers, and what each recovered.""" + """Record native recovery of `query` where it answers, and what it recovered.""" deferral, native = native_cte_facts(query=query) answered: list[CteFactView] = [native][: int(deferral is None)] - python: list[CteFactView] = [python_cte_facts(query=query) for _ in answered] parity.counts.update( [f"deferred:{str(deferral).partition(' ')[0]}"][: int(deferral is not None)] ) @@ -436,5 +377,4 @@ def compare_cte_facts(*, query: CteFactQuery, parity: CteFactParity) -> None: for index, kind in enumerate(_FACT_KINDS): parity.counts[f"recovered_{kind}"] += sum(bool(view[index]) for view in answered) parity.queries.extend((query.sql, query.profile.sql_analysis_dialect) for _ in answered) - parity.python.extend(python) parity.native.extend(answered) diff --git a/tests/integration/src/sqlbuild/compiler/analysis_session/_test_types.py b/tests/integration/src/sqlbuild/compiler/analysis_session/_test_types.py index 6bce16f42e..7b53a6d733 100644 --- a/tests/integration/src/sqlbuild/compiler/analysis_session/_test_types.py +++ b/tests/integration/src/sqlbuild/compiler/analysis_session/_test_types.py @@ -3,12 +3,13 @@ from dataclasses import dataclass from sqlbuild.adapter.contract.models import ExpressionInferenceProfile +from sqlbuild.compiler.analysis_session.types import QueryColumnsMode from sqlbuild.compiler.lineage.types import ColumnLineageMode @dataclass(frozen=True) -class GeneratedAnalysisParityTestCase: - """Seeded generated projects whose model analysis both engines must agree on.""" +class GeneratedAnalysisTestCase: + """Seeded generated projects whose uncached, cached and re-proven native analyses agree.""" description: str seed: int @@ -20,33 +21,38 @@ class GeneratedAnalysisParityTestCase: expected_minimum_native: int expected_minimum_expression_shapes: int expected_minimum_pivot_proofs: int - expected_minimum_python_cte_recoveries: int - expected_minimum_legacy_analyses: int - expected_legacy_analysis_deferrals: int expected_minimum_proven_pivots: int - expected_maximum_enrichment_deferrals: int expected_minimum_native_enrichments: int @dataclass(frozen=True) -class AnalysisFallbackTestCase: - """A project the native session hands back to Python whole, recording why.""" +class InternalFailureTestCase: + """A project whose native analysis fails internally, and the error the compile raises.""" description: str files: dict[str, str] - allow_compact_analysis: bool - keeps_catalog: bool - expected_kind: str + expected_message: str @dataclass(frozen=True) -class SessionFailureTestCase: - """A session that fails after Python answered deferrals, so Python analyses everything.""" +class CyclicAnalysisTestCase: + """Models that `ref` each other, which the native session analyses in one unordered wave.""" description: str - seed: int - model_count: int - expected_kinds: dict[str, int] + files: dict[str, str] + dialects: tuple[str, ...] + lineage_modes: tuple[ColumnLineageMode, ...] + expected_analysed: int + + +@dataclass(frozen=True) +class CyclicCompileTestCase: + """A project whose models `ref` each other, compiled through the CLI.""" + + description: str + files: dict[str, str] + expected_exit_code: int + expected_compiled: tuple[str, ...] @dataclass(frozen=True) @@ -84,3 +90,70 @@ class CteFactRecoveryParityTestCase: count: int expected_minimum_compared: int expected_minimum_recovered: dict[str, int] + + +@dataclass(frozen=True) +class AdapterRuleCallbackTestCase: + """A project-local adapter rule the native session calls back into, and what it raises.""" + + description: str + seed: int + model_count: int + raised: type[Exception] | None + expected_minimum_calls: int + + +@dataclass(frozen=True) +class SharedQueryOutputTestCase: + """Models with equal query shapes over different inputs, and each model's own outputs.""" + + description: str + models: dict[str, str] + expected_lineage: tuple[tuple[str, str, str], ...] = () + expected_findings: tuple[tuple[str, str], ...] = () + + +@dataclass(frozen=True) +class FallbackColumnsTestCase: + """A model native analysis cannot project, and the columns its parsed tree still gives.""" + + description: str + query_sql: str + expected_columns: tuple[tuple[str, str | None, str], ...] + + +@dataclass(frozen=True) +class TableFunctionColumnsTestCase: + """A table function's declared return columns against its body's output columns.""" + + description: str + returns: str + body_sql: str + expected_error: str | None + + +@dataclass(frozen=True) +class MissingSessionAnalysisTestCase: + """A broken invariant: the session returns no analysis for a model it was asked about.""" + + description: str + expected_message: str + + +@dataclass(frozen=True) +class ProjectionFactsTestCase: + """Fixture queries whose projection facts Python recorded in a golden.""" + + description: str + queries: tuple[tuple[str, str], ...] + expected_differences: list[tuple[int, str, object, object]] + + +@dataclass(frozen=True) +class NormalizationRejectionTestCase: + """Queries outside the session whose analysis SQL Python's normalization rejects.""" + + description: str + queries: tuple[tuple[str, QueryColumnsMode], ...] + dialect: str + expected_message: str diff --git a/tests/integration/src/sqlbuild/compiler/analysis_session/helpers.py b/tests/integration/src/sqlbuild/compiler/analysis_session/helpers.py index 2f11c54cef..9f149afe19 100644 --- a/tests/integration/src/sqlbuild/compiler/analysis_session/helpers.py +++ b/tests/integration/src/sqlbuild/compiler/analysis_session/helpers.py @@ -1,12 +1,13 @@ from __future__ import annotations +import functools +import itertools import json import random from collections import Counter from collections.abc import Callable from contextlib import suppress from dataclasses import dataclass, field, replace -from functools import partial from itertools import chain from pathlib import Path from typing import Any, cast @@ -15,11 +16,11 @@ import sqlbuild._native as native_module import sqlbuild.compiler.analysis_session.classes.native_model_analysis as native_model_analysis -import sqlbuild.compiler.compile._helpers.analysis.compact as compact_analysis import sqlbuild.compiler.compile._helpers.assembly.project as project_assembly import sqlbuild.compiler.compile._helpers.native_stages.assembly as native_stage_assembly from sqlbuild.adapter.contract.models import ExpressionInferenceProfile from sqlbuild.adapters.duckdb.classes.duckdb_adapter import DuckDbAdapter +from sqlbuild.cli.entry.main.entry import main from sqlbuild.compiler.analysis_session.main._analyze_native_model_sql import ( analyze_native_model_sql, ) @@ -34,15 +35,25 @@ NativeModelAnalysisRequest, NativePivotTables, ) -from sqlbuild.compiler.compile._helpers.assembly.semantic_shapes import ( - get_expression_source_shapes, +from sqlbuild.compiler.compile._helpers.analysis.cache import build_analysis_cache_context +from sqlbuild.compiler.compile._helpers.analysis.pivot_requests import ( + model_dynamic_families, + model_pivot_sql, ) +from sqlbuild.compiler.compile._helpers.analysis.syntax_checks import model_placeholders +from sqlbuild.compiler.compile._helpers.render.cursor_intrinsics import ( + cursor_intrinsics_analysis_sql, +) +from sqlbuild.compiler.compile.classes.python_model_analysis import PythonModelAnalysis from sqlbuild.compiler.compile.exceptions import CompileInputError from sqlbuild.compiler.compile.main._build_compile_inputs import build_compile_inputs from sqlbuild.compiler.compile.models import ( + AnalysisCacheContext, CompactLineageFacts, CompileAdapterContext, CompiledLineageColumnFact, + CompiledModel, + CompileModelInput, CompileProjectInputs, DynamicColumnContractProof, InferredColumn, @@ -52,6 +63,10 @@ from sqlbuild.compiler.lineage.types import ColumnLineageMode, InferredNullability from sqlbuild.spec.contracts.models import SchemaDynamicColumnFamily from sqlbuild.sql_values.types import CollectionRendering +from tests.integration.src.sqlbuild.compiler.analysis_session._test_types import ( + AdapterRuleCallbackTestCase, +) +from tests.integration.src.sqlbuild.compiler.helpers import GoldenEntry, golden_entry _PROJECT_TOML: str = ( 'name = "orders_analysis"\nadapter = "duckdb"\n\n[connection]\ndatabase = "orders.duckdb"\n' @@ -229,11 +244,6 @@ def _pivot_models(rng: random.Random) -> dict[str, str]: return files -_PYTHON_CTE_RECOVERY: Callable[..., Any] = compact_analysis._polyglot_cte_passthrough_facts -_PYTHON_LEGACY_ANALYSIS: Callable[..., Any] = ( - compact_analysis._analyze_columns_and_lineage_from_polyglot_ast -) - type _Relation = tuple[str, tuple[str, ...]] type _Template = Callable[[random.Random, list[_Relation]], tuple[str, str, tuple[str, ...]]] @@ -411,7 +421,7 @@ class NativePivotProofs: def native_pivot_proofs(*, monkeypatch: pytest.MonkeyPatch) -> NativePivotProofs: - """Record every batch of native pivot proofs assembly takes, failing any wheel pivot proof.""" + """Record every batch of native pivot proofs assembly takes.""" recorded_proofs: NativePivotProofs = NativePivotProofs() native_proofs: Callable[..., tuple[DynamicColumnContractProof | None, ...]] = ( @@ -425,16 +435,7 @@ def recorded(**keywords: Any) -> tuple[DynamicColumnContractProof | None, ...]: recorded_proofs.session_proofs += proven * (keywords["session"] is not None) return proofs - python_proof: Callable[..., DynamicColumnContractProof | None] = ( - project_assembly.analyze_dynamic_column_contract - ) - - def wheel_not_expected(**keywords: Any) -> DynamicColumnContractProof | None: - assert not keywords["families"], "the Python wheel proved a pivot native should prove" - return python_proof(**keywords) - monkeypatch.setattr(native_stage_assembly, "prove_native_dynamic_contracts", recorded) - monkeypatch.setattr(project_assembly, "analyze_dynamic_column_contract", wheel_not_expected) return recorded_proofs @@ -505,10 +506,8 @@ def started_sessions(*, monkeypatch: pytest.MonkeyPatch) -> list[Any]: started: list[Any] = [] original: Callable[..., Any] = native_module.start_model_analysis_session - def start( - catalog: object, request: tuple[object, ...], cache: tuple[str, str] | None = None - ) -> Any: - started.append(original(catalog, request, cache)) + def start(catalog: object, request: tuple[object, ...], *options: Any) -> Any: + started.append(original(catalog, request, *options)) return started[-1] monkeypatch.setattr(native_module, "start_model_analysis_session", start) @@ -529,143 +528,141 @@ def compile_inputs(*, project_dir: Path, files: dict[str, str]) -> CompileProjec ) +def compiled_project_view( + *, + project_dir: Path, + files: dict[str, str], + capsys: pytest.CaptureFixture[str], +) -> tuple[int, object, object, dict[str, str]]: + """Compile a written project through the CLI: exit code, report, manifest nodes, SQL files.""" + + for relative_path, contents in files.items(): + path: Path = project_dir / relative_path + path.parent.mkdir(parents=True, exist_ok=True) + _ = path.write_text(contents, encoding="utf-8") + _ = capsys.readouterr() + code: int = main(["--project-dir", str(project_dir), "compile", "--json", "--manifest"]) + report: dict[str, object] = json.loads(capsys.readouterr().out) + manifest: dict[str, object] = json.loads( + (project_dir / "target" / "manifest.json").read_text(encoding="utf-8") + ) + compiled: Path = project_dir / "target" / "compiled" + _ = report.pop("compile_timings") + _ = manifest.pop("metadata") + return ( + code, + report, + manifest, + { + path.relative_to(compiled).as_posix(): path.read_text(encoding="utf-8") + for path in sorted(compiled.rglob("*.sql")) + }, + ) + + @dataclass -class AnalysisParity: - """Python's and the native session's views of every analysis seam call.""" +class NativeAnalysisRuns: + """Each native analysis seam call's uncached, cold-cached and warm-cached views.""" names: list[object] = field(default_factory=list) - python: list[object] = field(default_factory=list) - native: list[object] = field(default_factory=list) + uncached: list[object] = field(default_factory=list) + cached: list[object] = field(default_factory=list) analysed_models: int = 0 expression_shapes: int = 0 pivot_proofs: int = 0 - python_cte_recoveries: int = 0 - legacy_analyses: int = 0 standalone_proofs: int = 0 session_proofs: int = 0 proven_pivots: int = 0 native_enrichments: int = 0 native_column_objects: int = 0 native_column_values: int = 0 + golden: list[GoldenEntry] = field(default_factory=list) -def compare_analyses( +def analyse_natively( *, inputs: CompileProjectInputs, inference_profile: ExpressionInferenceProfile, lineage_mode: ColumnLineageMode, - parity: AnalysisParity, + runs: NativeAnalysisRuns, + cache_root: Path, monkeypatch: pytest.MonkeyPatch, ) -> None: - """Assemble `inputs` under `inference_profile`, analysing every seam call with both engines.""" + """Assemble `inputs`, analysing each model batch natively uncached, cold-cached and warm. - sessions: list[Any] = [] + Every analysis, catalog change, session and standalone dynamic pivot proof, and expression + shape must not depend on the analysis store, on the session, or on Python's shape inference. + `runs.golden` gathers the entries the Python oracle recorded for the same seam calls. + """ - def models_by_both( - *, - python_analysis: partial[dict[str, ModelSqlAnalysis]], - dynamic_families_by_table: dict[str, tuple[SchemaDynamicColumnFamily, ...]], + original_analysis: Callable[..., tuple[dict[str, ModelSqlAnalysis], Any]] = ( + native_stage_assembly.analyze_model_sql + ) + + def analysed_three_ways( + request: NativeModelAnalysisRequest, ) -> tuple[dict[str, ModelSqlAnalysis], Any]: - keywords: dict[str, Any] = {**python_analysis.keywords, "analysis_cache": None} - profile: ExpressionInferenceProfile = keywords["inference_profile"] - native_catalog: Any = profile.binding_catalog.with_relations({}) - native_result: NativeModelAnalyses | None = analyze_native_model_sql( - request=NativeModelAnalysisRequest( - **{ - **keywords, - "inference_profile": replace(profile, binding_catalog=native_catalog), - }, - dynamic_families_by_table=dynamic_families_by_table, - ) + profile: ExpressionInferenceProfile = request.inference_profile + cache: AnalysisCacheContext | None = build_analysis_cache_context( + root=cache_root, inference_profile=profile, allow_compact_analysis=True ) - native: dict[str, ModelSqlAnalysis] | None = getattr(native_result, "analyses", None) - sessions.append(getattr(native_result, "session", None)) - with monkeypatch.context() as patch: - patch.setattr( - compact_analysis, - "_polyglot_cte_passthrough_facts", - partial(_counted_cte_recovery, parity=parity), - ) - patch.setattr( - compact_analysis, - "_analyze_columns_and_lineage_from_polyglot_ast", - partial(_counted_legacy_analysis, parity=parity), + cached_views: list[object] = [] + for _ in range(2): + catalog: Any = cast(Any, profile.binding_catalog).with_relations({}) + cached: NativeModelAnalyses = analyze_native_model_sql( + request=replace( + request, + analysis_cache=cache, + inference_profile=replace(profile, binding_catalog=catalog), + ) ) - python: dict[str, ModelSqlAnalysis] = python_analysis.func(**keywords) + cached_views.append((_analysis_views(cached.analyses), _catalog_view(catalog))) + analyses, session = original_analysis(replace(request, analysis_cache=None)) + uncached_view: object = (_analysis_views(analyses), _catalog_view(profile.binding_catalog)) columns: list[InferredColumn] = list( - chain.from_iterable(map(_native_columns, (native or {}).values())) - ) - parity.native_column_objects += len(set(map(id, columns))) - parity.native_column_values += len(set(columns)) - parity.analysed_models += len(python) - _append(parity, "model analyses", _analysis_views(python), _analysis_views(native)) - _append( - parity, - "catalog", - _catalog_view(profile.binding_catalog), - _catalog_view(native_catalog), - ) - return native or python, sessions[-1] - - def proofs_by_both( - *, - sql_analysis: ModelSqlAnalysis | None, - native_proof: DynamicColumnContractProof | None, - python_proof: partial[DynamicColumnContractProof | None], - ) -> DynamicColumnContractProof | None: - native: DynamicColumnContractProof | None = getattr( - sql_analysis, "dynamic_column_contract", None + chain.from_iterable(map(_native_columns, analyses.values())) ) - python: DynamicColumnContractProof | None = python_proof() - session: Any = (sessions or [None])[-1] - standalone: DynamicColumnContractProof | None = _batched_proof( - session=None, python_proof=python_proof - ) - in_session: DynamicColumnContractProof | None = _batched_proof( - session=session, python_proof=python_proof - ) - parity.session_proofs += in_session is not None and session is not None - parity.pivot_proofs += native is not None - parity.proven_pivots += native is not None and native.output_proven - parity.standalone_proofs += standalone is not None - _append(parity, "dynamic pivot proof", python, native or python) - _append(parity, "standalone dynamic pivot proof", python, standalone or python) - _append(parity, "session dynamic pivot proof", python, in_session or python) - return python - - def shapes_by_both( + runs.native_column_objects += len(set(map(id, columns))) + runs.native_column_values += len(set(columns)) + runs.analysed_models += len(analyses) + runs.golden.append(golden_entry("models", _analysis_views(analyses))) + runs.golden.append(golden_entry("catalog", _catalog_view(profile.binding_catalog))) + for index, view in enumerate(cached_views): + _append(runs, f"model analyses, cached run {index}", uncached_view, view) + _compare_proofs(request=request, analyses=analyses, session=session, runs=runs) + return analyses, session + + def recorded_shapes( *, expressions: tuple[str, ...], profile: ExpressionInferenceProfile ) -> tuple[dict[str, str] | None, ...]: catalog: Any = cast(Any, profile.binding_catalog) - native_catalog: Any = catalog.with_relations({}) - native: tuple[dict[str, str] | None, ...] | None = infer_native_expression_source_shapes( - expressions=expressions, profile=replace(profile, binding_catalog=native_catalog) - ) - python: tuple[dict[str, str] | None, ...] = get_expression_source_shapes( + native: tuple[dict[str, str] | None, ...] = infer_native_expression_source_shapes( expressions=expressions, profile=profile ) - parity.expression_shapes += sum(shape is not None for shape in python) - _append( - parity, - "expression shapes", - (python, catalog.expression_shapes), - (native, native_catalog.expression_shapes), - ) - return python + runs.expression_shapes += sum(shape is not None for shape in native) + runs.golden.append(golden_entry("shapes", (native, catalog.expression_shapes))) + return native native_lineage_facts: Callable[..., tuple[CompiledLineageColumnFact, ...]] = ( native_model_analysis.lineage_facts ) def counted_native_enrichment(rows: list[Any]) -> tuple[CompiledLineageColumnFact, ...]: - parity.native_enrichments += 1 + runs.native_enrichments += 1 return native_lineage_facts(rows) + assembled_model: Callable[..., CompiledModel] = project_assembly._assemble_compiled_model + + def recorded_model(*arguments: Any, **keywords: Any) -> CompiledModel: + model: CompiledModel = assembled_model(*arguments, **keywords) + runs.golden.append(golden_entry("proof", model.dynamic_column_contract)) + return model + with monkeypatch.context() as patch: patch.setattr(native_model_analysis, "lineage_facts", counted_native_enrichment) - patch.setattr(project_assembly, "analyze_model_sql_by_engine", models_by_both) - patch.setattr(project_assembly, "expression_source_shapes_by_engine", shapes_by_both) - patch.setattr(project_assembly, "dynamic_column_contract_by_engine", proofs_by_both) + patch.setattr(project_assembly, "_assemble_compiled_model", recorded_model) + patch.setattr(project_assembly, "analyze_model_sql", analysed_three_ways) + patch.setattr(project_assembly, "expression_source_shapes_by_engine", recorded_shapes) with suppress(CompileInputError): _ = project_assembly.assemble_compiled_project( inputs=inputs, @@ -674,8 +671,22 @@ def counted_native_enrichment(rows: list[Any]) -> tuple[CompiledLineageColumnFac ) +def duplicate_analysed_model_names(*, monkeypatch: pytest.MonkeyPatch) -> None: + """Name every analysed model after the first, an invariant discovery guarantees (D007).""" + + original: Callable[[PythonModelAnalysis], list[tuple[object, ...]]] = ( + PythonModelAnalysis.model_rows + ) + + def renamed(analysis: PythonModelAnalysis) -> list[tuple[object, ...]]: + rows: list[tuple[object, ...]] = original(analysis) + return [(rows[0][0], *row[1:]) for row in rows] + + monkeypatch.setattr(PythonModelAnalysis, "model_rows", renamed) + + def custom_nullability_rule(arguments: tuple[InferredNullability, ...]) -> InferredNullability: - """An adapter rule SQLBuild does not ship, so native analysis leaves it to Python.""" + """An adapter rule SQLBuild does not ship, so native analysis calls it back.""" return InferredNullability.NULLABLE @@ -690,20 +701,15 @@ def analysis_request( requests: list[NativeModelAnalysisRequest] = [] - def captured( - *, - python_analysis: partial[dict[str, ModelSqlAnalysis]], - dynamic_families_by_table: dict[str, tuple[SchemaDynamicColumnFamily, ...]], - ) -> tuple[dict[str, ModelSqlAnalysis], None]: - requests.append( - NativeModelAnalysisRequest( - **python_analysis.keywords, dynamic_families_by_table=dynamic_families_by_table - ) - ) - return python_analysis(), None + def captured(request: NativeModelAnalysisRequest) -> tuple[dict[str, ModelSqlAnalysis], None]: + requests.append(request) + return {}, None - with monkeypatch.context() as patch, suppress(CompileInputError): - patch.setattr(project_assembly, "analyze_model_sql_by_engine", captured) + with ( + monkeypatch.context() as patch, + suppress(CompileInputError, native_module.NativeCompilerError), + ): + patch.setattr(project_assembly, "analyze_model_sql", captured) _ = project_assembly.assemble_compiled_project( inputs=inputs, inference_profile=inference_profile, @@ -728,42 +734,66 @@ def _native_columns(analysis: ModelSqlAnalysis) -> tuple[InferredColumn, ...]: return analysis.polyglot_analysis.columns or () -def _counted_legacy_analysis(*, parity: AnalysisParity, **arguments: Any) -> Any: - parity.legacy_analyses += 1 - return _PYTHON_LEGACY_ANALYSIS(**arguments) - - -def _counted_cte_recovery(*, parity: AnalysisParity, **arguments: Any) -> Any: - recovered: Any = _PYTHON_CTE_RECOVERY(**arguments) - parity.python_cte_recoveries += bool(recovered[2]) - return recovered - - -def _batched_proof( - *, session: Any, python_proof: partial[DynamicColumnContractProof | None] -) -> DynamicColumnContractProof | None: - keywords: dict[str, Any] = python_proof.keywords - return prove_native_dynamic_contracts( - session=session, - tables=NativePivotTables( - dialect=keywords["dialect"], - column_types_by_table=keywords["column_types_by_table"], - authoritative_column_types_by_table=keywords["authoritative_column_types_by_table"], - column_nullability_by_table=keywords["column_nullability_by_table"], - dynamic_families_by_table=keywords["dynamic_families_by_table"], - ), - models=((keywords["query_sql"], keywords["families"]),), - )[0] - - -def _append(parity: AnalysisParity, name: str, python: object, native: object) -> None: - parity.names.append(name) - parity.python.append(python) - parity.native.append(native) - - -def _analysis_views(analyses: dict[str, ModelSqlAnalysis] | None) -> object: - return analyses and { +def _compare_proofs( + *, + request: NativeModelAnalysisRequest, + analyses: dict[str, ModelSqlAnalysis], + session: Any, + runs: NativeAnalysisRuns, +) -> None: + """Each analysed pivot model's proof, proven again in the session and standalone.""" + + tables: NativePivotTables = NativePivotTables( + dialect=request.inference_profile.sql_analysis_dialect, + column_types_by_table=request.column_types_by_table, + authoritative_column_types_by_table=request.complete_binding_schemas, + column_nullability_by_table=request.column_nullability_by_table, + dynamic_families_by_table=request.dynamic_families_by_table, + ) + proved: list[bool] = [ + bool(model_dynamic_families(model_input)) + and model_input.model_file.file_path.stem in analyses + for model_input in request.model_inputs + ] + pivot_inputs: list[CompileModelInput] = list(itertools.compress(request.model_inputs, proved)) + for model_input in pivot_inputs: + families: tuple[SchemaDynamicColumnFamily, ...] = model_dynamic_families(model_input) + analysis: ModelSqlAnalysis = analyses[model_input.model_file.file_path.stem] + models: tuple[tuple[str, tuple[SchemaDynamicColumnFamily, ...]], ...] = ( + ( + model_pivot_sql( + query_sql=cursor_intrinsics_analysis_sql( + sql=model_input.query_sql, + cursor_type=model_input.config.values.get("cursor_type"), + ), + placeholders=model_placeholders(model_input), + ), + families, + ), + ) + proof: DynamicColumnContractProof | None = analysis.dynamic_column_contract + standalone: DynamicColumnContractProof | None = prove_native_dynamic_contracts( + session=None, tables=tables, models=models + )[0] + in_session: DynamicColumnContractProof | None = prove_native_dynamic_contracts( + session=session, tables=tables, models=models + )[0] + runs.pivot_proofs += proof is not None + runs.proven_pivots += proof is not None and proof.output_proven + runs.standalone_proofs += standalone is not None + runs.session_proofs += in_session is not None + _append(runs, "standalone dynamic pivot proof", proof, standalone) + _append(runs, "session dynamic pivot proof", proof, in_session) + + +def _append(runs: NativeAnalysisRuns, name: str, uncached: object, cached: object) -> None: + runs.names.append(name) + runs.uncached.append(uncached) + runs.cached.append(cached) + + +def _analysis_views(analyses: dict[str, ModelSqlAnalysis]) -> object: + return { name: ( analysis.polyglot_analysis.analysis_succeeded, analysis.polyglot_analysis.columns, @@ -784,36 +814,101 @@ def _catalog_view(catalog: Any) -> tuple[object, ...]: return (dict(catalog.schemas), dict(catalog.analysis_shapes)) -class FailingProvideSession: - """A native session whose answers to deferrals are refused, as a failed session refuses.""" +class RecordingNullabilityRule: + """An adapter nullability rule recording its calls, answering nullable or raising.""" - def __init__(self, session: Any) -> None: - self._session: Any = session - self.answered: int = 0 - self.failure: str = "injected session failure" + def __init__(self, *, raised: type[Exception] | None) -> None: + self.calls: list[tuple[InferredNullability, ...]] = [] + self._outcomes: list[Callable[[], InferredNullability]] = [ + _nullable, + *(functools.partial(_raise, error) for error in filter(None, (raised,))), + ] - def run(self) -> object: - return self._session.run() + def __call__(self, arguments: tuple[InferredNullability, ...]) -> InferredNullability: + self.calls.append(arguments) + return self._outcomes[-1]() - def provide(self, answers: list[object]) -> bool: - self.answered += len(answers) - return False - def finish(self) -> object: - return self._session.finish() +def adapter_rule_request( + *, + test_case: AdapterRuleCallbackTestCase, + rule: RecordingNullabilityRule, + tmp_path: Path, + monkeypatch: pytest.MonkeyPatch, +) -> NativeModelAnalysisRequest: + """A generated project plus the adapter-rule models, analysed with `rule` for UPPER and IFF.""" + + request: NativeModelAnalysisRequest = analysis_request( + inputs=compile_inputs( + project_dir=tmp_path / "project", + files={ + **generated_analysis_files( + rng=random.Random(test_case.seed), model_count=test_case.model_count + ), + **ADAPTER_RULE_MODELS, + }, + ), + monkeypatch=monkeypatch, + inference_profile=ExpressionInferenceProfile( + sql_analysis_dialect="duckdb", + function_nullability_rules={"UPPER": rule, "IFF": rule}, + ), + ) + rule.calls.clear() + return request -def failing_provide_sessions(*, monkeypatch: pytest.MonkeyPatch) -> list[FailingProvideSession]: - """Make every native session refuse Python's answers; return the sessions started.""" +def _nullable() -> InferredNullability: + return InferredNullability.NULLABLE - started: list[FailingProvideSession] = [] - original: Callable[..., Any] = native_module.start_model_analysis_session - def start( - catalog: object, request: tuple[object, ...], cache: tuple[str, str] | None = None - ) -> FailingProvideSession: - started.append(FailingProvideSession(original(catalog, request, cache))) - return started[-1] +def _raise(error: type[Exception]) -> InferredNullability: + raise error("adapter rule failed") - monkeypatch.setattr(native_module, "start_model_analysis_session", start) - return started + +def write_shared_query_project( + *, project_dir: Path, models: dict[str, str], upstream_sql: str +) -> None: + """Write an orders project with `orders`, `customers` and `models`.""" + + _ = (project_dir / "sqlbuild_project.toml").write_text( + 'name = "orders"\nadapter = "duckdb"\n[rules]\nselect = []\n', encoding="utf-8" + ) + model_dir: Path = project_dir / "models" + model_dir.mkdir() + for name, sql in {"orders": upstream_sql, "customers": upstream_sql, **models}.items(): + _ = (model_dir / f"{name}.sql").write_text(sql, encoding="utf-8") + + +def upstream_lineage_sources( + *, project_dir: Path, column: str, mode: str, capsys: pytest.CaptureFixture[str] +) -> tuple[int, list[str]]: + """The lineage command's exit code and the upstream resources of `column` one level up.""" + + code: int = main( + [ + "--project-dir", + str(project_dir), + "lineage", + column, + "--format", + "json", + "--direction", + "upstream", + "--depth", + "1", + "--mode", + mode, + ] + ) + trace: list[dict[str, Any]] = json.loads(capsys.readouterr().out)["trace"] + return code, [step["source"]["resource_name"] for step in trace] + + +def projection_view( + row: tuple[list[tuple[str, str]], list[str], list[str]], +) -> tuple[dict[str, str], frozenset[str], frozenset[str]]: + """A native projection-facts row as Python's `_simple_projection_facts` returned it.""" + + types, null_literal_names, quoted_names = row + return dict(types), frozenset(null_literal_names), frozenset(quoted_names) diff --git a/tests/integration/src/sqlbuild/compiler/analysis_session/test_native_cte_fact_recovery.py b/tests/integration/src/sqlbuild/compiler/analysis_session/test_native_cte_fact_recovery.py index 119e8e0c71..11ab086dac 100644 --- a/tests/integration/src/sqlbuild/compiler/analysis_session/test_native_cte_fact_recovery.py +++ b/tests/integration/src/sqlbuild/compiler/analysis_session/test_native_cte_fact_recovery.py @@ -1,4 +1,4 @@ -"""Native CTE fact recovery equals Python's recovery on seeded queries, query by query.""" +"""Native CTE fact recovery matches the facts recorded from Python's recovery, query by query.""" from __future__ import annotations @@ -15,7 +15,12 @@ from tests.integration.src.sqlbuild.compiler.analysis_session._test_types import ( CteFactRecoveryParityTestCase, ) -from tests.integration.src.sqlbuild.compiler.helpers import mismatches +from tests.integration.src.sqlbuild.compiler.helpers import ( + golden_differences, + golden_entry, + golden_name, + read_golden, +) @pytest.mark.parametrize( @@ -36,15 +41,21 @@ ], ids=lambda case: case.description, ) -def test_given_seeded_cte_queries_when_recovering_facts_natively_then_matches_python( +def test_given_seeded_cte_queries_when_recovering_facts_natively_then_matches_recorded_python( test_case: CteFactRecoveryParityTestCase, ) -> None: rng: random.Random = random.Random(test_case.seed) - parity: CteFactParity = CteFactParity(queries=[], python=[], native=[], counts=Counter()) + parity: CteFactParity = CteFactParity(queries=[], native=[], counts=Counter()) for _ in range(test_case.count): compare_cte_facts(query=generated_cte_fact_query(rng=rng), parity=parity) - assert mismatches(inputs=parity.queries, expected=parity.python, actual=parity.native) == [] + assert ( + golden_differences( + read_golden(golden_name("cte_facts", test_case.description)), + [golden_entry("cte_facts", view) for view in parity.native], + ) + == [] + ) assert parity.counts["compared"] >= test_case.expected_minimum_compared assert { kind: parity.counts[f"recovered_{kind}"] >= minimum diff --git a/tests/integration/src/sqlbuild/compiler/analysis_session/test_native_model_analysis.py b/tests/integration/src/sqlbuild/compiler/analysis_session/test_native_model_analysis.py index ce17a2bb06..6a1a488a99 100644 --- a/tests/integration/src/sqlbuild/compiler/analysis_session/test_native_model_analysis.py +++ b/tests/integration/src/sqlbuild/compiler/analysis_session/test_native_model_analysis.py @@ -2,14 +2,16 @@ from __future__ import annotations +import itertools import random from collections import Counter -from dataclasses import replace +from itertools import product from pathlib import Path from typing import Any import pytest +import sqlbuild._native as native_module from sqlbuild.adapter.contract.models import ExpressionInferenceProfile from sqlbuild.adapters.duckdb.classes.duckdb_adapter import DuckDbAdapter from sqlbuild.adapters.snowflake.classes.snowflake_adapter import SnowflakeAdapter @@ -24,33 +26,41 @@ ) from sqlbuild.compiler.frontier.constants import COMPILER_ENGINE_ENV_VAR from sqlbuild.compiler.frontier.types import CompilerEngine -from sqlbuild.compiler.lineage.types import ColumnLineageMode +from sqlbuild.compiler.lineage.types import ColumnLineageMode, InferredNullability from sqlbuild.compiler.sql_analysis.constants import ANALYSIS_RECORD_DIR_ENV_VAR from tests.integration.src.sqlbuild.compiler.analysis_session._test_types import ( - AnalysisFallbackTestCase, - GeneratedAnalysisParityTestCase, - SessionFailureTestCase, + AdapterRuleCallbackTestCase, + CyclicAnalysisTestCase, + CyclicCompileTestCase, + GeneratedAnalysisTestCase, + InternalFailureTestCase, SharedAnalysisTestCase, StandalonePivotProofTestCase, ) from tests.integration.src.sqlbuild.compiler.analysis_session.helpers import ( ADAPTER_RULE_MODELS, - AnalysisParity, - FailingProvideSession, + NativeAnalysisRuns, NativePivotProofs, - analysis_request, - compare_analyses, + RecordingNullabilityRule, + adapter_rule_request, + analyse_natively, compile_inputs, + compiled_project_view, custom_nullability_rule, deferral_kinds, - failing_provide_sessions, + duplicate_analysed_model_names, generated_analysis_files, native_pivot_proofs, pivot_project_files, shared_analysis_files, started_sessions, ) -from tests.integration.src.sqlbuild.compiler.helpers import mismatches +from tests.integration.src.sqlbuild.compiler.helpers import ( + golden_differences, + golden_name, + mismatches, + read_golden, +) _DIALECT_PROFILES: tuple[ExpressionInferenceProfile, ...] = tuple( ExpressionInferenceProfile(sql_analysis_dialect=dialect) @@ -60,6 +70,40 @@ SnowflakeAdapter().expression_inference_profile(), DuckDbAdapter().expression_inference_profile(), ) +_CUSTOM_RULE_PROFILES: tuple[ExpressionInferenceProfile, ...] = ( + ExpressionInferenceProfile( + sql_analysis_dialect="duckdb", + function_nullability_rules={ + **DuckDbAdapter().expression_inference_profile().function_nullability_rules, + "SUM": custom_nullability_rule, + "COALESCE": custom_nullability_rule, + }, + ), +) +_CYCLIC_PROJECT: dict[str, str] = { + "sqlbuild_project.toml": 'name = "orders_cycle"\nadapter = "duckdb"\n', + "sources/raw.yml": ( + "sources:\n - name: raw_orders\n description: Raw orders.\n columns:\n" + " - name: order_id\n type: INTEGER\n" + " - name: amount\n type: DOUBLE\n" + ), + "models/orders.sql": ( + 'MODEL (description "Orders");\n\nSELECT o.order_id, o.amount, r.refund\n' + 'FROM __source("raw_orders") AS o\n' + 'LEFT JOIN __ref("returns") AS r ON r.order_id = o.order_id\n' + ), + "models/returns.sql": ( + 'MODEL (description "Returns");\n\n' + 'SELECT order_id, amount * -1 AS refund FROM __ref("orders")\n' + ), + "models/order_summary.sql": ( + 'MODEL (description "Summary");\n\nSELECT * FROM __ref("returns")\n' + ), + "models/order_audit.sql": ( + 'MODEL (description "Audit");\n\n' + 'SELECT order_id, missing_column FROM __ref("order_audit")\n' + ), +} _ORDERS_PROJECT: dict[str, str] = { "sqlbuild_project.toml": 'name = "orders_cycle"\nadapter = "duckdb"\n', "models/orders.sql": 'MODEL (description "Orders");\n\nSELECT order_id FROM __ref("returns")\n', @@ -70,7 +114,7 @@ @pytest.mark.parametrize( "test_case", [ - GeneratedAnalysisParityTestCase( + GeneratedAnalysisTestCase( description="stars, CTEs, CTE facts, set operations, untyped inputs, contracts, pivots", seed=20261008, count=6, @@ -81,14 +125,10 @@ expected_minimum_native=500, expected_minimum_expression_shapes=40, expected_minimum_pivot_proofs=80, - expected_minimum_python_cte_recoveries=39, - expected_minimum_legacy_analyses=152, - expected_legacy_analysis_deferrals=0, expected_minimum_proven_pivots=12, - expected_maximum_enrichment_deferrals=0, expected_minimum_native_enrichments=90, ), - GeneratedAnalysisParityTestCase( + GeneratedAnalysisTestCase( description="rich lineage over untyped inputs, CTE facts and contracts", seed=20261008, count=6, @@ -99,14 +139,10 @@ expected_minimum_native=500, expected_minimum_expression_shapes=40, expected_minimum_pivot_proofs=80, - expected_minimum_python_cte_recoveries=27, - expected_minimum_legacy_analyses=95, - expected_legacy_analysis_deferrals=0, expected_minimum_proven_pivots=12, - expected_maximum_enrichment_deferrals=0, expected_minimum_native_enrichments=90, ), - GeneratedAnalysisParityTestCase( + GeneratedAnalysisTestCase( description="snowflake and duckdb adapter rules, fast lineage", seed=20261010, count=3, @@ -117,14 +153,10 @@ expected_minimum_native=200, expected_minimum_expression_shapes=15, expected_minimum_pivot_proofs=30, - expected_minimum_python_cte_recoveries=4, - expected_minimum_legacy_analyses=52, - expected_legacy_analysis_deferrals=6, expected_minimum_proven_pivots=10, - expected_maximum_enrichment_deferrals=0, expected_minimum_native_enrichments=30, ), - GeneratedAnalysisParityTestCase( + GeneratedAnalysisTestCase( description="snowflake and duckdb adapter rules, rich lineage", seed=20261010, count=3, @@ -135,25 +167,35 @@ expected_minimum_native=190, expected_minimum_expression_shapes=15, expected_minimum_pivot_proofs=30, - expected_minimum_python_cte_recoveries=4, - expected_minimum_legacy_analyses=62, - expected_legacy_analysis_deferrals=18, expected_minimum_proven_pivots=10, - expected_maximum_enrichment_deferrals=0, expected_minimum_native_enrichments=20, ), + GeneratedAnalysisTestCase( + description="a project-local adapter's own nullability rules, called back natively", + seed=20261011, + count=3, + model_count=24, + inference_profiles=_CUSTOM_RULE_PROFILES, + extra_files=ADAPTER_RULE_MODELS, + lineage_mode=ColumnLineageMode.FAST, + expected_minimum_native=1, + expected_minimum_expression_shapes=1, + expected_minimum_pivot_proofs=1, + expected_minimum_proven_pivots=1, + expected_minimum_native_enrichments=1, + ), ], ids=lambda case: case.description, ) -def test_given_generated_projects_when_analysing_natively_then_matches_python( - test_case: GeneratedAnalysisParityTestCase, +def test_given_generated_projects_when_analysing_natively_then_cached_and_proven_runs_agree( + test_case: GeneratedAnalysisTestCase, tmp_path: Path, monkeypatch: pytest.MonkeyPatch, ) -> None: record_dir: Path = tmp_path / "records" monkeypatch.setenv(ANALYSIS_RECORD_DIR_ENV_VAR, str(record_dir)) rng: random.Random = random.Random(test_case.seed) - parity: AnalysisParity = AnalysisParity() + runs: NativeAnalysisRuns = NativeAnalysisRuns() for index in range(test_case.count): inputs: CompileProjectInputs = compile_inputs( project_dir=tmp_path / f"project_{index}", @@ -162,39 +204,34 @@ def test_given_generated_projects_when_analysing_natively_then_matches_python( **test_case.extra_files, }, ) - for profile in test_case.inference_profiles: - compare_analyses( + for profile_index, profile in enumerate(test_case.inference_profiles): + analyse_natively( inputs=inputs, inference_profile=profile, lineage_mode=test_case.lineage_mode, - parity=parity, + runs=runs, + cache_root=tmp_path / f"cache_{index}_{profile_index}", monkeypatch=monkeypatch, ) kinds: Counter[str] = deferral_kinds(record_dir) + kinds.pop("analysis_session:adapter_nullability_callback", None) - assert mismatches(inputs=parity.names, expected=parity.python, actual=parity.native) == [] - assert kinds["analysis_session:session"] == kinds["analysis_session:expression_shapes"] == 0 - assert kinds["analysis_session:dynamic_pivot"] == 0 - assert kinds["analysis_session:legacy_analysis"] == test_case.expected_legacy_analysis_deferrals - assert parity.legacy_analyses >= test_case.expected_minimum_legacy_analyses - assert parity.python_cte_recoveries >= test_case.expected_minimum_python_cte_recoveries assert ( - parity.analysed_models - - kinds["analysis_session:legacy_analysis"] - - kinds["analysis_session:input_enrichment"] - >= test_case.expected_minimum_native - ) - assert parity.expression_shapes >= test_case.expected_minimum_expression_shapes - assert parity.pivot_proofs >= test_case.expected_minimum_pivot_proofs - assert parity.standalone_proofs >= test_case.expected_minimum_pivot_proofs - assert parity.session_proofs >= test_case.expected_minimum_pivot_proofs - assert parity.proven_pivots >= test_case.expected_minimum_proven_pivots - assert ( - kinds["analysis_session:input_enrichment"] - <= test_case.expected_maximum_enrichment_deferrals + golden_differences( + read_golden(golden_name("analysis_generated", test_case.description)), runs.golden + ) + == [] ) - assert parity.native_enrichments >= test_case.expected_minimum_native_enrichments - assert parity.native_column_objects == parity.native_column_values > 0 + assert mismatches(inputs=runs.names, expected=runs.uncached, actual=runs.cached) == [] + assert kinds == Counter() + assert runs.analysed_models >= test_case.expected_minimum_native + assert runs.expression_shapes >= test_case.expected_minimum_expression_shapes + assert runs.pivot_proofs >= test_case.expected_minimum_pivot_proofs + assert runs.standalone_proofs >= test_case.expected_minimum_pivot_proofs + assert runs.session_proofs >= test_case.expected_minimum_pivot_proofs + assert runs.proven_pivots >= test_case.expected_minimum_proven_pivots + assert runs.native_enrichments >= test_case.expected_minimum_native_enrichments + assert runs.native_column_objects == runs.native_column_values > 0 @pytest.mark.parametrize( @@ -214,7 +251,7 @@ def test_given_generated_projects_when_analysing_natively_then_matches_python( ], ids=lambda case: case.description, ) -def test_given_equal_model_queries_when_analysing_natively_then_shares_and_matches_python( +def test_given_equal_model_queries_when_analysing_natively_then_shares_and_cached_runs_agree( test_case: SharedAnalysisTestCase, tmp_path: Path, monkeypatch: pytest.MonkeyPatch ) -> None: record_dir: Path = tmp_path / "records" @@ -226,30 +263,38 @@ def test_given_equal_model_queries_when_analysing_natively_then_shares_and_match ), ) sessions: list[Any] = started_sessions(monkeypatch=monkeypatch) - parity: AnalysisParity = AnalysisParity() + runs: NativeAnalysisRuns = NativeAnalysisRuns() _ = [ - compare_analyses( + analyse_natively( inputs=inputs, inference_profile=ExpressionInferenceProfile(sql_analysis_dialect=dialect), lineage_mode=ColumnLineageMode.FAST, - parity=parity, + runs=runs, + cache_root=tmp_path / f"cache_{dialect}", monkeypatch=monkeypatch, ) for dialect in test_case.dialects ] - shared: int = sum(session.sharing[0] for session in sessions) + uncached: list[Any] = sessions[2::3] + shared: int = sum(session.sharing[0] for session in uncached) - assert mismatches(inputs=parity.names, expected=parity.python, actual=parity.native) == [] assert ( - parity.analysed_models, + golden_differences( + read_golden(golden_name("analysis_shared", test_case.description)), runs.golden + ) + == [] + ) + assert mismatches(inputs=runs.names, expected=runs.uncached, actual=runs.cached) == [] + assert ( + runs.analysed_models, shared, - sum(session.sharing[1] for session in sessions), - parity.analysed_models - shared, + sum(session.sharing[1] for session in uncached), + runs.analysed_models - shared, deferral_kinds(record_dir), - parity.native_column_objects, - parity.native_column_values, + runs.native_column_objects, + runs.native_column_values, ) == ( test_case.expected_analysed, test_case.expected_shared, @@ -264,92 +309,135 @@ def test_given_equal_model_queries_when_analysing_natively_then_shares_and_match @pytest.mark.parametrize( "test_case", [ - AnalysisFallbackTestCase( - description="models that reference each other", - files=_ORDERS_PROJECT, - allow_compact_analysis=True, - keeps_catalog=True, - expected_kind="session", - ), - AnalysisFallbackTestCase( - description="lineage disabled, so compact analysis is off", - files=_ORDERS_PROJECT, - allow_compact_analysis=False, - keeps_catalog=True, - expected_kind="no_compact_analysis", - ), - AnalysisFallbackTestCase( - description="an inference profile without a binding catalog", - files=_ORDERS_PROJECT, - allow_compact_analysis=True, - keeps_catalog=False, - expected_kind="no_analysis_catalog", - ), + CyclicAnalysisTestCase( + description="a ref cycle, a model reading itself and a star consumer of the cycle", + files=_CYCLIC_PROJECT, + dialects=("duckdb", "snowflake"), + lineage_modes=(ColumnLineageMode.FAST, ColumnLineageMode.RICH), + expected_analysed=16, + ) ], ids=lambda case: case.description, ) -def test_given_unsupported_analysis_when_analysing_natively_then_python_analyses_and_records( - test_case: AnalysisFallbackTestCase, tmp_path: Path, monkeypatch: pytest.MonkeyPatch +def test_given_cyclic_models_when_analysing_natively_then_session_answers_and_cached_runs_agree( + test_case: CyclicAnalysisTestCase, tmp_path: Path, monkeypatch: pytest.MonkeyPatch ) -> None: record_dir: Path = tmp_path / "records" - request: NativeModelAnalysisRequest = analysis_request( - inputs=compile_inputs(project_dir=tmp_path / "project", files=test_case.files), - monkeypatch=monkeypatch, - ) - profile: ExpressionInferenceProfile = request.inference_profile monkeypatch.setenv(ANALYSIS_RECORD_DIR_ENV_VAR, str(record_dir)) + inputs: CompileProjectInputs = compile_inputs( + project_dir=tmp_path / "project", files=test_case.files + ) + sessions: list[Any] = started_sessions(monkeypatch=monkeypatch) + runs: NativeAnalysisRuns = NativeAnalysisRuns() - analyses: object = analyze_native_model_sql( - request=replace( - request, - allow_compact_analysis=test_case.allow_compact_analysis, - inference_profile=replace( - profile, binding_catalog=(None, profile.binding_catalog)[test_case.keeps_catalog] - ), + _ = [ + analyse_natively( + inputs=inputs, + inference_profile=ExpressionInferenceProfile(sql_analysis_dialect=dialect), + lineage_mode=lineage_mode, + runs=runs, + cache_root=tmp_path / f"cache_{dialect}_{lineage_mode.value}", + monkeypatch=monkeypatch, ) - ) + for dialect, lineage_mode in product(test_case.dialects, test_case.lineage_modes) + ] - assert analyses is None - assert deferral_kinds(record_dir) == Counter({f"analysis_session:{test_case.expected_kind}": 1}) + assert ( + golden_differences( + read_golden(golden_name("analysis_cyclic", test_case.description)), runs.golden + ) + == [] + ) + assert mismatches(inputs=runs.names, expected=runs.uncached, actual=runs.cached) == [] + assert ( + runs.analysed_models, + len(sessions) // 3, + None in sessions, + deferral_kinds(record_dir), + ) == ( + test_case.expected_analysed, + len(test_case.dialects) * len(test_case.lineage_modes), + False, + Counter(), + ) @pytest.mark.parametrize( "test_case", [ - SessionFailureTestCase( - description="a custom adapter rule defers analyses before the session fails", - seed=20261009, - model_count=12, - expected_kinds={"analysis_session:session": 1}, + CyclicCompileTestCase( + description="a ref cycle, a model reading itself and a star consumer of the cycle", + files=_CYCLIC_PROJECT, + expected_exit_code=0, + expected_compiled=( + "models/order_audit.sql", + "models/order_summary.sql", + "models/orders.sql", + "models/returns.sql", + ), ) ], ids=lambda case: case.description, ) -def test_given_session_failure_after_deferrals_when_analysing_then_records_only_the_session( - test_case: SessionFailureTestCase, tmp_path: Path, monkeypatch: pytest.MonkeyPatch +def test_given_cyclic_project_when_compiling_then_native_output_is_complete_and_repeatable( + test_case: CyclicCompileTestCase, + tmp_path: Path, + capsys: pytest.CaptureFixture[str], + monkeypatch: pytest.MonkeyPatch, ) -> None: record_dir: Path = tmp_path / "records" - request: NativeModelAnalysisRequest = analysis_request( - inputs=compile_inputs( - project_dir=tmp_path / "project", - files=generated_analysis_files( - rng=random.Random(test_case.seed), model_count=test_case.model_count + monkeypatch.setenv(ANALYSIS_RECORD_DIR_ENV_VAR, str(record_dir)) + monkeypatch.setenv(COMPILER_ENGINE_ENV_VAR, CompilerEngine.NATIVE.value) + native: tuple[int, object, object, dict[str, str]] = compiled_project_view( + project_dir=tmp_path / "native" / "orders_cycle", files=test_case.files, capsys=capsys + ) + native_deferrals: Counter[str] = deferral_kinds(record_dir) + + repeated: tuple[int, object, object, dict[str, str]] = compiled_project_view( + project_dir=tmp_path / "repeated" / "orders_cycle", files=test_case.files, capsys=capsys + ) + + assert native == repeated + assert (native[0], tuple(native[3]), native_deferrals) == ( + test_case.expected_exit_code, + test_case.expected_compiled, + Counter(), + ) + + +@pytest.mark.parametrize( + "test_case", + [ + InternalFailureTestCase( + description="two analysed models sharing a name break the session's invariant", + files=_ORDERS_PROJECT, + expected_message=( + "NativeCompilerError: native model analysis: two analysed models share a name" ), ), - monkeypatch=monkeypatch, - inference_profile=ExpressionInferenceProfile( - sql_analysis_dialect="duckdb", - function_nullability_rules={"SUM": custom_nullability_rule}, - ), - ) - sessions: list[FailingProvideSession] = failing_provide_sessions(monkeypatch=monkeypatch) + ], + ids=lambda case: case.description, +) +def test_given_internal_native_failure_when_assembling_then_raises_without_python_analysis( + test_case: InternalFailureTestCase, tmp_path: Path, monkeypatch: pytest.MonkeyPatch +) -> None: + record_dir: Path = tmp_path / "records" monkeypatch.setenv(ANALYSIS_RECORD_DIR_ENV_VAR, str(record_dir)) + inputs: CompileProjectInputs = compile_inputs( + project_dir=tmp_path / "project", files=test_case.files + ) + duplicate_analysed_model_names(monkeypatch=monkeypatch) - analyses: object = analyze_native_model_sql(request=request) + with pytest.raises(native_module.NativeCompilerError) as raised: + _ = assemble_compiled_project( + inputs=inputs, + inference_profile=ExpressionInferenceProfile(sql_analysis_dialect="duckdb"), + ) - assert analyses is None - assert sum(session.answered for session in sessions) > 0 - assert deferral_kinds(record_dir) == Counter(test_case.expected_kinds) + assert (str(raised.value), deferral_kinds(record_dir)) == ( + test_case.expected_message, + Counter(), + ) @pytest.mark.parametrize( @@ -411,5 +499,71 @@ def test_given_unanalysed_pivot_model_when_assembling_then_native_proves_it_with ) +@pytest.mark.parametrize( + "test_case", + [ + AdapterRuleCallbackTestCase( + description="the adapter's own rule answers natively analysed CTE nullability", + seed=20261012, + model_count=6, + raised=None, + expected_minimum_calls=1, + ), + ], + ids=lambda case: case.description, +) +def test_given_adapter_nullability_rule_when_analysing_natively_then_rule_is_called_back( + test_case: AdapterRuleCallbackTestCase, tmp_path: Path, monkeypatch: pytest.MonkeyPatch +) -> None: + rule: RecordingNullabilityRule = RecordingNullabilityRule(raised=test_case.raised) + request: NativeModelAnalysisRequest = adapter_rule_request( + test_case=test_case, rule=rule, tmp_path=tmp_path, monkeypatch=monkeypatch + ) + record_dir: Path = tmp_path / "records" + monkeypatch.setenv(ANALYSIS_RECORD_DIR_ENV_VAR, str(record_dir)) + + assert analyze_native_model_sql(request=request).analyses + assert len(rule.calls) >= test_case.expected_minimum_calls, test_case.description + assert all( + isinstance(value, InferredNullability) + for value in itertools.chain.from_iterable(rule.calls) + ) + assert deferral_kinds(record_dir) == Counter( + {"analysis_session:adapter_nullability_callback": 1} + ), test_case.description + + +@pytest.mark.parametrize( + "test_case", + [ + AdapterRuleCallbackTestCase( + description="the adapter rule's exception reaches the caller unchanged", + seed=20261012, + model_count=6, + raised=LookupError, + expected_minimum_calls=1, + ), + ], + ids=lambda case: case.description, +) +def test_given_failing_adapter_nullability_rule_when_analysing_natively_then_its_error_raises( + test_case: AdapterRuleCallbackTestCase, tmp_path: Path, monkeypatch: pytest.MonkeyPatch +) -> None: + rule: RecordingNullabilityRule = RecordingNullabilityRule(raised=test_case.raised) + request: NativeModelAnalysisRequest = adapter_rule_request( + test_case=test_case, rule=rule, tmp_path=tmp_path, monkeypatch=monkeypatch + ) + record_dir: Path = tmp_path / "records" + monkeypatch.setenv(ANALYSIS_RECORD_DIR_ENV_VAR, str(record_dir)) + + with pytest.raises(LookupError, match="adapter rule failed"): + _ = analyze_native_model_sql(request=request) + + assert len(rule.calls) >= test_case.expected_minimum_calls, test_case.description + assert deferral_kinds(record_dir) == Counter( + {"analysis_session:adapter_nullability_callback": 1} + ), test_case.description + + if __name__ == "__main__": pytest.main([__file__, "-vv"]) diff --git a/tests/integration/src/sqlbuild/compiler/analysis_session/test_native_projection_facts.py b/tests/integration/src/sqlbuild/compiler/analysis_session/test_native_projection_facts.py new file mode 100644 index 0000000000..31c31a7c47 --- /dev/null +++ b/tests/integration/src/sqlbuild/compiler/analysis_session/test_native_projection_facts.py @@ -0,0 +1,73 @@ +"""Fixture projection facts match Python's `_simple_projection_facts` recorded in a golden.""" + +from __future__ import annotations + +import pytest + +import sqlbuild._native as native_module +from tests.integration.src.sqlbuild.compiler.analysis_session._test_types import ( + ProjectionFactsTestCase, +) +from tests.integration.src.sqlbuild.compiler.analysis_session.helpers import projection_view +from tests.integration.src.sqlbuild.compiler.helpers import ( + GoldenEntry, + golden_differences, + golden_entry, + golden_name, + read_golden, +) + + +@pytest.mark.parametrize( + "test_case", + [ + ProjectionFactsTestCase( + description="fixture projection edges", + queries=( + ("SELECT 'a' AS name, 1 AS qty, TRUE AS flag, NULL AS missing", "duckdb"), + ( + "SELECT ARRAY_CONSTRUCT(1, 2) AS items, OBJECT_CONSTRUCT('a', 1) AS obj, PARSE_JSON('{}') AS doc, [1, 2] AS arr", + "snowflake", + ), + ('SELECT NULL AS "Quoted", \'x\' AS "Größe", 2 AS STRASSE', "duckdb"), + ( + "WITH base AS (SELECT NULL AS gone, 'v' AS kept) SELECT gone, kept FROM base", + "duckdb", + ), + ("SELECT * FROM (SELECT NULL AS inner_null, 1.5 AS ratio) AS t", "duckdb"), + ("SELECT 'a' AS x UNION ALL SELECT NULL AS x", "duckdb"), + ("SELECT lower('A') AS lowered, CAST(1 AS INT) AS cast_one, 'ß' AS ß", "duckdb"), + ("SELECT 1 AS a, 'dup' AS a", "generic"), + ("SELECT parse_json('[1]') AS p, STRUCT_PACK(a := 1) AS s", "duckdb"), + ("SELECT ( AS broken", "duckdb"), + ("SELECT 1 AS one; SELECT 2 AS two", "duckdb"), + ("SELECT {'a': 1} AS st, NULL AS n", "duckdb"), + ("INSERT INTO t SELECT NULL AS n, 'a' AS s", "duckdb"), + ('SELECT \'é\' AS "ÉTÉ", null AS "İ"', "bigquery"), + ("SELECT 1 AS id", "postgres"), + ("SELECT 'a' AS k", "tsql"), + ), + expected_differences=[], + ) + ], + ids=lambda case: case.description, +) +def test_given_fixture_queries_when_reading_projection_facts_then_matches_python_golden( + test_case: ProjectionFactsTestCase, +) -> None: + views: list[tuple[dict[str, str], frozenset[str], frozenset[str]]] = [ + projection_view(native_module.fixture_projection_facts(sql, dialect)) + for sql, dialect in test_case.queries + ] + expected: list[GoldenEntry] = read_golden( + golden_name("projection_facts", test_case.description) + ) + + assert ( + golden_differences(expected, [golden_entry("projection_facts", view) for view in views]) + == test_case.expected_differences + ) + + +if __name__ == "__main__": + pytest.main([__file__, "-vv"]) diff --git a/tests/integration/src/sqlbuild/compiler/analysis_session/test_native_query_columns.py b/tests/integration/src/sqlbuild/compiler/analysis_session/test_native_query_columns.py new file mode 100644 index 0000000000..435209c048 --- /dev/null +++ b/tests/integration/src/sqlbuild/compiler/analysis_session/test_native_query_columns.py @@ -0,0 +1,181 @@ +"""Column inference outside the analysis session: models native analysis cannot project and +table-function bodies keep the columns Python's parsed-tree inference gave them. + +Expected outputs recorded from the pre-port Python `infer_columns_with_sql_analysis`. +""" + +from __future__ import annotations + +import re +from pathlib import Path + +import pytest + +import sqlbuild._native as native_module +import sqlbuild.compiler.compile._helpers.assembly.project as project_assembly +from sqlbuild.adapter.contract.models import ExpressionInferenceProfile +from sqlbuild.compiler.analysis_session.main._infer_native_query_columns import ( + infer_native_query_columns, +) +from sqlbuild.compiler.analysis_session.models import NativeColumnQuery +from sqlbuild.compiler.compile.exceptions import CompileInputError +from sqlbuild.compiler.compile.models import CompiledModel, CompiledProject +from tests.integration.src.sqlbuild.compiler.analysis_session._test_types import ( + FallbackColumnsTestCase, + MissingSessionAnalysisTestCase, + NormalizationRejectionTestCase, + TableFunctionColumnsTestCase, +) +from tests.integration.src.sqlbuild.compiler.lineage.helpers import compiled_project + +_PROJECT: str = 'name = "orders"\nadapter = "duckdb"\n[rules]\nselect = []\n' +_HEADER: str = "MODEL (description 'Test model.', materialized view);\n" + + +@pytest.mark.parametrize( + "test_case", + [ + FallbackColumnsTestCase( + description="CREATE TABLE AS takes its inner select's columns", + query_sql="CREATE TABLE t AS SELECT 1 AS a", + expected_columns=(("a", None, "non_null"),), + ), + FallbackColumnsTestCase( + description="INSERT ... SELECT takes its select's columns", + query_sql="INSERT INTO t SELECT 1 AS a", + expected_columns=(("a", None, "non_null"),), + ), + FallbackColumnsTestCase( + description="calls nested 200 deep", + query_sql="SELECT " + "f(" * 200 + "1" + ")" * 200 + " AS deep", + expected_columns=(("deep", None, "unknown"),), + ), + ], + ids=lambda case: case.description, +) +def test_given_unprojectable_model_when_compiling_then_parsed_tree_columns_are_kept( + test_case: FallbackColumnsTestCase, tmp_path: Path +) -> None: + project: CompiledProject = compiled_project( + project_dir=tmp_path, + files={ + "sqlbuild_project.toml": _PROJECT, + "models/orders.sql": _HEADER + test_case.query_sql, + }, + ) + model: CompiledModel = project.models[0] + + assert model.inferred_columns is not None + assert ( + tuple( + (column.name, column.type, column.nullability.value) + for column in model.inferred_columns + ) + == test_case.expected_columns + ) + + +@pytest.mark.parametrize( + "test_case", + [ + TableFunctionColumnsTestCase( + description="matching return columns", + returns="table (id INTEGER, label VARCHAR)", + body_sql="SELECT x AS id, 'a' AS label", + expected_error=None, + ), + TableFunctionColumnsTestCase( + description="fewer body columns than declared", + returns="table (id INTEGER, label VARCHAR)", + body_sql="SELECT x AS id", + expected_error=( + "SQL table function functions/sql/table_fn__orders.sql declares 2 return " + "columns but its query produces 1" + ), + ), + ], + ids=lambda case: case.description, +) +def test_given_table_function_when_compiling_then_body_columns_match_declaration( + test_case: TableFunctionColumnsTestCase, tmp_path: Path +) -> None: + files: dict[str, str] = { + "sqlbuild_project.toml": _PROJECT, + "functions/sql/table_fn__orders.sql": ( + "FUNCTION (description 'Test function.', arguments (x INTEGER), " + f"returns {test_case.returns}); {test_case.body_sql}" + ), + } + error: str | None = None + try: + _ = compiled_project(project_dir=tmp_path, files=files) + except CompileInputError as raised: + error = str(raised) + + assert error == test_case.expected_error + + +@pytest.mark.parametrize( + "test_case", + [ + MissingSessionAnalysisTestCase( + description="a requested model the session left unanalysed", + expected_message=( + "NativeCompilerError: native model analysis: the session returned no analysis " + "for model 'orders'" + ), + ) + ], + ids=lambda case: case.description, +) +def test_given_session_without_model_analysis_when_assembling_then_raises_native_compiler_error( + test_case: MissingSessionAnalysisTestCase, tmp_path: Path, monkeypatch: pytest.MonkeyPatch +) -> None: + monkeypatch.setattr(project_assembly, "analyze_model_sql", lambda _request: ({}, None)) + + with pytest.raises(native_module.NativeCompilerError) as raised: + _ = compiled_project( + project_dir=tmp_path, + files={ + "sqlbuild_project.toml": _PROJECT, + "models/orders.sql": _HEADER + "SELECT 1 AS a", + }, + ) + + assert str(raised.value) == test_case.expected_message + + +@pytest.mark.parametrize( + "test_case", + [ + NormalizationRejectionTestCase( + description="a parse query whose table-function call never closes", + queries=(("SELECT 1 AS a", "parse"), ('SELECT * FROM __table_fn("f")(1', "parse")), + dialect="duckdb", + expected_message="invalid table-function analysis input: Parenthesis", + ), + NormalizationRejectionTestCase( + description="a legacy query whose table-function argument quote never closes", + queries=(('SELECT * FROM __table_fn("f")(\'x)', "legacy"),), + dialect="motherduck", + expected_message="invalid table-function analysis input: Quote", + ), + ], + ids=lambda case: case.description, +) +def test_given_sql_normalization_rejects_when_inferring_columns_then_python_value_error_raises( + test_case: NormalizationRejectionTestCase, +) -> None: + queries: tuple[NativeColumnQuery, ...] = tuple( + NativeColumnQuery(sql=sql, mode=mode) for sql, mode in test_case.queries + ) + + with pytest.raises(ValueError, match=re.escape(test_case.expected_message)): + _ = infer_native_query_columns( + queries=queries, + profile=ExpressionInferenceProfile(sql_analysis_dialect=test_case.dialect), + ) + + +if __name__ == "__main__": + pytest.main([__file__, "-vv"]) diff --git a/tests/integration/src/sqlbuild/compiler/analysis_session/test_shared_query_outputs.py b/tests/integration/src/sqlbuild/compiler/analysis_session/test_shared_query_outputs.py new file mode 100644 index 0000000000..ec666691b3 --- /dev/null +++ b/tests/integration/src/sqlbuild/compiler/analysis_session/test_shared_query_outputs.py @@ -0,0 +1,195 @@ +"""Models whose analysis queries are equal in shape keep their own diagnostics and lineage. + +Explicit expected outputs carried over from the deleted Python shared-binding tests. +""" + +from __future__ import annotations + +import json +from pathlib import Path +from typing import Any + +import pytest + +from sqlbuild.cli.commands.main.entrypoint.entry import main +from tests.integration.src.sqlbuild.compiler.analysis_session._test_types import ( + SharedQueryOutputTestCase, +) +from tests.integration.src.sqlbuild.compiler.analysis_session.helpers import ( + upstream_lineage_sources, + write_shared_query_project, +) + +_UPSTREAM_SQL: str = ( + "MODEL (description 'Test model.', materialized view); SELECT 1 AS id, 2.5 AS amount" +) +_HEADER: str = 'MODEL (description "Test model.", materialized view); ' +_STUB_CTE: str = ( + "MODEL (description 'Test model.', materialized view); WITH {name} AS " + '(SELECT CAST(2 AS VARCHAR) AS id) SELECT id FROM __ref("{upstream}")' +) +_MISSING: str = _HEADER + 'SELECT id FROM __ref("{upstream}") WHERE missing > 0' + + +@pytest.mark.parametrize( + "test_case", + [ + SharedQueryOutputTestCase( + description="identical shapes over different inputs", + models={ + "orders_summary": _HEADER + 'SELECT id, amount FROM __ref("orders")', + "customers_summary": _HEADER + 'SELECT id, amount FROM __ref("customers")', + }, + expected_lineage=( + ("orders_summary.id", "orders", "rich"), + ("customers_summary.id", "customers", "rich"), + ("orders_summary.amount", "orders", "fast"), + ("customers_summary.amount", "customers", "fast"), + ), + ), + SharedQueryOutputTestCase( + description="a relation name used as a qualifier", + models={ + "orders_summary": _HEADER + 'SELECT orders.id FROM __ref("orders") AS orders', + "customers_summary": ( + _HEADER + 'SELECT customers.id FROM __ref("customers") AS customers' + ), + }, + expected_lineage=( + ("orders_summary.id", "orders", "rich"), + ("customers_summary.id", "customers", "rich"), + ), + ), + SharedQueryOutputTestCase( + description="an authored lowercase stub-named CTE", + models={ + "orders_summary": _STUB_CTE.format( + name="__sqlbuild_project_input_0", upstream="orders" + ), + "customers_summary": _STUB_CTE.format( + name="__sqlbuild_project_input_0", upstream="customers" + ), + "next_orders": _HEADER + 'SELECT id + 1 AS next_id FROM __ref("orders_summary")', + }, + expected_lineage=( + ("orders_summary.id", "orders", "rich"), + ("customers_summary.id", "customers", "rich"), + ), + ), + SharedQueryOutputTestCase( + description="an authored uppercase stub-named CTE", + models={ + "orders_summary": _STUB_CTE.format( + name="__SQLBUILD_PROJECT_INPUT_0", upstream="orders" + ), + "customers_summary": _STUB_CTE.format( + name="__SQLBUILD_PROJECT_INPUT_0", upstream="customers" + ), + "next_orders": _HEADER + 'SELECT id + 1 AS next_id FROM __ref("orders_summary")', + }, + expected_lineage=( + ("orders_summary.id", "orders", "rich"), + ("customers_summary.id", "customers", "rich"), + ), + ), + SharedQueryOutputTestCase( + description="later-wave members of equal shape", + models={ + "orders_summary": _HEADER + 'SELECT id, amount FROM __ref("orders")', + "customers_summary": _HEADER + 'SELECT id, amount FROM __ref("customers")', + "orders_rollup": _HEADER + 'SELECT id, amount FROM __ref("orders_summary")', + "customers_rollup": (_HEADER + 'SELECT id, amount FROM __ref("customers_summary")'), + }, + expected_lineage=( + ("orders_rollup.amount", "orders_summary", "rich"), + ("customers_rollup.amount", "customers_summary", "rich"), + ), + ), + ], + ids=lambda case: case.description, +) +def test_given_equal_shapes_when_compiling_then_each_model_keeps_its_own_lineage( + test_case: SharedQueryOutputTestCase, + tmp_path: Path, + capsys: pytest.CaptureFixture[str], +) -> None: + write_shared_query_project( + project_dir=tmp_path, models=test_case.models, upstream_sql=_UPSTREAM_SQL + ) + + compiled: int = main(["--project-dir", str(tmp_path), "compile", "--json", "--no-cache"]) + diagnostics: list[object] = json.loads(capsys.readouterr().out)["diagnostics"] + traces: list[tuple[int, list[str]]] = [ + upstream_lineage_sources(project_dir=tmp_path, column=column, mode=mode, capsys=capsys) + for column, _, mode in test_case.expected_lineage + ] + + assert (compiled, diagnostics) == (0, []) + assert traces == [(0, [upstream]) for _, upstream, _ in test_case.expected_lineage] + + +@pytest.mark.parametrize( + "test_case", + [ + SharedQueryOutputTestCase( + description="findings after the relation", + models={ + "orders_summary": _MISSING.format(upstream="orders"), + "customers_summary": _MISSING.format(upstream="customers"), + }, + expected_findings=(("orders_summary", "orders"), ("customers_summary", "customers")), + ), + SharedQueryOutputTestCase( + description="a later-wave member of a group with findings", + models={ + "orders_summary": _MISSING.format(upstream="orders"), + "customers_summary": _MISSING.format(upstream="customers"), + "orders_mid": _HEADER + 'SELECT id, amount FROM __ref("orders")', + "orders_late": _MISSING.format(upstream="orders_mid"), + }, + expected_findings=( + ("orders_summary", "orders"), + ("customers_summary", "customers"), + ("orders_late", "orders_mid"), + ), + ), + ], + ids=lambda case: case.description, +) +def test_given_equal_shapes_with_findings_when_compiling_then_reports_each_model_exactly( + test_case: SharedQueryOutputTestCase, + tmp_path: Path, + capsys: pytest.CaptureFixture[str], +) -> None: + write_shared_query_project( + project_dir=tmp_path, models=test_case.models, upstream_sql=_UPSTREAM_SQL + ) + + compiled: int = main(["--project-dir", str(tmp_path), "compile", "--json", "--no-cache"]) + diagnostics: list[dict[str, Any]] = json.loads(capsys.readouterr().out)["diagnostics"] + findings: list[tuple[str, str, str, int, int]] = sorted( + ( + diagnostic["resource_name"], + diagnostic["code"], + diagnostic["message"], + diagnostic["location"]["column"], + diagnostic["location"]["end_column"], + ) + for diagnostic in diagnostics + ) + + assert compiled == 1 + assert findings == sorted( + ( + model, + "B002", + f"Unknown column 'missing' in {upstream}", + test_case.models[model].index("missing") + 1, + test_case.models[model].index("missing") + 1 + len("missing"), + ) + for model, upstream in test_case.expected_findings + ) + + +if __name__ == "__main__": + pytest.main([__file__, "-vv"]) diff --git a/tests/integration/src/sqlbuild/compiler/attachments/_test_types.py b/tests/integration/src/sqlbuild/compiler/attachments/_test_types.py index b63bbf4e49..3ee6f94f54 100644 --- a/tests/integration/src/sqlbuild/compiler/attachments/_test_types.py +++ b/tests/integration/src/sqlbuild/compiler/attachments/_test_types.py @@ -1,24 +1,7 @@ from __future__ import annotations -import random -from collections.abc import Callable from dataclasses import dataclass -from sqlbuild.compiler.sql_analysis.models import SqlLexicalSyntax - - -@dataclass(frozen=True) -class AuthoredSqlParityTestCase: - """Seeded authored SQL expanded by the Python engine and by the preview engine.""" - - description: str - seed: int - count: int - generate: Callable[[random.Random], str] - expected_minimum_expanded: int - expected_minimum_python_errors: int - expected_minimum_exact_errors: int - @dataclass(frozen=True) class AttachedAuditParityTestCase: @@ -32,75 +15,6 @@ class AttachedAuditParityTestCase: expected_minimum_python_errors: int -@dataclass(frozen=True) -class AttachmentProjectTestCase: - """One project variant compiled to compile inputs by each engine.""" - - description: str - overrides: dict[str, str] - expected_native_entries: frozenset[str] - expected_outcome_fragment: str - - -@dataclass(frozen=True) -class ParameterParityTestCase: - """Seeded SQL test bodies whose `@param` references each engine expands.""" - - description: str - seed: int - count: int - expected_minimum_expanded: int - expected_minimum_python_errors: int - expected_minimum_exact_errors: int - - -@dataclass(frozen=True) -class OmittedSelectParityTestCase: - """Seeded test bodies completed with an omitted `SELECT 1` under one lexical syntax.""" - - description: str - seed: int - count: int - syntax: SqlLexicalSyntax - expected_minimum_completed: int - - -@dataclass(frozen=True) -class RawDirectLogicParityTestCase: - """Seeded unexpanded direct-logic test bodies extracted natively and by Python.""" - - description: str - seed: int - count: int - expected_minimum_extracted: int - expected_minimum_python_errors: int - - -@dataclass(frozen=True) -class ScenarioParityTestCase: - """Seeded scenario bodies extracted by each engine under one lexical syntax.""" - - description: str - seed: int - count: int - syntax: SqlLexicalSyntax - expected_minimum_extracted: int - expected_minimum_native: int - expected_minimum_python_errors: int - expected_minimum_native_errors: int - - -@dataclass(frozen=True) -class TargetParityTestCase: - """Seeded model test targets validated by each engine against known resources.""" - - description: str - seed: int - count: int - expected_minimum_valid: int - expected_minimum_python_errors: int - - @dataclass(frozen=True) class BodyCallParityTestCase: """Seeded helper bodies whose call reading the native extractor shares with a Python scanner.""" diff --git a/tests/integration/src/sqlbuild/compiler/attachments/helpers.py b/tests/integration/src/sqlbuild/compiler/attachments/helpers.py index 211c1de33f..5f00772f85 100644 --- a/tests/integration/src/sqlbuild/compiler/attachments/helpers.py +++ b/tests/integration/src/sqlbuild/compiler/attachments/helpers.py @@ -4,17 +4,10 @@ import random import re -from collections.abc import Callable from dataclasses import dataclass -from functools import partial from pathlib import Path from typing import cast -import orjson -import pytest - -import sqlbuild._native as _native -from sqlbuild.adapters.duckdb.classes.duckdb_adapter import DuckDbAdapter from sqlbuild.compiler.attachments.main._render_native_attached_audit import ( render_native_attached_audit, ) @@ -24,158 +17,16 @@ resolve_audit_run_scope, resolve_audit_severity, ) -from sqlbuild.compiler.compile._helpers.attachment.sql_tests import ( - build_test_inputs, - validate_test_ctes, -) from sqlbuild.compiler.compile._helpers.refs.references import scan_sql_reference_calls -from sqlbuild.compiler.compile._helpers.render import macros from sqlbuild.compiler.compile._helpers.render.arguments import render_parameterized_sql from sqlbuild.compiler.compile._helpers.render.macros import find_macro_call_names -from sqlbuild.compiler.compile._helpers.render.parameters import expand_test_parameters -from sqlbuild.compiler.compile._helpers.render.sql_vars import expand_authored_sql_result -from sqlbuild.compiler.compile._helpers.scenarios.core import extract_sql_scenario_ctes -from sqlbuild.compiler.compile._helpers.sql_tests.core import complete_omitted_ceremonial_select from sqlbuild.compiler.compile._helpers.sql_tests.native import extract_unexpanded_sql_test from sqlbuild.compiler.compile.exceptions import CompileInputError -from sqlbuild.compiler.compile.main._build_compile_inputs import build_compile_inputs from sqlbuild.compiler.compile.models import ( - AuthoredSqlExpansionResult, - CompileAdapterContext, - CompileModelSqlTestCtes, - CompileProjectInputs, - CompileSqlTestCtes, - DeclarationExpansionContext, - DeclarationResolutionContext, - LoadedMacro, - MacroContext, SqlReferenceScan, ) from sqlbuild.compiler.compile.types import SqlTestMode -from sqlbuild.compiler.discovery.main.discover import discover_project_inputs -from sqlbuild.compiler.discovery.models import ( - DiscoveredProjectInputs, - DiscoveredSqlTestBlock, - DiscoveredSqlTestFile, -) -from sqlbuild.compiler.frontier.constants import COMPILER_ENGINE_ENV_VAR -from sqlbuild.compiler.frontier.main._compile_frontier import compile_frontier -from sqlbuild.compiler.frontier.types import CompilerEngine, CompilerStage from sqlbuild.compiler.sql_analysis.models import SqlLexicalSyntax -from sqlbuild.spec.contracts.main.resolve_effective_collection_rendering import ( - resolve_effective_collection_rendering, -) -from sqlbuild.spec.contracts.models import ( - LocalConfig, - ProjectConfig, -) -from sqlbuild.sql_values.main.normalize import normalize_sql_value -from sqlbuild.sql_values.models import SqlValue -from sqlbuild.sql_values.types import CollectionRendering -from tests.integration.src.sqlbuild.compiler.model_loop.helpers import ( - DECLARATIONS, - generated_reference_sql, -) - -EFFECTIVE_VARS: dict[str, object] = { - "region": "north", - "limit_rows": 10, - "ratio": 0.5, - "enabled": True, - "unset": None, - "regions": ["north", "south"], -} -_VARIABLE_TOKENS: tuple[str, ...] = ( - "@@region", - "@@limit_rows ", - "'@@region'", - "@@ratio", - "@@enabled", - "@@unset", - "@@@window_start", - "@@ENV:SQB_ORDERS_REGION", - "@@ENV:SQB_MISSING_REGION", - "@@regions", - "@@missing", - "@@CTX:run.target", - "-- @@missing\n", -) -_MACRO_CONTEXT: MacroContext = MacroContext( - adapter_name="duckdb", sql_analysis_enabled=True, target_name="dev" -) - - -def generated_authored_sql(*, rng: random.Random) -> str: - """Return SQL mixing project variables with enum and constant references.""" - - parts: list[str] = [ - generated_reference_sql(rng=rng), - *rng.choices(_VARIABLE_TOKENS, k=rng.randint(0, 3)), - ] - rng.shuffle(parts) - return " ".join(parts) - - -_DOLLAR_PIECES: tuple[str, ...] = ( - "$", - "$$", - "$t$", - "$tag$", - "a$", - "$1", - "$1$", - "--", - "/*", - "*/", - "'", - "\n", - " ", - "@@region", - "@@limit_rows", - "@@missing", - "@@ENV:SQB_ORDERS_REGION", - '@const("sales_cap")', - '@enum("order_status").PLACED', - "`", - "``", - "`@@missing``", - "`@@regions``", - "`@@CTX:run.target``", -) - - -def generated_dollar_authored_sql(*, rng: random.Random) -> str: - """Return SQL dense in dollar quotes around variables, enum and constant references.""" - - parts: list[str] = [ - generated_reference_sql(rng=rng), - *rng.choices(_DOLLAR_PIECES, k=rng.randint(1, 10)), - ] - rng.shuffle(parts) - return "".join(parts) - - -def authored_outcome( - *, sql: str, engine: CompilerEngine, monkeypatch: pytest.MonkeyPatch -) -> AuthoredSqlExpansionResult | str: - """Expand one string under `engine`, returning the result or Python's error text.""" - - monkeypatch.setenv(COMPILER_ENGINE_ENV_VAR, engine.value) - monkeypatch.setenv("SQB_ORDERS_REGION", "south") - try: - return expand_authored_sql_result( - sql=sql, - file_path=Path("audits/orders.sql"), - effective_vars=EFFECTIVE_VARS, - loaded_macros={}, - macro_context=_MACRO_CONTEXT, - value_renderer=DuckDbAdapter(), - collection_rendering=CollectionRendering.VALUE_LIST, - declarations=DECLARATIONS, - ) - except CompileInputError as error: - return str(error) - _SQL_PIECES: tuple[str, ...] = ( "SELECT * FROM t WHERE ", @@ -357,559 +208,6 @@ def _python_rendering(audit: GeneratedAudit) -> tuple[object, ...] | str: return (*rendered, severity, run_scope) -NATIVE_ATTACHMENT_ENTRIES: tuple[str, ...] = ( - "scan_test_parameter_references", - "omitted_ceremonial_select", - "extract_sql_scenario_json", - "SqlTestTargetCatalog", - "pair_seed_files", - "render_attached_generic_audit", - "expand_config_templates", - "interpolate_sql_batch", - "scan_sql_declaration_references", -) -_MISSING_ENV: str = "SQB_ATTACHMENTS_UNSET" -ATTACHMENT_PROJECT: dict[str, str] = { - "sqlbuild_project.toml": ( - 'name = "orders"\nadapter = "duckdb"\ndefault_target = "dev"\n\n' - '[vars]\nregion = "north"\n\n' - '[connections.local]\ndatabase = "orders.duckdb"\n\n' - '[targets.dev]\nconnection = "local"\nschema = "dev"\n' - ), - "macros/labels.py": ( - "def tidy_label(expression: str) -> str:\n" - ' """Trim and lower-case a label."""\n' - ' return f"LOWER(TRIM({expression}))"\n' - ), - "seeds/channel_codes.csv": "id,label\n1,web\n2,store\n", - "seeds/channel_codes.yml": ( - "seeds:\n - name: channel_codes\n description: Channel codes.\n columns:\n" - " - name: id\n type: INTEGER\n audits:\n - not_null\n" - " - name: label\n type: VARCHAR\n" - ), - "seeds/product_codes.csv": "id\n1\n", - "seeds/product_codes.yml": ( - "seeds:\n - name: product_codes\n columns:\n - name: id\n type: INTEGER\n" - ), - "sources/events.yml": ( - "sources:\n - name: order_events\n" - f" description: \"Order feed ${{coalesce(ENV:{_MISSING_ENV}, 'events')}}\"\n" - " expression: \"(SELECT 1 AS id, @tidy_label('@@region') AS region, " - '$$--@@region /* $$ AS note)"\n' - " columns:\n - name: id\n type: INTEGER\n audits:\n" - " - accepted_values:\n values: [1, 2]\n" - " - name: region\n type: VARCHAR\n" - ), - "functions/sql/order_label.sql": ( - 'FUNCTION (\n description "Label an order status.",\n' - f" schema \"${{coalesce(ENV:{_MISSING_ENV}, 'udfs')}}\",\n" - " arguments (raw_status STRING),\n returns STRING,\n);\n\n" - 'UPPER(@tidy_label("raw_status"))\n' - ), - "audits/generic/amount_floor.sql": ( - 'AUDIT ();\n\nSELECT *\nFROM __ref("@model")\nWHERE @column < @minimum ' - "AND @tidy_label(\"label\") <> @'label' AND $tag$--@@region$tag$ <> @'label'\n" - ), - "models/orders.sql": ( - 'MODEL (\n materialized table,\n description "Orders.",\n' - ' audits [amount_floor (column amount, minimum -5, label "it\'s", severity warn)],\n' - ");\n\nSELECT c.id, 1.5 AS amount, c.label\n" - 'FROM __seed("channel_codes") c\nJOIN __source("order_events") e ON e.id = c.id\n' - ), - "tests/unit/test_orders.sql": ( - "TEST();\n\nWITH\n__seed__channel_codes AS (\n" - " SELECT 1 AS id, @tidy_label(\"' Web '\") AS label, $$ /* $$ AS note, " - "'@@region' AS region -- */\n),\n" - "__source__order_events AS (\n SELECT 1 AS id, 'north' AS region\n),\n" - "__expected__orders AS (\n SELECT 1 AS id, 1.5 AS amount, 'web' AS label\n)\n" - "SELECT 1\n" - ), - "tests/unit/test_orders_cases.sql": ( - 'TEST (\n name "orders_keep_region",\n parameters (\n region_value string,\n ),\n' - ' cases (\n north (region_value "north"),\n' - ' quoted (region_value "it\'s"),\n ),\n);\n\n' - "WITH\n__seed__channel_codes AS (SELECT 1 AS id, 'web' AS label),\n" - '__source__order_events AS (SELECT 1 AS id, @param("region_value") AS region),\n' - "__expected__orders AS (SELECT 1 AS id, 1.5 AS amount, 'web' AS label);\n" - ), - "tests/unit/test_tidy_label.sql": ( - 'TEST (mode macro, name "tidies_labels");\n\n' - "WITH\ninput_values AS (SELECT ' Web ' AS label),\n" - '__macro_actual__ AS (SELECT @tidy_label("label") AS label FROM input_values),\n' - "__macro_expected__ AS (SELECT 'web' AS label)\nSELECT 1\n" - ), - "tests/scenarios/orders_scenario.sql": ( - 'SCENARIO (\n description "Orders join their channel"\n);\n\n' - "WITH\n__seed__channel_codes AS (\n SELECT 1 AS id, @tidy_label(\"'Web'\") AS label\n),\n" - "__source__order_events AS (\n SELECT 1 AS id, 'north' AS region\n),\n" - "__expected__orders AS (\n SELECT 1 AS id, 1.5 AS amount, 'web' AS label\n)\n" - "SELECT 1\n" - ), -} - - -def attachment_engine_outcome( - *, - project_dir: Path, - engine: CompilerEngine, - overrides: dict[str, str], - monkeypatch: pytest.MonkeyPatch, -) -> tuple[frozenset[str], str]: - """Build compile inputs under `engine`; return the native entries called and the outcome.""" - - for relative_path, contents in {**ATTACHMENT_PROJECT, **overrides}.items(): - path: Path = project_dir / relative_path - path.parent.mkdir(parents=True, exist_ok=True) - path.write_text(contents, encoding="utf-8") - called: set[str] = set() - for name in NATIVE_ATTACHMENT_ENTRIES: - monkeypatch.setattr(_native, name, _recorded(called=called, name=name)) - bridged: list[Path] = [] - monkeypatch.setattr(macros, "_bridged_sql_macros", _recorded_bridge(bridged=bridged)) - monkeypatch.setenv(COMPILER_ENGINE_ENV_VAR, engine.value) - try: - inputs: CompileProjectInputs = compile_frontier( - until=CompilerStage.COMPILE_PROJECT_INPUTS, - python_stage=partial(_compile_inputs, project_dir=project_dir), - ) - except CompileInputError as error: - return frozenset(called), f"error: {error}".replace(str(project_dir), "") - called.update(f"bridged:{str(path).replace(str(project_dir), '')}" for path in bridged) - return frozenset(called), repr( - ( - inputs.seed_inputs, - inputs.source_inputs, - inputs.sql_function_inputs, - inputs.audit_inputs, - inputs.test_inputs, - inputs.scenario_inputs, - inputs.diagnostics, - ) - ).replace(str(project_dir), "") - - -def _compile_inputs(*, project_dir: Path) -> CompileProjectInputs: - discovered: DiscoveredProjectInputs = discover_project_inputs(project_dir=project_dir) - adapter: DuckDbAdapter = DuckDbAdapter() - return build_compile_inputs( - discovered_inputs=discovered, - adapter_context=CompileAdapterContext( - value_renderer=adapter, - collection_rendering=resolve_effective_collection_rendering( - project_config=discovered.project_config, declaration_override=None - ), - python_functions_inherit_default_namespace=( - adapter.python_functions_inherit_default_namespace() - ), - sql_lexical_syntax=adapter.sql_lexical_syntax, - ), - run_id="20261008T000000Z_orders", - resolved_connection={}, - no_sql_validation=True, - defer_model_sql_validation=True, - no_cache=True, - ) - - -def _recorded_bridge(*, bridged: list[Path]) -> Callable[..., object]: - entry: Callable[..., object] = cast(Callable[..., object], macros._bridged_sql_macros) - - def recorded(*, consumer_path: Path, **arguments: object) -> object: - bridged.append(consumer_path) - return entry(consumer_path=consumer_path, **arguments) - - return recorded - - -def _recorded(*, called: set[str], name: str) -> Callable[..., object]: - entry: Callable[..., object] = getattr(_native, name) - - def recorded(*args: object) -> object: - called.add(name) - return entry(*args) - - return recorded - - -_PARAMETER_PIECES: tuple[str, ...] = ( - "SELECT ", - '@param("region")', - '@param ( "limit_rows" )', - '@param(\n"region"\n)', - '@param(\u00a0"region")', - '@param("missing")', - "@param(region)", - "@params", - "@param_x", - "'@param(\"region\")'", - '"quoted"', - "`tick`", - '$$ @param("region") $$', - "$1", - '-- @param("region")\n', - '/* @param("region") */', - "'", - "/*", - "\u00e9", - ", ", -) -PARAMETER_VALUES: tuple[tuple[str, SqlValue], ...] = ( - ("region", normalize_sql_value(raw_value="north", context="region")), - ("limit_rows", normalize_sql_value(raw_value=10, context="limit_rows")), -) - - -def generated_parameter_sql(*, rng: random.Random) -> str: - """Return a test body mixing parameter references with quotes and comments.""" - - return "".join(rng.choices(_PARAMETER_PIECES, k=rng.randint(1, 8))) - - -def parameter_outcome( - *, sql: str, engine: CompilerEngine, monkeypatch: pytest.MonkeyPatch -) -> tuple[str, frozenset[str]] | str: - """Expand one body's parameters under `engine`, returning Python's error text on failure.""" - - monkeypatch.setenv(COMPILER_ENGINE_ENV_VAR, engine.value) - try: - return expand_test_parameters( - sql=sql, - file_path=Path("tests/unit/test_orders.sql"), - values=PARAMETER_VALUES, - value_renderer=DuckDbAdapter(), - test_name="orders", - case_name="north", - ) - except CompileInputError as error: - return str(error) - - -_BODY_PIECES: tuple[str, ...] = ( - "WITH ", - "with ", - "WITHIN ", - "w\u0131th ", - "__seed__orders AS (SELECT 1)", - "a AS (SELECT ')' AS x)", - "b AS (SELECT (1))", - ", ", - ")", - "(", - " SELECT 1", - ";", - "\n", - " -- done", - " # done", - " /* done */", - "/* /* nested */ */", - "'", - "'it\\'s'", - "'''tri)ple'''", - "$$)$$", - "$1", - "\u00e9", - "\v", -) - - -def generated_test_body(*, rng: random.Random) -> str: - """Return a test or scenario body around CTEs, terminators, comments and quotes.""" - - keyword: str = rng.choice(_BODY_PIECES[:4]) - ctes: str = ", ".join(rng.choices(_BODY_PIECES[4:7], k=rng.randint(1, 3))) - return keyword + ctes + "".join(rng.choices(_BODY_PIECES, k=rng.randint(0, 3))) - - -def completed_body( - *, - sql: str, - syntax: SqlLexicalSyntax, - engine: CompilerEngine, - monkeypatch: pytest.MonkeyPatch, -) -> str: - """Complete one body's omitted `SELECT 1` under `engine`.""" - - monkeypatch.setenv(COMPILER_ENGINE_ENV_VAR, engine.value) - return complete_omitted_ceremonial_select(sql=sql, syntax=syntax) - - -_RAW_MODE_CTES: dict[SqlTestMode, tuple[str, str]] = { - SqlTestMode.MACRO: ("__macro_actual__", "__macro_expected__"), - SqlTestMode.UDF: ("__udf_actual__", "__udf_expected__"), - SqlTestMode.TABLE_FN: ("__table_fn_actual__", "__table_fn_expected__"), -} -_RAW_CALLS: tuple[str, ...] = ( - "", - "@tidy_label(1)", - "@MY_MACRO(1)", - '__udf("order_label")', - '__udf ("order_label")', - "__udf('order_label')", - '__udf("order_label", 1)', - '__table_fn("order_rows")', - "'__udf(\"order_label\")'", - '-- __udf("order_label")\n', - "/* @tidy_label(1) */", - '$$__udf("order_label")$$', - "@m()", - "@@region", - '__ref("orders")', - '__source("events", "orders")', - '__udf("\u00e9")', - '`__udf("order_label")`', - '__udf\u00a0("order_label")', - '\u00e9__udf("order_label")', -) -_RAW_CTE_NAMES: tuple[str, ...] = ( - "helper", - "a\u00e9", - '"quoted"', - "`ticked`", - "a$b", - "__ref__orders", - "__expected__orders", - "__macro__tidy", - "__udf_actual__", - "__udf_expected__", - "__macro_expected__", - "__table_fn_expected__", - "HELPER", - "\u0131", - "\u017f", -) -_RAW_TAILS: tuple[str, ...] = ("", " FROM helper", " -- c", " UNION ALL SELECT 2", ", 'x' AS b") - - -def _raw_body(rng: random.Random) -> str: - call: str = rng.choice(("1", "1", "1", "1", *_RAW_CALLS)) - projection: str = rng.choice((f"SELECT {call} AS a", f"SELECT {call} AS a", f"SELECT {call}")) - return projection + rng.choice(("", "", "", *_RAW_TAILS)) - - -def generated_raw_direct_logic_test(*, rng: random.Random) -> tuple[str, SqlTestMode]: - """Return one unexpanded direct-logic test with the shapes Python and native read apart.""" - - mode: SqlTestMode = rng.choice(tuple(_RAW_MODE_CTES)) - actual, expected = _RAW_MODE_CTES[mode] - ctes: list[tuple[str, str]] = [ - (actual, _raw_body(rng)), - (expected, _raw_body(rng)), - *((rng.choice(_RAW_CTE_NAMES), _raw_body(rng)) for _ in range(rng.choice((0, 0, 1, 2)))), - ] - rng.shuffle(ctes) - body: str = ", ".join(f"{name} AS ({sql})" for name, sql in ctes) - return f"WITH {body}" + rng.choice(("", "", " SELECT 1", ";")), mode - - -def raw_extraction_accepts(*, sql: str, mode: SqlTestMode) -> bool: - """Whether the raw direct-logic pass accepts `sql` before expansion.""" - - try: - _ = extract_unexpanded_sql_test( - sql=sql, - file_label="tests/unit/test_logic.sql", - syntax=DuckDbAdapter().sql_lexical_syntax, - mode=mode, - ) - except CompileInputError: - return False - return True - - -def raw_test_compile_outcome( - *, sql: str, mode: SqlTestMode, engine: CompilerEngine, monkeypatch: pytest.MonkeyPatch -) -> str: - """Build one unexpanded direct-logic test's input under `engine`, or Python's error text.""" - - monkeypatch.setenv(COMPILER_ENGINE_ENV_VAR, engine.value) - adapter: DuckDbAdapter = DuckDbAdapter() - try: - return repr( - build_test_inputs( - discovered_inputs=DiscoveredProjectInputs( - project_config=ProjectConfig(name="orders", adapter="duckdb"), - local_config=LocalConfig(), - test_files=( - DiscoveredSqlTestFile( - file_path=Path("/project/tests/unit/test_logic.sql"), - relative_path=Path("tests/unit/test_logic.sql"), - contents=sql, - blocks=( - DiscoveredSqlTestBlock( - test_index=0, header_values={}, sql_body=sql, mode=mode - ), - ), - ), - ), - ), - effective_vars={"region": "north"}, - macro_context=_MACRO_CONTEXT, - loaded_macros={}, - declaration_expansion=DeclarationExpansionContext( - declarations=DeclarationResolutionContext(), - value_renderer=adapter, - collection_rendering=CollectionRendering.VALUE_LIST, - ), - sql_lexical_syntax=adapter.sql_lexical_syntax, - ) - ) - except CompileInputError as error: - return f"error: {error}" - - -_SCENARIO_CTES: tuple[str, ...] = ( - "__source__raw_orders AS (SELECT 1 AS id, 'placed' AS status)", - "__ref__customers AS (SELECT 1 AS id)", - "__seed__channel_codes AS (SELECT 1 AS id, 'web' AS label)", - "__dbt_ref__legacy__orders AS (SELECT 1 AS id)", - "__table_fn__order_rows AS (SELECT 1 AS id)", - "helper AS (SELECT id FROM __source__raw_orders)", - "__expected__orders AS (SELECT 1 AS id)", - "__expected__orders_view AS (SELECT id FROM helper)", - "__assert__positive AS (SELECT id FROM helper WHERE id < 0)", - "__assert__matches AS (SELECT * FROM __expected__orders)", - "__expected__nested AS (WITH __assert__inner AS (SELECT 1) SELECT 1 AS id)", - "__macro__tidy AS (SELECT 'x')", - '"__source__quoted" AS (SELECT 1)', - "__expected__ AS (SELECT 1)", - "__source__raw_orders AS (SELECT 2 AS id)", - "notes AS (SELECT 'caf\u00e9 -- )' AS note /* ) */)", - "dollar AS (SELECT $$ ) $$ AS note)", - "hashed AS (SELECT 1 # )\n)", -) -_SCENARIO_ERROR_CTES: tuple[str, ...] = ( - "__ref__ AS (SELECT 1)", - "__seed__ AS (SELECT 1)", - "__dbt_ref__ AS (SELECT 1)", - "__assert__ AS (SELECT 1)", - "missing_as (SELECT 1)", - "no_body AS SELECT 1", - "columns (id, label) AS (SELECT 1, 'x')", - "unclosed AS (SELECT (1)", - "open_quote AS (SELECT 'x)", - "/* open AS (SELECT 1)", - "__assert__reads_expected AS (SELECT id FROM __expected__orders_view)", - "caf\u00e9 AS (SELECT 1)", -) -_SCENARIO_ERROR_WEIGHTS: tuple[int, int] = (3, 1) -_DEFERRED_ANSWER: str = '{"deferred": true}' -_NATIVE_SCENARIO_ANSWERS: dict[frozenset[str], str] = { - frozenset({"deferred"}): "deferred", - frozenset({"independence", "scenario"}): "independence", - frozenset({"independence", "error"}): "independence", - frozenset({"error"}): "error", - frozenset({"scenario"}): "extracted", -} -_SCENARIO_TAILS: tuple[str, ...] = ("\nSELECT 1\n", "", ";", "\nSELECT 2", " -- end", ";\n") -_SCENARIO_KEYWORDS: tuple[str, ...] = ( - "WITH\n", - "with ", - "WITH RECURSIVE ", - "w\u0131th ", - "SELECT ", -) - - -def generated_scenario(*, rng: random.Random) -> str: - """Return one scenario body mixing fixtures, checks, helpers and invalid CTEs.""" - - ctes: list[str] = rng.sample(_SCENARIO_CTES, k=rng.randint(1, 5)) - errors: list[str] = rng.sample( - _SCENARIO_ERROR_CTES, k=rng.choices((0, 1), weights=_SCENARIO_ERROR_WEIGHTS)[0] - ) - mixed: list[str] = rng.sample([*ctes, *errors], k=len(ctes) + len(errors)) - return rng.choice(_SCENARIO_KEYWORDS) + ",\n".join(mixed) + rng.choice(_SCENARIO_TAILS) - - -def scenario_outcome( - *, - sql: str, - syntax: SqlLexicalSyntax, - engine: CompilerEngine, - monkeypatch: pytest.MonkeyPatch, -) -> object: - """Extract one scenario under `engine`, or return Python's error text.""" - - monkeypatch.setenv(COMPILER_ENGINE_ENV_VAR, engine.value) - try: - return extract_sql_scenario_ctes( - sql=sql, file_label="tests/scenarios/orders.sql", syntax=syntax - ) - except CompileInputError as error: - return str(error) - - -def native_scenario_answer(*, sql: str, syntax: SqlLexicalSyntax) -> str: - """How the native extraction answers: extracted, error, or the Python step it leaves.""" - - response: str | None = _native.extract_sql_scenario_json( - sql, "tests/scenarios/orders.sql", syntax.native_mapping - ) - outcome: dict[str, object] = orjson.loads(response or _DEFERRED_ANSWER) - return _NATIVE_SCENARIO_ANSWERS[frozenset(outcome)] - - -_TARGET_NAMES: tuple[str, ...] = ("orders", "customers", "channel_codes", "returns", "order_rows") -_KNOWN_NAMES: frozenset[str] = frozenset({"orders", "customers", "channel_codes", "order_rows"}) - - -def generated_test_targets( - *, rng: random.Random -) -> tuple[CompileModelSqlTestCtes, tuple[str, ...]]: - """Return one model test payload and assertion targets mixing known and unknown names.""" - - def names() -> tuple[str, ...]: - return tuple(rng.sample(_TARGET_NAMES, k=rng.choice((0, 0, 1, 1, 2)))) - - return ( - CompileModelSqlTestCtes( - macro_mocks=dict.fromkeys(names(), "'x'"), - mock_model_names=names(), - mock_source_names=names(), - mock_seed_names=names(), - mock_table_function_names=names(), - expected_model_names=names(), - ), - names(), - ) - - -def target_validation_outcome( - *, - payload: CompileModelSqlTestCtes, - assertion_targets: tuple[str, ...], - engine: CompilerEngine, - monkeypatch: pytest.MonkeyPatch, -) -> str | None: - """Validate one payload's targets under `engine`, returning Python's error text.""" - - monkeypatch.setenv(COMPILER_ENGINE_ENV_VAR, engine.value) - known: set[str] = set(_KNOWN_NAMES) - try: - validate_test_ctes( - test_ctes=CompileSqlTestCtes(mode=SqlTestMode.MODEL, payload=payload), - test_file=DiscoveredSqlTestFile( - file_path=Path("/project/tests/unit/test_orders.sql"), - relative_path=Path("tests/unit/test_orders.sql"), - contents="", - blocks=(), - ), - known_model_names=known, - known_seed_names=known, - known_source_names=known, - known_table_function_names=known, - loaded_macros=dict.fromkeys(known, cast(LoadedMacro, None)), - assertion_target_model_names=assertion_targets, - ) - except CompileInputError as error: - return str(error) - return None - - -_NAMES: tuple[object, ...] = ("raw_status", " amount ", "", " ", 1) -_TEXTS: tuple[object, ...] = ("orders", " Orders. ", "", " ", 3, None) - - _MACRO_PIECES: tuple[str, ...] = ( "a", "@m(1)", diff --git a/tests/integration/src/sqlbuild/compiler/attachments/test_native_attachment_project.py b/tests/integration/src/sqlbuild/compiler/attachments/test_native_attachment_project.py deleted file mode 100644 index c9eca73ebe..0000000000 --- a/tests/integration/src/sqlbuild/compiler/attachments/test_native_attachment_project.py +++ /dev/null @@ -1,249 +0,0 @@ -"""Every attachment kind compiles like Python natively, with macros through the bridge.""" - -from __future__ import annotations - -from pathlib import Path - -import pytest - -from sqlbuild.compiler.frontier.types import CompilerEngine -from tests.integration.src.sqlbuild.compiler.attachments._test_types import ( - AttachmentProjectTestCase, -) -from tests.integration.src.sqlbuild.compiler.attachments.helpers import ( - attachment_engine_outcome, -) - -_BRIDGED_CONSUMERS: frozenset[str] = frozenset( - { - "bridged:/audits/generic/accepted_values.sql", - "bridged:/audits/generic/not_null.sql", - "bridged:/audits/generic/amount_floor.sql", - "bridged:/functions/sql/order_label.sql", - "bridged:/models/orders.sql", - "bridged:/sources/events.yml", - "bridged:/tests/scenarios/orders_scenario.sql", - "bridged:/tests/unit/test_orders.sql", - } -) -_NATIVE_ONLY_ENTRIES: frozenset[str] = ( - frozenset( - { - "pair_seed_files", - "scan_test_parameter_references", - "SqlTestTargetCatalog", - } - ) - | _BRIDGED_CONSUMERS -) -_ATTACHMENT_ENTRIES: frozenset[str] = frozenset( - { - "pair_seed_files", - "render_attached_generic_audit", - "expand_config_templates", - "interpolate_sql_batch", - "scan_sql_declaration_references", - "scan_test_parameter_references", - "omitted_ceremonial_select", - "extract_sql_scenario_json", - "SqlTestTargetCatalog", - } -) -_SCENARIO: str = "tests/scenarios/orders_scenario.sql" -_SCENARIO_HEADER: str = 'SCENARIO (\n description "Orders join their channel"\n);\n\n' -_UNIT_TEST: str = "tests/unit/test_orders.sql" -_HELPER_TEST_MOCKS: str = ( - "TEST();\n\nWITH\n__seed__channel_codes AS (SELECT 1 AS id, 'web' AS label),\n" - "__source__order_events AS (SELECT 1 AS id, 'north' AS region),\n" -) -_HELPER_TEST_EXPECTED: str = "__expected__orders AS (SELECT 1 AS id, 1.5 AS amount, 'web' AS label)" - - -@pytest.mark.parametrize( - "test_case", - [ - AttachmentProjectTestCase( - description="macros in every attachment kind, seeds, templates and generic audits", - overrides={}, - expected_native_entries=_ATTACHMENT_ENTRIES | _BRIDGED_CONSUMERS, - expected_outcome_fragment="((CompileSeedInput(", - ), - AttachmentProjectTestCase( - description="a scenario check CTE reading a project source", - overrides={ - _SCENARIO: _SCENARIO_HEADER - + "WITH\n__seed__channel_codes AS (SELECT 1 AS id, 'web' AS label),\n" - + '__expected__orders AS (SELECT id, 1.5 AS amount, label FROM __source("order_events"))\n' - }, - expected_native_entries=frozenset({"SqlTestTargetCatalog"}), - expected_outcome_fragment="error: SQL scenario file tests/scenarios/orders_scenario.sql CTE", - ), - AttachmentProjectTestCase( - description="a scenario helper reading an unknown source", - overrides={ - _SCENARIO: _SCENARIO_HEADER - + 'WITH\nhelper AS (SELECT * FROM __source("missing_events")),\n' - + "__seed__channel_codes AS (SELECT 1 AS id, 'web' AS label),\n" - + "__expected__orders AS (SELECT 1 AS id, 1.5 AS amount, 'web' AS label)\n" - }, - expected_native_entries=frozenset({"SqlTestTargetCatalog"}), - expected_outcome_fragment="error: SQL scenario file tests/scenarios/orders_scenario.sql " - "references unknown source 'missing_events'", - ), - AttachmentProjectTestCase( - description="a check CTE reading a source before a later malformed reference call", - overrides={ - _SCENARIO: _SCENARIO_HEADER - + "WITH\n__seed__channel_codes AS (SELECT 1 AS id, 'web' AS label),\n" - + '__expected__orders AS (SELECT id, 1.5 AS amount, label FROM __source("order_events")),\n' - + "__assert__no_rows AS (SELECT 1 FROM __source(order_events))\n" - }, - expected_native_entries=frozenset({"SqlTestTargetCatalog"}), - expected_outcome_fragment="error: SQL scenario file tests/scenarios/orders_scenario.sql CTE " - "'__expected__orders' must not reference project source", - ), - AttachmentProjectTestCase( - description="a malformed call in a check CTE leaves the unknown helper source first", - overrides={ - _SCENARIO: _SCENARIO_HEADER - + 'WITH\nhelper AS (SELECT * FROM __source("missing_events")),\n' - + "__seed__channel_codes AS (SELECT 1 AS id, 'web' AS label),\n" - + "__expected__orders AS (SELECT 1 AS id FROM __source(order_events))\n" - }, - expected_native_entries=frozenset({"SqlTestTargetCatalog"}), - expected_outcome_fragment="error: SQL scenario file tests/scenarios/orders_scenario.sql " - "references unknown source 'missing_events'", - ), - AttachmentProjectTestCase( - description="an unknown helper source before a later malformed fixture call", - overrides={ - _SCENARIO: _SCENARIO_HEADER - + 'WITH\nhelper AS (SELECT * FROM __source("missing_events")),\n' - + "__seed__channel_codes AS (SELECT 1 AS id FROM __source(order_events)),\n" - + "__expected__orders AS (SELECT 1 AS id, 1.5 AS amount, 'web' AS label)\n" - }, - expected_native_entries=frozenset({"SqlTestTargetCatalog"}), - expected_outcome_fragment="error: SQL scenario file tests/scenarios/orders_scenario.sql " - "references unknown source 'missing_events'", - ), - AttachmentProjectTestCase( - description="a scenario fixture without a target name", - overrides={ - _SCENARIO: _SCENARIO_HEADER - + "WITH\n__seed__ AS (SELECT 1 AS id, 'web' AS label),\n" - + "__expected__orders AS (SELECT 1 AS id, 1.5 AS amount, 'web' AS label)\n" - }, - expected_native_entries=frozenset({"SqlTestTargetCatalog"}), - expected_outcome_fragment="error: SQL scenario 'tests/scenarios/orders_scenario.sql' " - "must use __seed__ to identify a target", - ), - AttachmentProjectTestCase( - description="a scenario macro mock", - overrides={ - _SCENARIO: _SCENARIO_HEADER - + "WITH\n__seed__channel_codes AS (SELECT 1 AS id, 'web' AS label),\n" - + "__macro__tidy AS (SELECT 'x'),\n" - + "__expected__orders AS (SELECT 1 AS id, 1.5 AS amount, 'web' AS label)\n" - }, - expected_native_entries=frozenset({"SqlTestTargetCatalog"}), - expected_outcome_fragment="does not support macro mock CTE '__macro__tidy'", - ), - AttachmentProjectTestCase( - description="a scenario whose expected result depends on an assertion", - overrides={ - _SCENARIO: _SCENARIO_HEADER - + "WITH\n__seed__channel_codes AS (SELECT 1 AS id, 'web' AS label),\n" - + "__assert__no_rows AS (SELECT 1 FROM __seed__channel_codes WHERE id IS NULL),\n" - + "__expected__orders AS (SELECT 1 AS id, 1.5 AS amount, 'web' AS label " - + "FROM __assert__no_rows)\n" - }, - expected_native_entries=frozenset({"SqlTestTargetCatalog"}), - expected_outcome_fragment="check CTE '__expected__orders' must not depend on " - "'__assert__no_rows'", - ), - AttachmentProjectTestCase( - description="a helper CTE reading a model through __ref and read by an assertion", - overrides={ - _UNIT_TEST: _HELPER_TEST_MOCKS - + 'built_orders AS (SELECT id FROM __ref("orders")),\n' - + _HELPER_TEST_EXPECTED - + ",\n__assert__has_rows AS (SELECT 1 FROM built_orders WHERE id IS NULL)\n" - }, - expected_native_entries=frozenset({"SqlTestTargetCatalog"}), - expected_outcome_fragment="reference_target_model_names=('orders',)", - ), - AttachmentProjectTestCase( - description="a helper chain where one helper reads another", - overrides={ - _UNIT_TEST: _HELPER_TEST_MOCKS - + 'built_orders AS (SELECT id FROM __ref("orders")),\n' - + "built_ids AS (SELECT id FROM built_orders),\n" - + _HELPER_TEST_EXPECTED - + ",\n__assert__has_ids AS (SELECT 1 FROM built_ids WHERE id IS NULL)\n" - }, - expected_native_entries=frozenset({"SqlTestTargetCatalog"}), - expected_outcome_fragment="reference_target_model_names=('orders',)", - ), - AttachmentProjectTestCase( - description="an unread helper referencing an unknown model", - overrides={ - _UNIT_TEST: _HELPER_TEST_MOCKS - + 'unused_returns AS (SELECT id FROM __ref("returns")),\n' - + _HELPER_TEST_EXPECTED - + "\n" - }, - expected_native_entries=frozenset({"SqlTestTargetCatalog"}), - expected_outcome_fragment="read_helper_names=(), reference_target_model_names=()", - ), - AttachmentProjectTestCase( - description="a read helper referencing an unknown model reports P013", - overrides={ - _UNIT_TEST: _HELPER_TEST_MOCKS - + 'built_returns AS (SELECT id FROM __ref("returns")),\n' - + _HELPER_TEST_EXPECTED - + ",\n__assert__no_returns AS (SELECT 1 FROM built_returns)\n" - }, - expected_native_entries=frozenset({"SqlTestTargetCatalog"}), - expected_outcome_fragment="P013", - ), - AttachmentProjectTestCase( - description="a model test expecting an unknown model", - overrides={ - _UNIT_TEST: "TEST();\n\nWITH\n__seed__channel_codes AS (SELECT 1 AS id),\n" - "__expected__returns AS (SELECT 1 AS id)\n" - }, - expected_native_entries=frozenset({"SqlTestTargetCatalog"}), - expected_outcome_fragment="error: SQL test file tests/unit/test_orders.sql expects " - "unknown model 'returns'", - ), - ], - ids=lambda case: case.description, -) -def test_given_attachment_project_when_building_inputs_then_native_engines_match_python( - test_case: AttachmentProjectTestCase, tmp_path: Path, monkeypatch: pytest.MonkeyPatch -) -> None: - outcomes: dict[CompilerEngine, tuple[frozenset[str], str]] = { - engine: attachment_engine_outcome( - project_dir=tmp_path / engine.value, - engine=engine, - overrides=test_case.overrides, - monkeypatch=monkeypatch, - ) - for engine in CompilerEngine - } - python_called, python_outcome = outcomes[CompilerEngine.PYTHON] - native_called, native_outcome = outcomes[CompilerEngine.NATIVE] - preview_called, preview_outcome = outcomes[CompilerEngine.NATIVE_PREVIEW] - - assert ( - preview_outcome.replace(CompilerEngine.NATIVE_PREVIEW.value, "python"), - native_outcome.replace(CompilerEngine.NATIVE.value, "python"), - test_case.expected_outcome_fragment in python_outcome, - native_called >= test_case.expected_native_entries, - preview_called >= test_case.expected_native_entries, - python_called & _NATIVE_ONLY_ENTRIES, - ) == (python_outcome, python_outcome, True, True, True, frozenset()), test_case.description - - -if __name__ == "__main__": - pytest.main([__file__, "-vv"]) diff --git a/tests/integration/src/sqlbuild/compiler/attachments/test_native_authored_sql.py b/tests/integration/src/sqlbuild/compiler/attachments/test_native_authored_sql.py deleted file mode 100644 index a8863d30da..0000000000 --- a/tests/integration/src/sqlbuild/compiler/attachments/test_native_authored_sql.py +++ /dev/null @@ -1,71 +0,0 @@ -"""Authored SQL outside models expands identically under the preview engine.""" - -from __future__ import annotations - -import random - -import pytest - -from sqlbuild.compiler.compile.models import AuthoredSqlExpansionResult -from sqlbuild.compiler.frontier.types import CompilerEngine -from tests.integration.src.sqlbuild.compiler.attachments._test_types import ( - AuthoredSqlParityTestCase, -) -from tests.integration.src.sqlbuild.compiler.attachments.helpers import ( - authored_outcome, - generated_authored_sql, - generated_dollar_authored_sql, -) -from tests.integration.src.sqlbuild.compiler.helpers import mismatches - - -@pytest.mark.parametrize( - "test_case", - [ - AuthoredSqlParityTestCase( - description="seeded variables, enum and constant references, quotes and comments", - seed=20261008, - count=2000, - generate=lambda rng: generated_authored_sql(rng=rng), - expected_minimum_expanded=600, - expected_minimum_python_errors=300, - expected_minimum_exact_errors=300, - ), - AuthoredSqlParityTestCase( - description="dollar quotes around variables, enum and constant references", - seed=550, - count=2000, - generate=lambda rng: generated_dollar_authored_sql(rng=rng), - expected_minimum_expanded=300, - expected_minimum_python_errors=300, - expected_minimum_exact_errors=600, - ), - ], - ids=lambda case: case.description, -) -def test_given_generated_authored_sql_when_expanding_with_preview_then_python_output_matches( - test_case: AuthoredSqlParityTestCase, monkeypatch: pytest.MonkeyPatch -) -> None: - rng: random.Random = random.Random(test_case.seed) - sqls: list[str] = [test_case.generate(rng) for _ in range(test_case.count)] - - python: list[AuthoredSqlExpansionResult | str] = [ - authored_outcome(sql=sql, engine=CompilerEngine.PYTHON, monkeypatch=monkeypatch) - for sql in sqls - ] - preview: list[AuthoredSqlExpansionResult | str] = [ - authored_outcome(sql=sql, engine=CompilerEngine.NATIVE_PREVIEW, monkeypatch=monkeypatch) - for sql in sqls - ] - - assert ( - mismatches(inputs=[*sqls], expected=[*python], actual=[*preview]), - sum(isinstance(item, AuthoredSqlExpansionResult) for item in python) - >= test_case.expected_minimum_expanded, - sum(isinstance(item, str) for item in python) >= test_case.expected_minimum_python_errors, - sum(isinstance(item, str) for item in preview) >= test_case.expected_minimum_exact_errors, - ) == ([], True, True, True), test_case.description - - -if __name__ == "__main__": - pytest.main([__file__, "-vv"]) diff --git a/tests/integration/src/sqlbuild/compiler/attachments/test_native_omitted_select.py b/tests/integration/src/sqlbuild/compiler/attachments/test_native_omitted_select.py deleted file mode 100644 index 7fa88f1c09..0000000000 --- a/tests/integration/src/sqlbuild/compiler/attachments/test_native_omitted_select.py +++ /dev/null @@ -1,82 +0,0 @@ -"""Test and scenario bodies gain an omitted `SELECT 1` identically under the preview engine.""" - -from __future__ import annotations - -import random - -import pytest - -from sqlbuild.compiler.frontier.types import CompilerEngine -from sqlbuild.compiler.sql_analysis.models import SqlLexicalSyntax -from tests.integration.src.sqlbuild.compiler.attachments._test_types import ( - OmittedSelectParityTestCase, -) -from tests.integration.src.sqlbuild.compiler.attachments.helpers import ( - completed_body, - generated_test_body, -) -from tests.integration.src.sqlbuild.compiler.helpers import mismatches - - -@pytest.mark.parametrize( - "test_case", - [ - OmittedSelectParityTestCase( - description="generic syntax", - seed=20261008, - count=4000, - syntax=SqlLexicalSyntax(), - expected_minimum_completed=1000, - ), - OmittedSelectParityTestCase( - description="backslash escapes, raw and triple-quoted strings, hash comments", - seed=20261009, - count=4000, - syntax=SqlLexicalSyntax( - backslash_escape_quotes=frozenset({"'", '"'}), - raw_string_prefix=True, - triple_quoted_strings=True, - line_comment_prefixes=frozenset({"--", "#"}), - ), - expected_minimum_completed=1000, - ), - OmittedSelectParityTestCase( - description="escape strings and nested block comments", - seed=20261010, - count=4000, - syntax=SqlLexicalSyntax(escape_string_prefix=True, nested_block_comments=True), - expected_minimum_completed=1000, - ), - ], - ids=lambda case: case.description, -) -def test_given_generated_bodies_when_completing_select_then_python_output_matches( - test_case: OmittedSelectParityTestCase, monkeypatch: pytest.MonkeyPatch -) -> None: - rng: random.Random = random.Random(test_case.seed) - sqls: list[str] = [generated_test_body(rng=rng) for _ in range(test_case.count)] - - python: list[str] = [ - completed_body( - sql=sql, syntax=test_case.syntax, engine=CompilerEngine.PYTHON, monkeypatch=monkeypatch - ) - for sql in sqls - ] - preview: list[str] = [ - completed_body( - sql=sql, - syntax=test_case.syntax, - engine=CompilerEngine.NATIVE_PREVIEW, - monkeypatch=monkeypatch, - ) - for sql in sqls - ] - - assert ( - mismatches(inputs=[*sqls], expected=[*python], actual=[*preview]), - sum(map(str.__ne__, python, sqls)) >= test_case.expected_minimum_completed, - ) == ([], True), test_case.description - - -if __name__ == "__main__": - pytest.main([__file__, "-vv"]) diff --git a/tests/integration/src/sqlbuild/compiler/attachments/test_native_raw_direct_logic_tests.py b/tests/integration/src/sqlbuild/compiler/attachments/test_native_raw_direct_logic_tests.py deleted file mode 100644 index 4d0a156133..0000000000 --- a/tests/integration/src/sqlbuild/compiler/attachments/test_native_raw_direct_logic_tests.py +++ /dev/null @@ -1,70 +0,0 @@ -"""Unexpanded direct-logic SQL tests build identical inputs under every compiler engine. - -Every engine extracts tests before expansion with the native extractor, so quoted CTE names, -calls in `__macro_expected__` and malformed reference calls are rejected the same way. -""" - -from __future__ import annotations - -import random - -import pytest - -from sqlbuild.compiler.compile.types import SqlTestMode -from sqlbuild.compiler.frontier.types import CompilerEngine -from tests.integration.src.sqlbuild.compiler.attachments._test_types import ( - RawDirectLogicParityTestCase, -) -from tests.integration.src.sqlbuild.compiler.attachments.helpers import ( - generated_raw_direct_logic_test, - raw_extraction_accepts, - raw_test_compile_outcome, -) -from tests.integration.src.sqlbuild.compiler.helpers import mismatches - - -@pytest.mark.parametrize( - "test_case", - [ - RawDirectLogicParityTestCase( - description="quoted, non-ASCII and $ CTE names, calls in expected CTEs, bad reference calls", - seed=20261008, - count=3000, - expected_minimum_extracted=400, - expected_minimum_python_errors=600, - ), - ], - ids=lambda case: case.description, -) -def test_given_unexpanded_direct_logic_tests_when_compiling_in_preview_then_python_matches( - test_case: RawDirectLogicParityTestCase, monkeypatch: pytest.MonkeyPatch -) -> None: - rng: random.Random = random.Random(test_case.seed) - tests: list[tuple[str, SqlTestMode]] = [ - generated_raw_direct_logic_test(rng=rng) for _ in range(test_case.count) - ] - - python: list[str] = [ - raw_test_compile_outcome( - sql=sql, mode=mode, engine=CompilerEngine.PYTHON, monkeypatch=monkeypatch - ) - for sql, mode in tests - ] - native: list[str] = [ - raw_test_compile_outcome( - sql=sql, mode=mode, engine=CompilerEngine.NATIVE_PREVIEW, monkeypatch=monkeypatch - ) - for sql, mode in tests - ] - - assert ( - mismatches(inputs=[*tests], expected=[*python], actual=[*native]), - sum(raw_extraction_accepts(sql=sql, mode=mode) for sql, mode in tests) - >= test_case.expected_minimum_extracted, - sum(item.startswith("error: ") for item in python) - >= test_case.expected_minimum_python_errors, - ) == ([], True, True), test_case.description - - -if __name__ == "__main__": - pytest.main([__file__, "-vv"]) diff --git a/tests/integration/src/sqlbuild/compiler/attachments/test_native_scenario_extraction.py b/tests/integration/src/sqlbuild/compiler/attachments/test_native_scenario_extraction.py deleted file mode 100644 index 9ac53d537d..0000000000 --- a/tests/integration/src/sqlbuild/compiler/attachments/test_native_scenario_extraction.py +++ /dev/null @@ -1,84 +0,0 @@ -"""Scenario CTEs and errors extract identically under the preview engine, mostly natively.""" - -from __future__ import annotations - -import random -from collections import Counter - -import pytest - -from sqlbuild.compiler.compile.models import CompileSqlScenarioCtes -from sqlbuild.compiler.frontier.types import CompilerEngine -from sqlbuild.compiler.sql_analysis.models import SqlLexicalSyntax -from tests.integration.src.sqlbuild.compiler.attachments._test_types import ( - ScenarioParityTestCase, -) -from tests.integration.src.sqlbuild.compiler.attachments.helpers import ( - generated_scenario, - native_scenario_answer, - scenario_outcome, -) -from tests.integration.src.sqlbuild.compiler.helpers import mismatches - - -@pytest.mark.parametrize( - "test_case", - [ - ScenarioParityTestCase( - description="generic syntax", - seed=20261008, - count=3000, - syntax=SqlLexicalSyntax(), - expected_minimum_extracted=150, - expected_minimum_native=80, - expected_minimum_python_errors=2000, - expected_minimum_native_errors=1200, - ), - ScenarioParityTestCase( - description="hash comments under the adapter's rules", - seed=20261009, - count=1000, - syntax=SqlLexicalSyntax(line_comment_prefixes=frozenset({"--", "#"})), - expected_minimum_extracted=50, - expected_minimum_native=25, - expected_minimum_python_errors=600, - expected_minimum_native_errors=400, - ), - ], - ids=lambda case: case.description, -) -def test_given_generated_scenarios_when_extracting_with_preview_then_python_output_matches( - test_case: ScenarioParityTestCase, monkeypatch: pytest.MonkeyPatch -) -> None: - rng: random.Random = random.Random(test_case.seed) - sqls: list[str] = [generated_scenario(rng=rng) for _ in range(test_case.count)] - - python: list[object] = [ - scenario_outcome( - sql=sql, syntax=test_case.syntax, engine=CompilerEngine.PYTHON, monkeypatch=monkeypatch - ) - for sql in sqls - ] - answers: list[str] = [native_scenario_answer(sql=sql, syntax=test_case.syntax) for sql in sqls] - preview: list[object] = [ - scenario_outcome( - sql=sql, - syntax=test_case.syntax, - engine=CompilerEngine.NATIVE_PREVIEW, - monkeypatch=monkeypatch, - ) - for sql in sqls - ] - - assert ( - mismatches(inputs=[*sqls], expected=python, actual=preview), - sum(isinstance(item, CompileSqlScenarioCtes) for item in python) - >= test_case.expected_minimum_extracted, - answers.count("extracted") >= test_case.expected_minimum_native, - sum(isinstance(item, str) for item in python) >= test_case.expected_minimum_python_errors, - answers.count("error") >= test_case.expected_minimum_native_errors, - ) == ([], True, True, True, True), (test_case.description, Counter(answers)) - - -if __name__ == "__main__": - pytest.main([__file__, "-vv"]) diff --git a/tests/integration/src/sqlbuild/compiler/attachments/test_native_test_parameters.py b/tests/integration/src/sqlbuild/compiler/attachments/test_native_test_parameters.py deleted file mode 100644 index 871d0e1a15..0000000000 --- a/tests/integration/src/sqlbuild/compiler/attachments/test_native_test_parameters.py +++ /dev/null @@ -1,58 +0,0 @@ -"""SQL test `@param` references expand identically under the preview engine.""" - -from __future__ import annotations - -import random - -import pytest - -from sqlbuild.compiler.frontier.types import CompilerEngine -from tests.integration.src.sqlbuild.compiler.attachments._test_types import ( - ParameterParityTestCase, -) -from tests.integration.src.sqlbuild.compiler.attachments.helpers import ( - generated_parameter_sql, - parameter_outcome, -) -from tests.integration.src.sqlbuild.compiler.helpers import mismatches - - -@pytest.mark.parametrize( - "test_case", - [ - ParameterParityTestCase( - description="seeded references, malformed and undeclared names, quotes, comments", - seed=20261008, - count=3000, - expected_minimum_expanded=800, - expected_minimum_python_errors=800, - expected_minimum_exact_errors=1500, - ), - ], - ids=lambda case: case.description, -) -def test_given_generated_test_bodies_when_expanding_parameters_then_python_output_matches( - test_case: ParameterParityTestCase, monkeypatch: pytest.MonkeyPatch -) -> None: - rng: random.Random = random.Random(test_case.seed) - sqls: list[str] = [generated_parameter_sql(rng=rng) for _ in range(test_case.count)] - - python: list[object] = [ - parameter_outcome(sql=sql, engine=CompilerEngine.PYTHON, monkeypatch=monkeypatch) - for sql in sqls - ] - preview: list[object] = [ - parameter_outcome(sql=sql, engine=CompilerEngine.NATIVE_PREVIEW, monkeypatch=monkeypatch) - for sql in sqls - ] - - assert ( - mismatches(inputs=[*sqls], expected=python, actual=preview), - sum(isinstance(item, tuple) for item in python) >= test_case.expected_minimum_expanded, - sum(isinstance(item, str) for item in python) >= test_case.expected_minimum_python_errors, - sum(isinstance(item, str) for item in preview) >= test_case.expected_minimum_exact_errors, - ) == ([], True, True, True), test_case.description - - -if __name__ == "__main__": - pytest.main([__file__, "-vv"]) diff --git a/tests/integration/src/sqlbuild/compiler/attachments/test_native_test_targets.py b/tests/integration/src/sqlbuild/compiler/attachments/test_native_test_targets.py deleted file mode 100644 index a0840a9ac6..0000000000 --- a/tests/integration/src/sqlbuild/compiler/attachments/test_native_test_targets.py +++ /dev/null @@ -1,69 +0,0 @@ -"""Model SQL test targets validate identically under the preview engine.""" - -from __future__ import annotations - -import random - -import pytest - -from sqlbuild.compiler.compile.models import CompileModelSqlTestCtes -from sqlbuild.compiler.frontier.types import CompilerEngine -from tests.integration.src.sqlbuild.compiler.attachments._test_types import ( - TargetParityTestCase, -) -from tests.integration.src.sqlbuild.compiler.attachments.helpers import ( - generated_test_targets, - target_validation_outcome, -) -from tests.integration.src.sqlbuild.compiler.helpers import mismatches - - -@pytest.mark.parametrize( - "test_case", - [ - TargetParityTestCase( - description="seeded mocks, macro mocks, expected models and assertion targets", - seed=20261008, - count=2000, - expected_minimum_valid=150, - expected_minimum_python_errors=1000, - ), - ], - ids=lambda case: case.description, -) -def test_given_generated_test_targets_when_validating_with_preview_then_python_errors_match( - test_case: TargetParityTestCase, monkeypatch: pytest.MonkeyPatch -) -> None: - rng: random.Random = random.Random(test_case.seed) - targets: list[tuple[CompileModelSqlTestCtes, tuple[str, ...]]] = [ - generated_test_targets(rng=rng) for _ in range(test_case.count) - ] - - python: list[str | None] = [ - target_validation_outcome( - payload=payload, - assertion_targets=assertion_targets, - engine=CompilerEngine.PYTHON, - monkeypatch=monkeypatch, - ) - for payload, assertion_targets in targets - ] - preview: list[str | None] = [ - target_validation_outcome( - payload=payload, - assertion_targets=assertion_targets, - engine=CompilerEngine.NATIVE_PREVIEW, - monkeypatch=monkeypatch, - ) - for payload, assertion_targets in targets - ] - - assert ( - mismatches(inputs=[*targets], expected=[*python], actual=[*preview]), - python.count(None) >= test_case.expected_minimum_valid, - len(python) - python.count(None) >= test_case.expected_minimum_python_errors, - ) == ([], True, True), test_case.description - - -if __name__ == "__main__": - pytest.main([__file__, "-vv"]) diff --git a/tests/integration/src/sqlbuild/compiler/compile/_test_types.py b/tests/integration/src/sqlbuild/compiler/compile/_test_types.py index 2267a116aa..f75f91d1ab 100644 --- a/tests/integration/src/sqlbuild/compiler/compile/_test_types.py +++ b/tests/integration/src/sqlbuild/compiler/compile/_test_types.py @@ -18,7 +18,6 @@ class MacroBridgeMemoTestCase: description: str files: dict[str, str] - expected_python_executions: int expected_native_executions: int @@ -31,9 +30,19 @@ class MacroBridgeFailureTestCase: expected_message_fragment: str +@dataclass(frozen=True) +class MacroExpansionEdgeTestCase: + """Hand-picked SQL texts whose expansion must match Python's expansion recorded in a golden.""" + + description: str + texts: tuple[str, ...] + expected_mismatches: list[tuple[object, object, object]] + + @dataclass(frozen=True) class MacroExpansionDifferentialTestCase: - """Seeded random SQL text that must expand identically with and without the bridge.""" + """Seeded random SQL text that must expand, with and without the bridge, as Python's + expansion recorded in its golden did.""" description: str seed: int @@ -55,3 +64,12 @@ class FailingMacroProjectParityTestCase: expected_minimum_errors_after_macro_runs: int expected_minimum_distinct_errors: int expected_mismatches: list[tuple[object, object, object]] + + +@dataclass(frozen=True) +class DeclarationUsageTestCase: + """SQL texts whose declaration usages Python's usage walk recorded in a golden.""" + + description: str + texts: tuple[str, ...] + expected_differences: list[tuple[int, str, object, object]] diff --git a/tests/integration/src/sqlbuild/compiler/compile/helpers.py b/tests/integration/src/sqlbuild/compiler/compile/helpers.py index 8378aafded..1a104bc0fa 100644 --- a/tests/integration/src/sqlbuild/compiler/compile/helpers.py +++ b/tests/integration/src/sqlbuild/compiler/compile/helpers.py @@ -15,12 +15,14 @@ import pytest from sqlbuild.adapters.duckdb.classes.duckdb_adapter import DuckDbAdapter +from sqlbuild.compiler.compile._helpers.render.declarations import declaration_usage_records from sqlbuild.compiler.compile._helpers.render.macros import expand_sql_macros_result from sqlbuild.compiler.compile.exceptions import CompileInputError from sqlbuild.compiler.compile.main._build_compile_inputs import build_compile_inputs from sqlbuild.compiler.compile.models import ( CompileAdapterContext, CompileProjectInputs, + DeclarationResolutionContext, LoadedMacro, MacroContext, MacroExpansionResult, @@ -37,8 +39,8 @@ from sqlbuild.compiler.frontier.types import CompilerStage from sqlbuild.compiler.macro_bridge.classes.macro_bridge import MacroBridge from sqlbuild.compiler.macro_bridge.constants import ACTIVE_MACRO_BRIDGE -from sqlbuild.compiler.scopes.models import ResourceIdentity -from sqlbuild.compiler.scopes.types import ResourceKind +from sqlbuild.compiler.scopes.models import DeclarationIdentity, ResourceIdentity, VisibilityRecord +from sqlbuild.compiler.scopes.types import DeclarationKind, ResourceKind, VisibilityReason from sqlbuild.spec.contracts.main.resolve_effective_collection_rendering import ( resolve_effective_collection_rendering, ) @@ -556,3 +558,43 @@ def engine_render_outcome( ), }[failure is None] return outcome, tuple(log_path.read_text(encoding="utf-8").splitlines()) + + +_USAGE_CONSUMER: ResourceIdentity = ResourceIdentity(ResourceKind.TEST, "orders_test") + + +def _visible(kind: DeclarationKind, name: str) -> tuple[VisibilityRecord, ...]: + return ( + VisibilityRecord( + resource=_USAGE_CONSUMER, + declaration=DeclarationIdentity(kind, name), + reason=VisibilityReason.GLOBAL, + ), + ) + + +_USAGE_DECLARATIONS: DeclarationResolutionContext = DeclarationResolutionContext( + enum_visibility={ + "status": _visible(DeclarationKind.ENUM, "status"), + "size": _visible(DeclarationKind.ENUM, "size"), + }, + constant_visibility={"rate": _visible(DeclarationKind.CONSTANT, "rate")}, +) + + +def declaration_usage_outcome(sql: str) -> tuple[object, ...]: + """The names of the declarations `sql` uses, in order, or the error the scan raises.""" + + capture: ExpansionFailureCapture = ExpansionFailureCapture() + names: list[tuple[object, ...]] = [()] + with capture: + names[0] = tuple( + usage.declaration.name + for usage in declaration_usage_records( + sql=sql, resource=_USAGE_CONSUMER, declarations=_USAGE_DECLARATIONS + ) + ) + return { + True: names[0], + False: (type(capture.failure).__name__, str(capture.failure)), + }[capture.failure is None] diff --git a/tests/integration/src/sqlbuild/compiler/compile/test_native_declaration_usages.py b/tests/integration/src/sqlbuild/compiler/compile/test_native_declaration_usages.py new file mode 100644 index 0000000000..7f84016974 --- /dev/null +++ b/tests/integration/src/sqlbuild/compiler/compile/test_native_declaration_usages.py @@ -0,0 +1,68 @@ +"""SQL-test declaration usages come from the native reference scan and match Python's walk.""" + +from __future__ import annotations + +import pytest + +from tests.integration.src.sqlbuild.compiler.compile._test_types import DeclarationUsageTestCase +from tests.integration.src.sqlbuild.compiler.compile.helpers import declaration_usage_outcome +from tests.integration.src.sqlbuild.compiler.helpers import ( + GoldenEntry, + golden_differences, + golden_entry, + golden_name, + read_golden, +) + + +@pytest.mark.parametrize( + "test_case", + [ + DeclarationUsageTestCase( + description="usage scan edges", + texts=( + "SELECT @enum('status').OPEN, @const('rate')", + "SELECT @enum('status') , @const('rate')", + "SELECT @enum x 'unclosed", + "SELECT @enum x, @const('rate') 'unclosed", + 'SELECT @const(rate), @enum("size").S', + "SELECT '@enum(''status'').A', @const('rate') /* open", + "SELECT @enumx('status').A, @const_x('rate'), @consté, @const('rate')", + "SELECT $$ @enum('status').A $$, @enum('size').M -- @const('rate')\n", + "SELECT x$$ @const('rate') $$", + "SELECT @enum ( 'status' ) . OPEN, @enum('status').OPEN, @const('missing')", + "SELECT `@const('rate')`, \"@enum('size').A\"", + "SELECT @const('rate'), @const('rate'), 'é' @enum('size').XL", + "SELECT @@const, @enum, @const", + "SELECT 1", + "SELECT @enum('status').OPEN /* @const('rate') */ 'it''s' @const('rate')", + "SELECT @const('rate' ", + "SELECT /* x @const('rate')", + "SELECT 'a @enum('status').A", + "SELECT @enum x 'oops @const('rate')", + "SELECT @const('rate') $tag$ @enum('size').S", + "SELECT @enum(\"status\").OPEN, @const('rate') /* tail @enum('size').S", + ), + expected_differences=[], + ), + ], + ids=lambda case: case.description, +) +def test_given_declaration_references_when_collecting_usages_then_matches_python_golden( + test_case: DeclarationUsageTestCase, +) -> None: + outcomes: list[tuple[object, ...]] = [declaration_usage_outcome(sql) for sql in test_case.texts] + expected: list[GoldenEntry] = read_golden( + golden_name("declaration_usages", test_case.description) + ) + + assert ( + golden_differences( + expected, [golden_entry("declaration_usages", outcome) for outcome in outcomes] + ) + == test_case.expected_differences + ) + + +if __name__ == "__main__": + pytest.main([__file__, "-vv"]) diff --git a/tests/integration/src/sqlbuild/compiler/compile/test_native_macro_bridge.py b/tests/integration/src/sqlbuild/compiler/compile/test_native_macro_bridge.py index cb5135b328..d25c4cbe83 100644 --- a/tests/integration/src/sqlbuild/compiler/compile/test_native_macro_bridge.py +++ b/tests/integration/src/sqlbuild/compiler/compile/test_native_macro_bridge.py @@ -1,4 +1,4 @@ -"""The native macro bridge renders compile inputs byte-identically to the Python engine.""" +"""The native macro bridge renders compile inputs as expected, running each call class once.""" from __future__ import annotations @@ -16,6 +16,7 @@ MacroBridgeMemoTestCase, MacroBridgeParityTestCase, MacroExpansionDifferentialTestCase, + MacroExpansionEdgeTestCase, ) from tests.integration.src.sqlbuild.compiler.compile.helpers import ( MACRO_BRIDGE_PROJECT_FILES, @@ -30,7 +31,13 @@ render_error, write_project, ) -from tests.integration.src.sqlbuild.compiler.helpers import mismatches +from tests.integration.src.sqlbuild.compiler.helpers import ( + GoldenEntry, + golden_differences, + golden_entry, + golden_name, + read_golden, +) _FAILURE_BASE_FILES: dict[str, str] = { "sqlbuild_project.toml": MACRO_BRIDGE_PROJECT_FILES["sqlbuild_project.toml"], @@ -73,22 +80,22 @@ ], ids=lambda case: case.description, ) -def test_given_macro_heavy_project_when_rendering_with_each_engine_then_inputs_are_identical( +def test_given_macro_heavy_project_when_rendering_with_each_engine_then_inputs_are_expected( test_case: MacroBridgeParityTestCase, tmp_path: Path, monkeypatch: pytest.MonkeyPatch ) -> None: project_dir: Path = write_project(root=tmp_path / "project", files=test_case.files) - python_capture: str = comparable_capture( - render_compile_inputs(project_dir=project_dir, engine="python", monkeypatch=monkeypatch) - ) native_capture: str = comparable_capture( + render_compile_inputs(project_dir=project_dir, engine="native", monkeypatch=monkeypatch) + ) + preview_capture: str = comparable_capture( render_compile_inputs( project_dir=project_dir, engine="native-preview", monkeypatch=monkeypatch ) ) - assert native_capture == python_capture - assert all(map(python_capture.__contains__, test_case.expected_fragments)) + assert preview_capture == native_capture + assert all(map(native_capture.__contains__, test_case.expected_fragments)) @pytest.mark.parametrize( @@ -97,7 +104,6 @@ def test_given_macro_heavy_project_when_rendering_with_each_engine_then_inputs_a MacroBridgeMemoTestCase( description="one global call text in three models", files=MACRO_BRIDGE_PROJECT_FILES, - expected_python_executions=3, expected_native_executions=1, ), ], @@ -108,14 +114,14 @@ def test_given_repeated_macro_calls_when_rendering_natively_then_each_call_class ) -> None: project_dir: Path = write_project(root=tmp_path / "project", files=test_case.files) executions: dict[str, int] = {} - for engine in ("python", "native-preview"): + for engine in ("native", "native-preview"): log_path: Path = tmp_path / f"{engine}.log" monkeypatch.setenv(MACRO_CALL_LOG_ENV_VAR, str(log_path)) _ = render_compile_inputs(project_dir=project_dir, engine=engine, monkeypatch=monkeypatch) executions[engine] = len(log_path.read_text(encoding="utf-8").splitlines()) assert executions == { - "python": test_case.expected_python_executions, + "native": test_case.expected_native_executions, "native-preview": test_case.expected_native_executions, } @@ -168,20 +174,20 @@ def test_given_repeated_macro_calls_when_rendering_natively_then_each_call_class ], ids=lambda case: case.description, ) -def test_given_failing_render_when_rendering_natively_then_raises_the_python_error( +def test_given_failing_render_when_rendering_natively_then_raises_the_expected_error( test_case: MacroBridgeFailureTestCase, tmp_path: Path, monkeypatch: pytest.MonkeyPatch ) -> None: project_dir: Path = write_project(root=tmp_path / "project", files=test_case.files) - python_error: tuple[type[BaseException], str, type[object]] = render_error( - project_dir=project_dir, engine="python", monkeypatch=monkeypatch - ) native_error: tuple[type[BaseException], str, type[object]] = render_error( + project_dir=project_dir, engine="native", monkeypatch=monkeypatch + ) + preview_error: tuple[type[BaseException], str, type[object]] = render_error( project_dir=project_dir, engine="native-preview", monkeypatch=monkeypatch ) - assert native_error == python_error - assert test_case.expected_message_fragment in python_error[1] + assert preview_error == native_error + assert test_case.expected_message_fragment in native_error[1] @pytest.mark.parametrize( @@ -206,26 +212,67 @@ def test_given_random_macro_sql_when_expanding_through_bridge_then_matches_pytho python_version=(sys.version_info[0], sys.version_info[1]), unicode_version=unicodedata.unidata_version, ) + unbridged: list[tuple[object, ...]] = [expansion_outcome(sql=sql, bridge=None) for sql in texts] + bridged: list[tuple[object, ...]] = [expansion_outcome(sql=sql, bridge=bridge) for sql in texts] + expected: list[GoldenEntry] = read_golden(golden_name("macro_expansion", test_case.description)) + + assert ( + golden_differences(expected, [golden_entry("macro_expansion", item) for item in bridged]), + golden_differences(expected, [golden_entry("macro_expansion", item) for item in unbridged]), + ) == (test_case.expected_mismatches, test_case.expected_mismatches) + assert sum(len(outcome) == 5 for outcome in bridged) >= test_case.expected_minimum_successes + assert bridge.stats()[0] > 0 + - python_outcomes: list[tuple[object, ...]] = [ - expansion_outcome(sql=sql, bridge=None) for sql in texts +@pytest.mark.parametrize( + "test_case", + [ + MacroExpansionEdgeTestCase( + description="nested argument scan edges", + texts=( + "@n(@nope(1))", + "@n(@m(1)", + "@n(@ab c(1))", + "@n(@m('x), 1)", + "@n(@m(1), 'oops)", + "@n(@mm (2), @m('é'))", + "@n(@é(1))", + "@n(/* @m( */ @m(1))", + "@n(@nope(1), @m(')", + "@n(@m(1) @xy z(2))", + "@n(@m(1) @mm z(2))", + "@mm z(2)", + "@n($$ ) $$, @m(1))", + '@n("@m(1)")', + "@n(@n(@n(@nope())))", + "@n(@m(1), -- )\n @m(2))", + "@n(@m(1), /* open)", + "@n(@m(@n(@m('é'))))", + ), + expected_mismatches=[], + ), + ], + ids=lambda case: case.description, +) +def test_given_nested_macro_arguments_when_expanding_then_matches_python_golden( + test_case: MacroExpansionEdgeTestCase, +) -> None: + bridge: MacroBridge = MacroBridge( + python_version=(sys.version_info[0], sys.version_info[1]), + unicode_version=unicodedata.unidata_version, + ) + unbridged: list[tuple[object, ...]] = [ + expansion_outcome(sql=sql, bridge=None) for sql in test_case.texts ] - bridged_outcomes: list[tuple[object, ...]] = [ - expansion_outcome(sql=sql, bridge=bridge) for sql in texts + bridged: list[tuple[object, ...]] = [ + expansion_outcome(sql=sql, bridge=bridge) for sql in test_case.texts ] + expected: list[GoldenEntry] = read_golden(golden_name("macro_expansion", test_case.description)) assert ( - mismatches( - inputs=list[object](texts), - expected=list[object](python_outcomes), - actual=list[object](bridged_outcomes), - ) - == test_case.expected_mismatches - ) - assert sum(len(outcome) == 5 for outcome in python_outcomes) >= ( - test_case.expected_minimum_successes - ) - assert bridge.stats()[0] > 0 + golden_differences(expected, [golden_entry("macro_expansion", item) for item in bridged]), + golden_differences(expected, [golden_entry("macro_expansion", item) for item in unbridged]), + ) == (test_case.expected_mismatches, test_case.expected_mismatches) @pytest.mark.parametrize( @@ -235,7 +282,7 @@ def test_given_random_macro_sql_when_expanding_through_bridge_then_matches_pytho description="seeded projects with raising, mistyped, unparsable and unreachable macros", seed=1043, projects=150, - engines=("python", "native", "native-preview"), + engines=("native", "native-preview"), expected_minimum_failures=100, expected_minimum_successes=10, expected_minimum_errors_after_macro_runs=80, @@ -245,7 +292,7 @@ def test_given_random_macro_sql_when_expanding_through_bridge_then_matches_pytho ], ids=lambda case: case.description, ) -def test_given_failing_macro_projects_when_rendering_then_every_engine_raises_python_error_once( +def test_given_failing_macro_projects_when_rendering_then_every_engine_raises_one_error( test_case: FailingMacroProjectParityTestCase, tmp_path: Path, monkeypatch: pytest.MonkeyPatch, diff --git a/tests/integration/src/sqlbuild/compiler/contracts/_test_types.py b/tests/integration/src/sqlbuild/compiler/contracts/_test_types.py index 3f8546f893..b6b73c5cba 100644 --- a/tests/integration/src/sqlbuild/compiler/contracts/_test_types.py +++ b/tests/integration/src/sqlbuild/compiler/contracts/_test_types.py @@ -6,7 +6,7 @@ @dataclass(frozen=True) -class GeneratedContractParityTestCase: +class GeneratedContractTestCase: """Generated projects whose models are perturbed into every contract family per dialect.""" description: str @@ -20,21 +20,19 @@ class GeneratedContractParityTestCase: @dataclass(frozen=True) -class GeneratedPromotionParityTestCase: - """Generated lifecycle configs and promotion settings compared with Python.""" +class FormerlyDeferredContractTestCase: + """A contract input Python used to answer, and the native `(code, model, column, message)`s.""" description: str - seed: int - variants: int - expected_minimum_conflicts: int + declared_type: str + dialect: str | None + expected_diagnostics: tuple[tuple[str, str | None, str | None, str], ...] @dataclass(frozen=True) -class DeferredContractTestCase: - """A contract input native validation hands back to Python, and the deferral it records.""" +class UnknownDialectContractTestCase: + """A dialect Polyglot does not know, and the error Python's type normalization raised.""" description: str - declared_type: str - dialect: str | None - expected_kind: str - expected_deferred_models: int + dialect: str + expected_error: str diff --git a/tests/integration/src/sqlbuild/compiler/contracts/helpers.py b/tests/integration/src/sqlbuild/compiler/contracts/helpers.py index 19b79f5805..4d735dffe3 100644 --- a/tests/integration/src/sqlbuild/compiler/contracts/helpers.py +++ b/tests/integration/src/sqlbuild/compiler/contracts/helpers.py @@ -1,9 +1,8 @@ -"""Generated contract inputs, and the Python and native contract results they produce.""" +"""Generated contract inputs, and the native contract results they produce.""" from __future__ import annotations import itertools -import json import random from collections import Counter from collections.abc import Callable, Iterator, Sequence @@ -14,8 +13,6 @@ import pytest import sqlbuild._native as native_module -from sqlbuild.adapter.contract.types import TablePromotionMode -from sqlbuild.adapter.type_system._helpers.type_normalization import normalize_type from sqlbuild.adapters.duckdb.classes.duckdb_adapter import DuckDbAdapter from sqlbuild.compiler.compile.models import ( CompiledModel, @@ -25,10 +22,8 @@ DynamicColumnFamilyProof, InferredColumn, ) -from sqlbuild.compiler.contracts.main.promotion_conflicts import promotion_conflict_diagnostics from sqlbuild.compiler.contracts.main.validate import evaluate_model_contracts from sqlbuild.compiler.discovery.main.discover import discover_project_inputs -from sqlbuild.compiler.frontier.constants import COMPILER_ENGINE_ENV_VAR from sqlbuild.compiler.lineage.types import InferredNullability from sqlbuild.compiler.pipeline.main.graph import build_project_graph from sqlbuild.compiler.planner.types import ContractPolicy, IncrementalMode, MaterializationType @@ -163,11 +158,10 @@ None, ) _PROMOTION_MODES: tuple[str | None, ...] = (None, "immediate", "staged", "IMMEDIATE", "") -_SETTINGS_FILES: tuple[str, ...] = ("sqlbuild_project.toml", "sqlbuild_local.toml") type ContractView = tuple[CompilerDiagnostic, ...] type NativeContractRequest = tuple[str, bool, list[Any]] -type NativeContractOutcome = tuple[str | None, list[Any]] +type NativeContractOutcome = list[Any] _EMPTY_SCHEMA_ROW: tuple[list[Any], list[Any], bool, bool] = ([], [], False, False) @@ -284,65 +278,35 @@ def _dynamic_proof(*, rng: random.Random) -> DynamicColumnContractProof: ) -def contract_views( - *, - project: CompiledProject, - dialect: str | None, - monkeypatch: pytest.MonkeyPatch, -) -> tuple[ContractView, ContractView]: - """Python's and the native engine's contract diagnostics for the same project.""" - - return ( - _on_engine( - engine="python", - monkeypatch=monkeypatch, - run=lambda: evaluate_model_contracts(project=project, dialect=dialect).diagnostics, - ), - _on_engine( - engine="native-preview", - monkeypatch=monkeypatch, - run=lambda: evaluate_model_contracts(project=project, dialect=dialect).diagnostics, - ), - ) +def contract_diagnostics(*, project: CompiledProject, dialect: str | None) -> ContractView: + """The project's contract diagnostics, through the public contract entry point.""" + return evaluate_model_contracts(project=project, dialect=dialect).diagnostics -def promotion_views( - *, - project: CompiledProject, - adapter_default: TablePromotionMode, - settings_file: str, - monkeypatch: pytest.MonkeyPatch, -) -> tuple[ContractView, ContractView]: - """Python's and the native engine's K011 promotion conflicts for the same project.""" - def run() -> ContractView: - return promotion_conflict_diagnostics( - project=project, adapter_default=adapter_default, settings_file=settings_file - ) - - return ( - _on_engine(engine="python", monkeypatch=monkeypatch, run=run), - _on_engine(engine="native-preview", monkeypatch=monkeypatch, run=run), - ) +def diagnostic_view(*, diagnostics: ContractView, project_dir: Path) -> str: + """Every field of the diagnostics, in order, with the project directory masked.""" - -def promotion_settings(*, rng: random.Random) -> tuple[TablePromotionMode, str]: - """A generated adapter default promotion mode and settings file.""" - - return rng.choice(tuple(TablePromotionMode)), rng.choice(_SETTINGS_FILES) - - -def _on_engine( - *, engine: str, monkeypatch: pytest.MonkeyPatch, run: Callable[[], ContractView] -) -> ContractView: - monkeypatch.setenv(COMPILER_ENGINE_ENV_VAR, engine) - normalize_type.cache_clear() - return run() + return repr( + [ + ( + diagnostic.code, + diagnostic.severity, + diagnostic.resource_name, + diagnostic.column_name, + diagnostic.message, + diagnostic.location, + diagnostic.related_locations, + diagnostic.help, + ) + for diagnostic in diagnostics + ] + ).replace(str(project_dir), "") class NativeContractRecord(NamedTuple): - """Native contract outcomes: `native` (evaluated natively), `typed_comparisons`, handback - kinds and `native_diagnostics` in `statuses`; codes of natively built diagnostics in `codes`.""" + """Native contract outcomes: `native` (evaluated natively), `typed_comparisons` and + `native_diagnostics` in `statuses`; codes of natively built diagnostics in `codes`.""" statuses: Counter[str] codes: Counter[str] @@ -359,10 +323,7 @@ def record_native_outcomes(*, monkeypatch: pytest.MonkeyPatch) -> NativeContract def counted(request: NativeContractRequest) -> list[NativeContractOutcome]: outcomes: list[NativeContractOutcome] = evaluate(request) record.statuses.update(native_contract_statuses(request=request, outcomes=outcomes)) - answered: list[NativeContractOutcome] = list(filter(_answered, outcomes)) - rows: Iterator[Sequence[Any]] = itertools.chain.from_iterable( - diagnostics for _, diagnostics in answered - ) + rows: Iterator[Sequence[Any]] = itertools.chain.from_iterable(outcomes) record.codes.update(row[0] for row in rows) return outcomes @@ -373,37 +334,22 @@ def counted(request: NativeContractRequest) -> list[NativeContractOutcome]: def native_contract_statuses( *, request: NativeContractRequest, outcomes: list[NativeContractOutcome] ) -> Counter[str]: - """Per-request counts: `native` for models native evaluated, `typed_comparisons` for those - that compared at least one typed column, each handback kind, and `native_diagnostics`.""" + """Per-request counts: `native` for evaluated models, `typed_comparisons` for those that + compared at least one typed column, and `native_diagnostics`.""" _, implicit, models = request - pairs: list[tuple[Sequence[Any], NativeContractOutcome]] = list( - zip(models, outcomes, strict=True) - ) - answered: list[tuple[Sequence[Any], NativeContractOutcome]] = list( - filter(lambda pair: _answered(pair[1]), pairs) - ) evaluated: list[Sequence[Any]] = list( - filter( - lambda model: _requires_evaluation(model=model, implicit=implicit), - (model for model, _ in answered), - ) - ) - statuses: Counter[str] = Counter( - str(deferral) for deferral, _ in filter(lambda outcome: not _answered(outcome), outcomes) + filter(lambda model: _requires_evaluation(model=model, implicit=implicit), models) ) + statuses: Counter[str] = Counter() statuses["native"] += len(evaluated) statuses["typed_comparisons"] += sum( _compares_typed_column(model=model, implicit=implicit) for model in evaluated ) - statuses["native_diagnostics"] += sum(len(diagnostics) for _, (_, diagnostics) in answered) + statuses["native_diagnostics"] += sum(len(diagnostics) for diagnostics in outcomes) return statuses -def _answered(outcome: NativeContractOutcome) -> bool: - return outcome[0] is None - - def _schema(model: Sequence[Any]) -> Sequence[Any]: return (_EMPTY_SCHEMA_ROW, model[2])[model[2] is not None] @@ -430,34 +376,6 @@ def _compares_typed_column(*, model: Sequence[Any], implicit: bool) -> bool: ) -def record_native_promotion_calls(*, monkeypatch: pytest.MonkeyPatch) -> Counter[str]: - """Count native promotion conflict calls and the conflicts they return.""" - - statuses: Counter[str] = Counter() - conflicts: Callable[..., list[tuple[int, str, str, str]]] = ( - native_module.native_promotion_conflicts - ) - - def counted(*arguments: Any) -> list[tuple[int, str, str, str]]: - found: list[tuple[int, str, str, str]] = conflicts(*arguments) - statuses["calls"] += 1 - statuses["conflicts"] += len(found) - return found - - monkeypatch.setattr(native_module, "native_promotion_conflicts", counted) - return statuses - - -def deferral_records(directory: Path) -> list[dict[str, str]]: - """Every deferral record written under `directory`, in file order.""" - - lines: Iterator[str] = itertools.chain.from_iterable( - path.read_text(encoding="utf-8").splitlines() - for path in sorted(directory.glob("analysis-deferrals-*.jsonl")) - ) - return [json.loads(line) for line in lines] - - def with_declared_type(*, project: CompiledProject, declared_type: str) -> CompiledProject: """The project with its enforced staging model declaring `declared_type` for every column.""" diff --git a/tests/integration/src/sqlbuild/compiler/contracts/test_native_model_contracts.py b/tests/integration/src/sqlbuild/compiler/contracts/test_native_model_contracts.py index 27d295ce33..2e21d0a4f0 100644 --- a/tests/integration/src/sqlbuild/compiler/contracts/test_native_model_contracts.py +++ b/tests/integration/src/sqlbuild/compiler/contracts/test_native_model_contracts.py @@ -1,39 +1,41 @@ -"""Native contract validation and promotion conflicts equal Python's on generated projects.""" +"""Native contract validation on generated projects and on inputs Python once answered.""" from __future__ import annotations import random -from collections import Counter from pathlib import Path import pytest from sqlbuild.compiler.compile.models import CompiledProject -from sqlbuild.compiler.sql_analysis.constants import ANALYSIS_RECORD_DIR_ENV_VAR from tests.integration.src.sqlbuild.compiler.contracts._test_types import ( - DeferredContractTestCase, - GeneratedContractParityTestCase, - GeneratedPromotionParityTestCase, + FormerlyDeferredContractTestCase, + GeneratedContractTestCase, + UnknownDialectContractTestCase, ) from tests.integration.src.sqlbuild.compiler.contracts.helpers import ( + ContractView, NativeContractRecord, compiled_contract_project, - contract_views, - deferral_records, + contract_diagnostics, + diagnostic_view, perturbed_project, - promotion_settings, - promotion_views, record_native_outcomes, - record_native_promotion_calls, with_declared_type, ) -from tests.integration.src.sqlbuild.compiler.helpers import mismatches +from tests.integration.src.sqlbuild.compiler.helpers import ( + GoldenEntry, + golden_differences, + golden_entry, + golden_name, + read_golden, +) @pytest.mark.parametrize( "test_case", [ - GeneratedContractParityTestCase( + GeneratedContractTestCase( description="enforced, implicit, typed, nullability and dynamic contracts", seed=20261009, variants=60, @@ -46,119 +48,156 @@ ], ids=lambda case: case.description, ) -def test_given_generated_contracts_when_validating_natively_then_diagnostics_match_python( - test_case: GeneratedContractParityTestCase, +def test_given_generated_contracts_when_validating_then_every_contract_family_is_answered( + test_case: GeneratedContractTestCase, tmp_path: Path, monkeypatch: pytest.MonkeyPatch, ) -> None: rng: random.Random = random.Random(test_case.seed) record: NativeContractRecord = record_native_outcomes(monkeypatch=monkeypatch) - base: CompiledProject = compiled_contract_project(project_dir=tmp_path / "project") - labels: list[object] = [] - python_views: list[object] = [] - native_views: list[object] = [] - for variant in range(test_case.variants): + project_dir: Path = tmp_path / "project" + base: CompiledProject = compiled_contract_project(project_dir=project_dir) + golden: list[GoldenEntry] = [] + for _ in range(test_case.variants): project: CompiledProject = perturbed_project(project=base, rng=rng) - for dialect in test_case.dialects: - python, native = contract_views( - project=project, dialect=dialect, monkeypatch=monkeypatch + golden.append( + golden_entry( + "contracts", + { + str(dialect): diagnostic_view( + diagnostics=contract_diagnostics(project=project, dialect=dialect), + project_dir=project_dir, + ) + for dialect in test_case.dialects + }, ) - labels.append((variant, dialect)) - python_views.append(python) - native_views.append(native) - - assert mismatches(inputs=labels, expected=python_views, actual=native_views) == [] - assert record.statuses["native"] >= test_case.expected_minimum_native - assert record.statuses["typed_comparisons"] >= test_case.expected_minimum_typed_comparisons - assert record.statuses["native_diagnostics"] >= test_case.expected_minimum_diagnostics - assert set(record.codes) >= test_case.expected_codes - - -@pytest.mark.parametrize( - "test_case", - [ - GeneratedPromotionParityTestCase( - description="lifecycle configs under explicit and adapter-default promotion modes", - seed=20261010, - variants=400, - expected_minimum_conflicts=30, ) - ], - ids=lambda case: case.description, -) -def test_given_generated_lifecycles_when_finding_promotion_conflicts_natively_then_match_python( - test_case: GeneratedPromotionParityTestCase, - tmp_path: Path, - monkeypatch: pytest.MonkeyPatch, -) -> None: - rng: random.Random = random.Random(test_case.seed) - base: CompiledProject = compiled_contract_project(project_dir=tmp_path / "project") - calls: Counter[str] = record_native_promotion_calls(monkeypatch=monkeypatch) - labels: list[object] = [] - python_views: list[object] = [] - native_views: list[object] = [] - for variant in range(test_case.variants): - project: CompiledProject = perturbed_project(project=base, rng=rng) - adapter_default, settings_file = promotion_settings(rng=rng) - python, native = promotion_views( - project=project, - adapter_default=adapter_default, - settings_file=settings_file, - monkeypatch=monkeypatch, - ) - labels.append(variant) - python_views.append(python) - native_views.append(native) - assert mismatches(inputs=labels, expected=python_views, actual=native_views) == [] - assert calls["calls"] == test_case.variants - assert calls["conflicts"] >= test_case.expected_minimum_conflicts + assert ( + golden_differences( + read_golden(golden_name("contracts_generated", test_case.description)), golden + ) + == [] + ) + assert ( + record.statuses["native"] >= test_case.expected_minimum_native, + record.statuses["typed_comparisons"] >= test_case.expected_minimum_typed_comparisons, + record.statuses["native_diagnostics"] >= test_case.expected_minimum_diagnostics, + set(record.codes) >= test_case.expected_codes, + ) == (True, True, True, True), test_case.description @pytest.mark.parametrize( "test_case", [ - DeferredContractTestCase( - description="a declared type outside ASCII", + FormerlyDeferredContractTestCase( + description="a declared type outside ASCII upper-cases as Python does", declared_type="TÉXT", dialect="duckdb", - expected_kind="type_normalization", - expected_deferred_models=1, + expected_diagnostics=( + ( + "K002", + "customer_totals", + "total_amount", + "column 'total_amount' inferred as DOUBLE but declared type is DECIMAL(18,2)", + ), + ( + "K005", + "stg_orders", + "customer_id", + "column 'customer_id' is not declared in enforced contract for model 'stg_orders'", + ), + ( + "K005", + "stg_orders", + "status", + "column 'status' is not declared in enforced contract for model 'stg_orders'", + ), + ( + "K002", + "stg_orders", + "order_id", + "column 'order_id' inferred as INTEGER but declared type is TÉXT", + ), + ( + "K002", + "stg_orders", + "amount", + "column 'amount' inferred as DOUBLE but declared type is TÉXT", + ), + ), ), - DeferredContractTestCase( - description="a dialect outside the native type system", + FormerlyDeferredContractTestCase( + description="a dialect outside the old native build", declared_type="INTEGER", dialect="mysql", - expected_kind="type_normalization", - expected_deferred_models=2, + expected_diagnostics=( + ( + "K002", + "customer_totals", + "total_amount", + "column 'total_amount' inferred as DOUBLE but declared type is DECIMAL(18,2)", + ), + ( + "K005", + "stg_orders", + "customer_id", + "column 'customer_id' is not declared in enforced contract for model 'stg_orders'", + ), + ( + "K005", + "stg_orders", + "status", + "column 'status' is not declared in enforced contract for model 'stg_orders'", + ), + ( + "K002", + "stg_orders", + "amount", + "column 'amount' inferred as DOUBLE but declared type is INTEGER", + ), + ), ), ], ids=lambda case: case.description, ) -def test_given_input_native_cannot_answer_when_validating_then_python_answers_and_it_is_recorded( - test_case: DeferredContractTestCase, - tmp_path: Path, - monkeypatch: pytest.MonkeyPatch, +def test_given_input_python_once_answered_when_validating_then_native_diagnostics_are_returned( + test_case: FormerlyDeferredContractTestCase, tmp_path: Path ) -> None: - record_dir: Path = tmp_path / "records" - record: NativeContractRecord = record_native_outcomes(monkeypatch=monkeypatch) project: CompiledProject = with_declared_type( project=compiled_contract_project(project_dir=tmp_path / "project"), declared_type=test_case.declared_type, ) - monkeypatch.setenv(ANALYSIS_RECORD_DIR_ENV_VAR, str(record_dir)) - python, native = contract_views( - project=project, dialect=test_case.dialect, monkeypatch=monkeypatch - ) + diagnostics: ContractView = contract_diagnostics(project=project, dialect=test_case.dialect) - assert native == python - assert record.statuses[test_case.expected_kind] == test_case.expected_deferred_models assert ( - deferral_records(record_dir) - == [{"kind": test_case.expected_kind, "site": "contracts/columns.py"}] - * test_case.expected_deferred_models - ) + tuple( + (diagnostic.code, diagnostic.resource_name, diagnostic.column_name, diagnostic.message) + for diagnostic in diagnostics + ) + == test_case.expected_diagnostics + ), test_case.description + + +@pytest.mark.parametrize( + "test_case", + [ + UnknownDialectContractTestCase( + description="a dialect Polyglot does not know raises the wheel's error", + dialect="motherduck", + expected_error="Unknown dialect: motherduck", + ), + ], + ids=lambda case: case.description, +) +def test_given_unknown_dialect_when_validating_typed_contracts_then_python_error_is_raised( + test_case: UnknownDialectContractTestCase, tmp_path: Path +) -> None: + project: CompiledProject = compiled_contract_project(project_dir=tmp_path / "project") + + with pytest.raises(ValueError, match=test_case.expected_error): + _ = contract_diagnostics(project=project, dialect=test_case.dialect) if __name__ == "__main__": diff --git a/tests/integration/src/sqlbuild/compiler/discovery/_test_types.py b/tests/integration/src/sqlbuild/compiler/discovery/_test_types.py index ce3c94f921..c7dbc3e5a1 100644 --- a/tests/integration/src/sqlbuild/compiler/discovery/_test_types.py +++ b/tests/integration/src/sqlbuild/compiler/discovery/_test_types.py @@ -47,15 +47,6 @@ class LargeDocumentOracleTestCase: expected_maximum_seconds: float = 2.0 -@dataclass(frozen=True) -class EngineSwitchParityTestCase: - """A project discovered through `discover_project_inputs` under each engine.""" - - description: str - files: tuple[tuple[str, bytes], ...] - expected_identical: bool = True - - @dataclass(frozen=True) class NativeRuntimeTestCase: """A project and runtime under which native model discovery runs or fails clearly.""" diff --git a/tests/integration/src/sqlbuild/compiler/discovery/helpers.py b/tests/integration/src/sqlbuild/compiler/discovery/helpers.py index 33223ae925..64308bde13 100644 --- a/tests/integration/src/sqlbuild/compiler/discovery/helpers.py +++ b/tests/integration/src/sqlbuild/compiler/discovery/helpers.py @@ -1235,8 +1235,8 @@ def generated_declaration_outcomes( write_project( project_dir=project_dir, files=((test_case.relative_path, contents.encode("utf-8")),) ) - python: tuple[object, ...] = declaration_files_outcome( - project_dir=project_dir, kind=test_case.kind, engine="python", monkeypatch=monkeypatch + shipped: tuple[object, ...] = declaration_files_outcome( + project_dir=project_dir, kind=test_case.kind, engine="native", monkeypatch=monkeypatch ) native: tuple[object, ...] = declaration_files_outcome( project_dir=project_dir, @@ -1249,7 +1249,7 @@ def generated_declaration_outcomes( file_path=project_dir / test_case.relative_path, kind=test_case.kind ) ] += 1 - agreements.append(native == python) + agreements.append(native == shipped) return tuple(compress(range(test_case.case_count), map(not_, agreements))), tags diff --git a/tests/integration/src/sqlbuild/compiler/discovery/test_deep_header_values.py b/tests/integration/src/sqlbuild/compiler/discovery/test_deep_header_values.py index 669e057847..f81951c945 100644 --- a/tests/integration/src/sqlbuild/compiler/discovery/test_deep_header_values.py +++ b/tests/integration/src/sqlbuild/compiler/discovery/test_deep_header_values.py @@ -35,7 +35,7 @@ description="every container kind at the limit beneath 300 extra frames", header=_AT_LIMIT_HEADER, stack_frames=300, - expected_engines=("python", "native", "native-preview"), + expected_engines=("native", "native-preview"), expected_max_depth=769, ) ], diff --git a/tests/integration/src/sqlbuild/compiler/discovery/test_discovery_failure_text.py b/tests/integration/src/sqlbuild/compiler/discovery/test_discovery_failure_text.py index 7cff580a22..808d10524b 100644 --- a/tests/integration/src/sqlbuild/compiler/discovery/test_discovery_failure_text.py +++ b/tests/integration/src/sqlbuild/compiler/discovery/test_discovery_failure_text.py @@ -18,7 +18,7 @@ write_project, ) -_ENGINES: tuple[str, ...] = ("python", "native", "native-preview") +_ENGINES: tuple[str, ...] = ("native", "native-preview") _MODEL: tuple[str, bytes] = ("models/orders.sql", b"MODEL ();\nSELECT 1 AS order_id") _HOOK: tuple[str, bytes] = ("hooks/sql/refresh.sql", b"HOOK (descri\x00ption 'x');\nSELECT 1") _CONSTANT: tuple[str, bytes] = ("constants/limits.sql", b"CONSTANT (name cap, valu\x00e 1);") @@ -101,12 +101,12 @@ def test_given_failing_project_when_discovering_then_every_engine_shows_authored ], ids=lambda case: case.description, ) -def test_given_nul_header_keys_when_discovering_tolerantly_then_faults_match_python( +def test_given_nul_header_keys_when_discovering_tolerantly_then_faults_match( test_case: TolerantFailureTextTestCase, tmp_path: Path, monkeypatch: pytest.MonkeyPatch ) -> None: write_project(project_dir=tmp_path, files=test_case.files) - python: tuple[object, tuple[DiscoveryFileFault, ...], tuple[DiscoveryFileFault, ...]] = ( - tolerant_declaration_outcome(project_dir=tmp_path, engine="python", monkeypatch=monkeypatch) + shipped: tuple[object, tuple[DiscoveryFileFault, ...], tuple[DiscoveryFileFault, ...]] = ( + tolerant_declaration_outcome(project_dir=tmp_path, engine="native", monkeypatch=monkeypatch) ) native: tuple[object, tuple[DiscoveryFileFault, ...], tuple[DiscoveryFileFault, ...]] = ( @@ -115,7 +115,7 @@ def test_given_nul_header_keys_when_discovering_tolerantly_then_faults_match_pyt ) ) - assert native == python + assert native == shipped assert ( tuple(sorted(fault.message.rsplit("keys: ", 1)[1] for fault in (*native[1], *native[2]))) == test_case.expected_fault_keys diff --git a/tests/integration/src/sqlbuild/compiler/discovery/test_native_declaration_discovery.py b/tests/integration/src/sqlbuild/compiler/discovery/test_native_declaration_discovery.py deleted file mode 100644 index 27e9443978..0000000000 --- a/tests/integration/src/sqlbuild/compiler/discovery/test_native_declaration_discovery.py +++ /dev/null @@ -1,72 +0,0 @@ -"""Engine parity for the declaration layout native discovery walks and validates.""" - -from __future__ import annotations - -from pathlib import Path - -import pytest - -from tests.integration.src.sqlbuild.compiler.discovery._test_types import ( - EngineSwitchParityTestCase, -) -from tests.integration.src.sqlbuild.compiler.discovery.helpers import ( - stage_outcome, - write_project, -) - -_AUDIT: bytes = b'AUDIT ();\n\nSELECT *\nFROM __ref("@model")\nWHERE NOT (@expression)\n' -_SCHEMA: bytes = ( - b'SCHEMA (\n name order_shape,\n description "Order shape",\n' - b" columns (\n id (type INTEGER),\n ),\n);\n" -) -_HOOK: bytes = b'HOOK (\n description "Record a refresh"\n);\n\nSELECT 1 AS refreshed\n' -_MACRO: bytes = b"def cents(value):\n return f'{value} * 100'\n" -_MODEL: bytes = b'MODEL (description "Orders");\nSELECT 1 AS order_id' - - -@pytest.mark.parametrize( - "test_case", - [ - EngineSwitchParityTestCase( - description="global, inherited, local and grouped declarations of every kind", - files=( - ("models/marts/orders.sql", _MODEL), - ("macros/money.py", _MACRO), - ("macros/__init__.py", b""), - ("enums/status.sql", b"ENUM (name order_status, members [PLACED]);\n"), - ("models/marts/_enums/tier.sql", b"ENUM (name tier, members [GOLD]);\n"), - ("models/marts/_sqlbuild/constants/limits.sql", b"CONSTANT (name cap, value 3);\n"), - ("models/marts/_sqlbuild/_audits/generic/is_true.sql", _AUDIT), - ("models/marts/_sqlbuild/_schemas/order_shape.sql", _SCHEMA), - ("models/marts/_sqlbuild/hooks/sql/record_refresh.sql", _HOOK), - ("audits/generic/is_true.sql", _AUDIT), - ("schemas/order_shape.sql", _SCHEMA), - ("hooks/sql/_private.sql", _HOOK), - ("functions/sql/_macros/helpers.py", _MACRO), - ("seeds/channels.csv", b"id\n1\n"), - ), - ), - EngineSwitchParityTestCase( - description="a nested declaration root fails with Python's error", - files=(("models/marts/_enums/macros/money.py", _MACRO),), - ), - EngineSwitchParityTestCase( - description="an unsupported audit role entry fails with Python's error", - files=(("models/marts/orders.sql", _MODEL), ("audits/is_true.sql", _AUDIT)), - ), - EngineSwitchParityTestCase( - description="an unreadable declaration file fails with Python's read error", - files=(("enums/status.sql", b"\xff"),), - ), - ], - ids=lambda case: case.description, -) -def test_given_declaration_layout_when_discovering_through_the_engine_switch_then_inputs_match( - test_case: EngineSwitchParityTestCase, tmp_path: Path, monkeypatch: pytest.MonkeyPatch -) -> None: - write_project(project_dir=tmp_path, files=test_case.files) - python: object = stage_outcome(project_dir=tmp_path, engine="python", monkeypatch=monkeypatch) - - native: object = stage_outcome(project_dir=tmp_path, engine="native", monkeypatch=monkeypatch) - - assert (native == python) is test_case.expected_identical, test_case.description diff --git a/tests/integration/src/sqlbuild/compiler/discovery/test_native_declaration_files.py b/tests/integration/src/sqlbuild/compiler/discovery/test_native_declaration_files.py index cbea4e7bcd..09855850ca 100644 --- a/tests/integration/src/sqlbuild/compiler/discovery/test_native_declaration_files.py +++ b/tests/integration/src/sqlbuild/compiler/discovery/test_native_declaration_files.py @@ -269,15 +269,15 @@ def test_given_declaration_files_when_discovering_through_the_engine_switch_then test_case: DeclarationFilesParityTestCase, tmp_path: Path, monkeypatch: pytest.MonkeyPatch ) -> None: write_project(project_dir=tmp_path, files=test_case.files) - python: tuple[object, ...] = stage_outcome( - project_dir=tmp_path, engine="python", monkeypatch=monkeypatch + shipped: tuple[object, ...] = stage_outcome( + project_dir=tmp_path, engine="native", monkeypatch=monkeypatch ) native: tuple[object, ...] = stage_outcome( project_dir=tmp_path, engine=_PREVIEW, monkeypatch=monkeypatch ) - assert native == python + assert native == shipped assert native[1] == test_case.expected_failure_type assert test_case.expected_message_fragment in str(native[2]) @@ -334,15 +334,15 @@ def test_given_deeply_nested_declaration_header_when_discovering_then_engines_re nested: str = "[" * test_case.depth + "1" + "]" * test_case.depth contents: str = test_case.prefix + nested + test_case.suffix write_project(project_dir=tmp_path, files=((test_case.relative_path, contents.encode()),)) - python: tuple[object, ...] = declaration_files_outcome( - project_dir=tmp_path, kind=test_case.kind, engine="python", monkeypatch=monkeypatch + shipped: tuple[object, ...] = declaration_files_outcome( + project_dir=tmp_path, kind=test_case.kind, engine="native", monkeypatch=monkeypatch ) native: tuple[object, ...] = declaration_files_outcome( project_dir=tmp_path, kind=test_case.kind, engine=_PREVIEW, monkeypatch=monkeypatch ) - assert native == python + assert native == shipped assert native[0] == test_case.expected_failure_type assert str(native[1]).endswith(test_case.expected_message_suffix), native[1] assert native[2] == test_case.expected_help @@ -376,15 +376,15 @@ def test_given_broken_declaration_files_when_discovering_tolerantly_then_faults_ test_case: TolerantDeclarationFilesTestCase, tmp_path: Path, monkeypatch: pytest.MonkeyPatch ) -> None: write_project(project_dir=tmp_path, files=test_case.files) - python: tuple[object, tuple[DiscoveryFileFault, ...], tuple[DiscoveryFileFault, ...]] = ( - tolerant_declaration_outcome(project_dir=tmp_path, engine="python", monkeypatch=monkeypatch) + shipped: tuple[object, tuple[DiscoveryFileFault, ...], tuple[DiscoveryFileFault, ...]] = ( + tolerant_declaration_outcome(project_dir=tmp_path, engine="native", monkeypatch=monkeypatch) ) native: tuple[object, tuple[DiscoveryFileFault, ...], tuple[DiscoveryFileFault, ...]] = ( tolerant_declaration_outcome(project_dir=tmp_path, engine=_PREVIEW, monkeypatch=monkeypatch) ) - assert native == python + assert native == shipped assert len(native[1]) == test_case.expected_resource_faults assert len(native[2]) == test_case.expected_declaration_faults @@ -402,11 +402,6 @@ def test_given_broken_declaration_files_when_discovering_tolerantly_then_faults_ engine="native", expected_session=True, ), - NativeSessionTestCase( - description="the Python engine keeps it too, since declaration files are native-only", - engine="python", - expected_session=True, - ), ], ids=lambda case: case.description, ) diff --git a/tests/integration/src/sqlbuild/compiler/discovery/test_native_model_discovery.py b/tests/integration/src/sqlbuild/compiler/discovery/test_native_model_discovery.py index 400211148f..f8793afb29 100644 --- a/tests/integration/src/sqlbuild/compiler/discovery/test_native_model_discovery.py +++ b/tests/integration/src/sqlbuild/compiler/discovery/test_native_model_discovery.py @@ -15,12 +15,8 @@ discover_native_model_files, ) from sqlbuild.compiler.discovery.classes.directory_snapshot import DirectorySnapshot -from sqlbuild.compiler.discovery.main.discover import discover_project_inputs from sqlbuild.compiler.discovery.models import DiscoveredSqlModelFile -from sqlbuild.compiler.frontier._helpers.stage_capture import render_stage_capture -from sqlbuild.compiler.frontier.constants import COMPILER_ENGINE_ENV_VAR from tests.integration.src.sqlbuild.compiler.discovery._test_types import ( - EngineSwitchParityTestCase, NativeRuntimeTestCase, SharedSnapshotTestCase, UnsupportedPythonCommandTestCase, @@ -33,35 +29,6 @@ _VALID_MODEL: bytes = b"MODEL (materialized table);\nSELECT order_id, total AS amount FROM orders" -@pytest.mark.parametrize( - "test_case", - [ - EngineSwitchParityTestCase( - description="models, model-local declarations and a macro", - files=( - ("models/orders.sql", _VALID_MODEL), - ( - "models/marts/customers.sql", - b"MODEL (enums (_tier [GOLD, SILVER]));\nSELECT 1 AS id", - ), - ("macros/money.py", b"def cents(value):\n return f'{value} * 100'\n"), - ), - ), - ], - ids=lambda case: case.description, -) -def test_given_project_when_discovering_through_the_engine_switch_then_inputs_match( - test_case: EngineSwitchParityTestCase, tmp_path: Path, monkeypatch: pytest.MonkeyPatch -) -> None: - write_project(project_dir=tmp_path, files=test_case.files) - monkeypatch.setenv(COMPILER_ENGINE_ENV_VAR, "python") - python: str = render_stage_capture(discover_project_inputs(project_dir=tmp_path)) - monkeypatch.setenv(COMPILER_ENGINE_ENV_VAR, "native") - native: str = render_stage_capture(discover_project_inputs(project_dir=tmp_path)) - - assert (native == python) is test_case.expected_identical - - @pytest.mark.parametrize( "test_case", [ diff --git a/tests/integration/src/sqlbuild/compiler/discovery/test_native_sql_test_discovery.py b/tests/integration/src/sqlbuild/compiler/discovery/test_native_sql_test_discovery.py deleted file mode 100644 index 957191f4c1..0000000000 --- a/tests/integration/src/sqlbuild/compiler/discovery/test_native_sql_test_discovery.py +++ /dev/null @@ -1,66 +0,0 @@ -"""Engine parity for SQL unit-test and scenario files discovered natively.""" - -from __future__ import annotations - -from pathlib import Path - -import pytest - -from tests.integration.src.sqlbuild.compiler.discovery._test_types import ( - EngineSwitchParityTestCase, -) -from tests.integration.src.sqlbuild.compiler.discovery.helpers import ( - stage_outcome, - write_project, -) - -_TEST: bytes = b'TEST (name "keeps_orders");\n\nSELECT 1\n' -_SCENARIO: bytes = b'SCENARIO (description "Orders world");\n\nSELECT 1\n' - - -@pytest.mark.parametrize( - "test_case", - [ - EngineSwitchParityTestCase( - description="test and scenario files in nested, macro and scoped folders", - files=( - ("models/orders.sql", b'MODEL (description "Orders");\nSELECT 1 AS order_id'), - ("tests/unit/orders.sql", _TEST), - ("tests/unit/marts/b.sql", _TEST), - ("tests/unit/macros/money.sql", _TEST), - ("tests/unit/marts/_macros/helpers.py", b"def cents(value):\n return value\n"), - ("tests/unit/marts/_sqlbuild/enums/status.sql", b"ENUM (name s, members [A]);\n"), - ("tests/scenarios/north/orders.sql", _SCENARIO), - ("tests/scenarios/south.sql", _SCENARIO), - ), - ), - EngineSwitchParityTestCase( - description="the first failing test file in path order wins", - files=( - ("tests/unit/a.sql", _TEST), - ("tests/unit/b.sql", b"\xff"), - ("tests/unit/c.sql", b"TEST (nme 1);\nSELECT 1"), - ), - ), - EngineSwitchParityTestCase( - description="a semantic failure in an earlier block beats a later syntax failure", - files=( - ("tests/unit/a.sql", b"TEST (mode bogus);\nSELECT 1\nTEST (name ();\nSELECT 2"), - ), - ), - EngineSwitchParityTestCase( - description="an unreadable scenario fails with Python's read error", - files=(("tests/scenarios/a.sql", b"SCENARIO ();\n\xfe"),), - ), - ], - ids=lambda case: case.description, -) -def test_given_test_files_when_discovering_through_the_engine_switch_then_inputs_match( - test_case: EngineSwitchParityTestCase, tmp_path: Path, monkeypatch: pytest.MonkeyPatch -) -> None: - write_project(project_dir=tmp_path, files=test_case.files) - python: object = stage_outcome(project_dir=tmp_path, engine="python", monkeypatch=monkeypatch) - - native: object = stage_outcome(project_dir=tmp_path, engine="native", monkeypatch=monkeypatch) - - assert (native == python) is test_case.expected_identical, test_case.description diff --git a/tests/integration/src/sqlbuild/compiler/discovery/test_native_yaml_file_discovery.py b/tests/integration/src/sqlbuild/compiler/discovery/test_native_yaml_file_discovery.py index f5fe19f68a..aa2c21dd88 100644 --- a/tests/integration/src/sqlbuild/compiler/discovery/test_native_yaml_file_discovery.py +++ b/tests/integration/src/sqlbuild/compiler/discovery/test_native_yaml_file_discovery.py @@ -7,12 +7,10 @@ import pytest from tests.integration.src.sqlbuild.compiler.discovery._test_types import ( - EngineSwitchParityTestCase, NativeYamlLoadTestCase, ) from tests.integration.src.sqlbuild.compiler.discovery.helpers import ( native_yaml_tags_and_values, - stage_outcome, write_project, ) @@ -29,51 +27,6 @@ ) -@pytest.mark.parametrize( - "test_case", - [ - EngineSwitchParityTestCase( - description="sources, model schema and seed declarations", - files=( - ("sources/orders.yml", _SOURCES), - ("sources/more.yaml", _SOURCES.replace(b"raw_orders", b"raw_customers")), - ("sources/notes.txt", b"ignored"), - ("models/orders.sql", b'MODEL (description "Orders");\nSELECT 1 AS order_id'), - ("models/marts/schema.yml", b"models: []\n"), - ("models/marts/_sqlbuild/schemas/schema.yml", b"models: []\n"), - ("seeds/channels.yml", _SEED), - ("seeds/channels.csv", b"id\n1\n"), - ), - ), - EngineSwitchParityTestCase( - description="a Python-only tag and invalid YAML load in Python with its error", - files=( - ("sources/a.yml", b"sources: []\nextra: !!set {a: null}\n"), - ("sources/b.yml", b"sources: [\n"), - ), - ), - EngineSwitchParityTestCase( - description="an unreadable source file fails with Python's read error", - files=(("sources/a.yml", b"sources: []\n# \xff\n"),), - ), - EngineSwitchParityTestCase( - description="a directory named like a source file fails as Python reads it", - files=(("sources/folder.yml/inner.txt", b""),), - ), - ], - ids=lambda case: case.description, -) -def test_given_yaml_files_when_discovering_through_the_engine_switch_then_inputs_match( - test_case: EngineSwitchParityTestCase, tmp_path: Path, monkeypatch: pytest.MonkeyPatch -) -> None: - write_project(project_dir=tmp_path, files=test_case.files) - python: object = stage_outcome(project_dir=tmp_path, engine="python", monkeypatch=monkeypatch) - - native: object = stage_outcome(project_dir=tmp_path, engine="native", monkeypatch=monkeypatch) - - assert (native == python) is test_case.expected_identical, test_case.description - - @pytest.mark.parametrize( "test_case", [ diff --git a/tests/integration/src/sqlbuild/compiler/model_loop/__init__.py b/tests/integration/src/sqlbuild/compiler/explicit_references/__init__.py similarity index 100% rename from tests/integration/src/sqlbuild/compiler/model_loop/__init__.py rename to tests/integration/src/sqlbuild/compiler/explicit_references/__init__.py diff --git a/tests/integration/src/sqlbuild/compiler/explicit_references/_test_types.py b/tests/integration/src/sqlbuild/compiler/explicit_references/_test_types.py new file mode 100644 index 0000000000..51f33a25d8 --- /dev/null +++ b/tests/integration/src/sqlbuild/compiler/explicit_references/_test_types.py @@ -0,0 +1,13 @@ +from __future__ import annotations + +from dataclasses import dataclass + + +@dataclass(frozen=True) +class ExplicitReferenceGoldenTestCase: + """Projects whose explicit-reference outcomes must equal Python's recorded golden.""" + + description: str + projects: tuple[tuple[str, dict[str, str], str], ...] + expected_codes: frozenset[str] + expected_raised: int diff --git a/tests/integration/src/sqlbuild/compiler/explicit_references/helpers.py b/tests/integration/src/sqlbuild/compiler/explicit_references/helpers.py new file mode 100644 index 0000000000..79e719e046 --- /dev/null +++ b/tests/integration/src/sqlbuild/compiler/explicit_references/helpers.py @@ -0,0 +1,438 @@ +"""Projects whose explicit-reference checks raise or report, and their full compile outcomes.""" + +from __future__ import annotations + +from collections.abc import Callable +from operator import attrgetter +from pathlib import Path +from typing import Any, cast + +from sqlbuild.adapters.duckdb.classes.duckdb_adapter import DuckDbAdapter +from sqlbuild.compiler.compile.main._assemble_project import assemble_project +from sqlbuild.compiler.compile.main._build_compile_inputs import build_compile_inputs +from sqlbuild.compiler.compile.models import ( + CompileAdapterContext, + CompiledProject, + CompilerDiagnostic, + LiteralSqlRelation, +) +from sqlbuild.compiler.discovery.main.discover import discover_project_inputs +from sqlbuild.sql_values.types import CollectionRendering + +_ADAPTER_CONTEXT: CompileAdapterContext = CompileAdapterContext( + value_renderer=DuckDbAdapter(), + collection_rendering=CollectionRendering.VALUE_LIST, + python_functions_inherit_default_namespace=True, + sql_lexical_syntax=DuckDbAdapter.sql_lexical_syntax, +) +_PROJECT: str = ( + 'name = "orders_project"\nadapter = "duckdb"\n\n' + "[settings]\nsql_analysis = false\nsql_validation = false\n" +) +_DISABLED: str = _PROJECT + "\n[references]\nenforce_explicit = false\n" +_OLD_NAMES_OFF: str = _PROJECT + "\n[migrations]\nold_name_views = false\n" +_HOOK_PATH: str = "models/marts/_sqlbuild/_hooks/python/lookups.py" +_SQL_HOOK_PATH: str = "models/marts/_sqlbuild/_hooks/sql/record_rows.sql" +_TASK_PATH: str = "python/tasks/export.py" +_CHECK_PATH: str = "python/checks/orders.py" +_ASSET_PATH: str = "python/assets/snapshot.py" +_LOADER_PATH: str = "python/loaders/raw.py" +_HOOKED: str = 'MODEL (description "Orders.", post_hooks [python("refresh_lookup")]);' +_NAMED_SQL_HOOK: str = 'MODEL (description "Orders.", post_hooks [sql("record_rows")]);' + + +def _model(sql: str, header: str = 'MODEL (description "Test model.");') -> str: + return f"{header}\n{sql}\n" + + +def _hook( + *, reads: str = "()", body: str = " return None\n", name: str = "refresh_lookup" +) -> str: + return ( + "from sqlbuild.hooks import hook\nfrom sqlbuild.refs import model, seed, source\n\n\n" + f"@hook(reads={reads})\ndef {name}(ctx):\n{body}" + ) + + +def _task(body: str, depends_on: str = 'model("orders")') -> str: + return ( + "from sqlbuild.refs import model, source\nfrom sqlbuild.tasks import task\n\n\n" + f"@task(depends_on={depends_on})\ndef export_orders(ctx):\n{body}" + ) + + +def _check(body: str) -> str: + return ( + "from sqlbuild.checks import check\nfrom sqlbuild.refs import model\n\n\n" + '@check(depends_on=model("orders"))\ndef orders_present(ctx):\n' + f"{body} return ctx.pass_()\n" + ) + + +def _asset(body: str) -> str: + return ( + "from sqlbuild.assets import asset\nfrom sqlbuild.refs import model\n\n\n" + '@asset(depends_on=model("orders"))\ndef orders_snapshot(context):\n' + f' """Test asset."""\n{body} return None\n' + ) + + +def _loaders(*, depends_on: str, body: str) -> str: + return ( + "from sqlbuild.loaders import loader\n\n\n" + "@loader\ndef raw_regions(ctx):\n '''Test loader raw_regions.'''\n" + " return [{'id': 1}]\n\n\n" + f"@loader(depends_on=[{depends_on}])\ndef raw_customers(ctx):\n{body}" + " return [{'id': 1}]\n" + ) + + +_MODELS: dict[str, str] = { + "models/marts/customers.sql": _model("SELECT 1 AS customer_id"), + "models/marts/orders.sql": _model("SELECT 1 AS order_id", header=_HOOKED), +} +_SEED: dict[str, str] = { + "seeds/country_codes.yml": ( + "seeds:\n - name: country_codes\n description: Country codes.\n" + " columns:\n - name: code\n type: VARCHAR\n" + ), + "seeds/country_codes.csv": "code\nGB\n", +} +_MANAGED: dict[str, str] = { + "sources/raw.yml": ( + "sources:\n" + " - name: raw_regions\n description: Raw regions.\n managed: true\n" + " write_strategy: table\n columns:\n - name: id\n type: INTEGER\n" + " - name: raw_customers\n description: Raw customers.\n managed: true\n" + " write_strategy: table\n columns:\n - name: id\n type: INTEGER\n" + ), +} +_EXTERNAL: dict[str, str] = { + "sources/landing.yml": ( + "sources:\n - name: landing_orders\n description: Landing orders.\n" + " schema: landing\n table: orders_feed\n" + " - name: computed\n description: Computed.\n expression: SELECT 1 AS id\n" + ), +} +_GATED_AUDIT: str = "AUDIT ();\nSELECT s.* FROM @relation s LEFT JOIN {read} a USING (code)" + + +def _gate_model(sql: str, audits: str) -> str: + return _model(sql, header=f'MODEL (description "Gated.", audits [{audits}]);') + + +# (description, files, project toml) +EXPLICIT_REFERENCE_PROJECTS: tuple[tuple[str, dict[str, str], str], ...] = ( + ( + "task literal SQL reading a managed source and a model", + { + **_MODELS, + **_MANAGED, + _HOOK_PATH: _hook(), + _LOADER_PATH: _loaders(depends_on="", body=""), + _TASK_PATH: _task( + ' ctx.query("SELECT * FROM raw_customers JOIN customers ON true")\n' + ' ctx.execute_sql(sql="DELETE FROM main.orders")\n' + ), + }, + _PROJECT, + ), + ( + "every owner kind, dedup on one line and line ordering across files", + { + **_MODELS, + **_SEED, + _HOOK_PATH: _hook( + reads='model("customers")', + body=( + ' ctx.query("SELECT * FROM orders JOIN customers ON true")\n' + ' ctx.query("SELECT * FROM country_codes, COUNTRY_CODES")\n' + ), + ), + _TASK_PATH: _task( + ' ctx.query("SELECT * FROM customers c1 JOIN customers c2 ON true")\n' + " ctx.query(**{'sql': 'SELECT * FROM \"Orders\"'})\n" + ), + _CHECK_PATH: _check(' ctx.query("SELECT count(*) FROM memory.main.customers")\n'), + _ASSET_PATH: _asset(' context.query("SELECT 1 FROM orders")\n'), + }, + _PROJECT, + ), + ( + "temporary tables, f-string placeholders, external and unparseable SQL", + { + **_MODELS, + **_EXTERNAL, + _HOOK_PATH: _hook(), + _TASK_PATH: _task( + ' ctx.query("CREATE TEMP TABLE customers AS SELECT 1")\n' + ' ctx.query("SELECT * FROM customers JOIN main.customers ON true")\n' + ' ctx.query(f"SELECT * FROM {ctx.schema}.orders ' + 'JOIN warehouse.events ON true")\n' + ' ctx.query(f"SELECT * FROM orders_{1} JOIN landing.orders_feed ON true")\n' + ' ctx.query("SELECT * FROM computed JOIN external_lookup ON true")\n' + ' ctx.query("SELEC broken FROM (")\n' + " ctx.query(sql_text)\n" + ), + }, + _PROJECT, + ), + ( + "loaders read their own, upstream and other sources and models", + { + **_MODELS, + **_MANAGED, + **_SEED, + _HOOK_PATH: _hook(), + _LOADER_PATH: _loaders( + depends_on="raw_regions", + body=( + ' ctx.query("SELECT * FROM raw_customers JOIN raw_regions ON true")\n' + ' ctx.query("SELECT * FROM customers JOIN country_codes ON true")\n' + ), + ), + }, + _PROJECT, + ), + ( + "loader with no upstream loader reads another managed source", + { + **_MODELS, + **_MANAGED, + _HOOK_PATH: _hook(), + _LOADER_PATH: _loaders( + depends_on="", + body=' ctx.query("SELECT * FROM raw_regions")\n', + ), + }, + _PROJECT, + ), + ( + "old names kept as compatibility views", + { + "models/marts/customers.sql": _model( + "SELECT 1 AS customer_id", + header=( + 'MODEL (description "Customers.", materialized table, ' + "migrate_from legacy_customers);" + ), + ), + "models/marts/orders.sql": _model( + "SELECT 1 AS order_id", + header=( + 'MODEL (description "Orders.", materialized table, ' + 'migrate_from "archive.old_orders");' + ), + ), + "models/marts/regions.sql": _model( + "SELECT 1 AS region_id", + header=( + 'MODEL (description "Regions.", materialized table, migrate_from customers);' + ), + ), + _TASK_PATH: _task( + ' ctx.query("SELECT * FROM legacy_customers JOIN archive.old_orders ON true")\n' + ' ctx.query("SELECT * FROM main.LEGACY_CUSTOMERS")\n' + ), + }, + _PROJECT, + ), + ( + "old names off leave old relations unmatched", + { + "models/marts/customers.sql": _model( + "SELECT 1 AS customer_id", + header=( + 'MODEL (description "Customers.", materialized table, ' + "migrate_from legacy_customers);" + ), + ), + "models/marts/orders.sql": _model("SELECT 1 AS order_id"), + _TASK_PATH: _task(' ctx.query("SELECT * FROM legacy_customers")\n'), + }, + _OLD_NAMES_OFF, + ), + ( + "enforcement disabled still checks hooks and audits", + { + **_MODELS, + _HOOK_PATH: _hook(reads='model("customers")'), + _TASK_PATH: _task(' ctx.query("SELECT * FROM customers")\n'), + }, + _DISABLED, + ), + ( + "python hook declaring an unknown model read", + { + **_MODELS, + _HOOK_PATH: _hook(reads='model("missing_customers")'), + _TASK_PATH: _task(' ctx.query("SELECT * FROM customers")\n'), + }, + _PROJECT, + ), + ( + "unknown hook reads raise for the first hook by name", + { + **_MODELS, + _HOOK_PATH: ( + _hook(reads='(seed("nope"), model("customers"))', name="z_hook") + + "\n\n" + + _hook(reads='source("missing")', name="a_hook").split("\n\n\n", 1)[1] + + "\n\n" + + _hook(name="refresh_lookup").split("\n\n\n", 1)[1] + ), + }, + _PROJECT, + ), + ( + "python and sql hooks reading their own dependants", + { + _HOOK_PATH: _hook(reads='model("customers")'), + _SQL_HOOK_PATH: ( + 'HOOK (description "Records rows.");\n' + 'INSERT INTO audit_log SELECT count(*) FROM __ref("item_totals")\n' + ), + "models/marts/orders.sql": _model("SELECT 1 AS order_id", header=_HOOKED), + "models/marts/customers.sql": _model('SELECT * FROM __ref("orders")'), + "models/marts/items.sql": _model("SELECT 1 AS item_id", header=_NAMED_SQL_HOOK), + "models/marts/item_totals.sql": _model( + 'SELECT * FROM __ref("items")', + header=( + 'MODEL (description "Totals.", pre_hooks ' + "[inline_sql('SELECT * FROM __ref(\"item_rollup\")')]);" + ), + ), + "models/marts/item_rollup.sql": _model('SELECT * FROM __ref("item_totals")'), + }, + _PROJECT, + ), + ( + "attached audits reading their targets' dependants", + { + **_SEED, + **_EXTERNAL, + "audits/generic/gated_lookup.sql": _GATED_AUDIT.format(read='__ref("enriched")'), + "audits/generic/source_lookup.sql": _GATED_AUDIT.format(read='__ref("landing_view")'), + "models/marts/base.sql": _gate_model("SELECT 'GB' AS code", "gated_lookup"), + "models/marts/enriched.sql": _model('SELECT * FROM __ref("base")'), + "audits/generic/seed_lookup.sql": _GATED_AUDIT.format(read='__ref("coded")'), + "models/marts/landing_view.sql": _model('SELECT * FROM __source("landing_audited")'), + "models/marts/coded.sql": _model('SELECT * FROM __seed("audited_codes")'), + "sources/landing_audits.yml": ( + "sources:\n - name: landing_audited\n description: Landing audited.\n" + " schema: landing\n audits:\n - source_lookup\n" + ), + "seeds/audited_codes.yml": ( + "seeds:\n - name: audited_codes\n description: Audited codes.\n" + " columns:\n - name: code\n type: VARCHAR\n" + " audits:\n - seed_lookup\n" + ), + "seeds/audited_codes.csv": "code\nGB\n", + }, + _PROJECT, + ), + ( + "audit gates, hook cycles and hard-coded names together", + { + "audits/generic/gated_lookup.sql": _GATED_AUDIT.format(read='__ref("enriched")'), + "models/marts/base.sql": _gate_model("SELECT 'GB' AS code", "gated_lookup"), + "models/marts/enriched.sql": _model('SELECT * FROM __ref("base")'), + _HOOK_PATH: _hook( + reads='model("customers")', + body=' ctx.query("SELECT * FROM legacy_orders JOIN orders ON true")\n', + ), + "models/marts/orders.sql": _model( + "SELECT 1 AS order_id", + header=( + 'MODEL (description "Orders.", materialized table, ' + 'migrate_from legacy_orders, post_hooks [python("refresh_lookup")]);' + ), + ), + "models/marts/customers.sql": _model('SELECT * FROM __ref("orders")'), + _TASK_PATH: _task(' ctx.query("SELECT * FROM enriched")\n'), + }, + _PROJECT, + ), +) + + +def write_project(*, project_dir: Path, files: dict[str, str], toml: str) -> None: + """Write the project config and files below `project_dir`.""" + + _ = [ + _write(path=project_dir / relative, contents=contents) + for relative, contents in {"sqlbuild_project.toml": toml, **files}.items() + ] + + +def compile_outcome(*, project_dir: Path) -> tuple[object, ...]: + """Assemble the project: every diagnostic and unmatched relation, or the error raised.""" + + try: + project: CompiledProject = assemble_project( + inputs=build_compile_inputs( + discovered_inputs=discover_project_inputs(project_dir=project_dir), + adapter_context=_ADAPTER_CONTEXT, + run_id="explicit_references", + ), + skip_column_inference=True, + ) + except Exception as error: + return ( + "error", + type(error).__name__, + str(error), + getattr(error, "code", None), + getattr(error, "help", None), + ) + return ( + "ok", + tuple(_diagnostic_view(diagnostic) for diagnostic in project.diagnostics), + tuple(_unmatched_view(relation) for relation in project.unmatched_literal_sql_relations), + ) + + +def _diagnostic_view(diagnostic: CompilerDiagnostic) -> tuple[object, ...]: + return ( + str(diagnostic.phase), + str(diagnostic.severity), + diagnostic.code, + diagnostic.message, + _optional(diagnostic.path, Path.as_posix), + diagnostic.line, + _optional(diagnostic.location, attrgetter("column")), + _optional(diagnostic.resource_type, str), + diagnostic.resource_name, + diagnostic.help, + ) + + +def _optional(value: Any, convert: Callable[[Any], object]) -> object: + """`convert(value)`, or None where `value` is None.""" + + return {True: lambda: None, False: lambda: convert(value)}[value is None]() + + +def outcome_codes(outcome: tuple[object, ...]) -> tuple[object, ...]: + """The diagnostic codes of a successful outcome; none for a raised error.""" + + return { + "ok": lambda: tuple(diagnostic[2] for diagnostic in cast(Any, outcome[1])), + "error": tuple, + }[cast(str, outcome[0])]() + + +def _unmatched_view(relation: LiteralSqlRelation) -> tuple[object, ...]: + return ( + relation.owner_label, + str(relation.owner_kind), + relation.relative_path.as_posix(), + relation.line, + relation.method, + (relation.relation.database, relation.relation.schema, relation.relation.name), + ) + + +def _write(*, path: Path, contents: str) -> int: + path.parent.mkdir(parents=True, exist_ok=True) + return path.write_text(contents, encoding="utf-8") diff --git a/tests/integration/src/sqlbuild/compiler/explicit_references/test_native_explicit_references.py b/tests/integration/src/sqlbuild/compiler/explicit_references/test_native_explicit_references.py new file mode 100644 index 0000000000..a25d35f57d --- /dev/null +++ b/tests/integration/src/sqlbuild/compiler/explicit_references/test_native_explicit_references.py @@ -0,0 +1,69 @@ +"""Native explicit-reference checks report Python's recorded diagnostics, order and errors.""" + +from __future__ import annotations + +from itertools import chain +from pathlib import Path + +import pytest + +from tests.integration.src.sqlbuild.compiler.explicit_references._test_types import ( + ExplicitReferenceGoldenTestCase, +) +from tests.integration.src.sqlbuild.compiler.explicit_references.helpers import ( + EXPLICIT_REFERENCE_PROJECTS, + compile_outcome, + outcome_codes, + write_project, +) +from tests.integration.src.sqlbuild.compiler.helpers import ( + GoldenEntry, + golden_differences, + golden_entry, + golden_name, + read_golden, +) + + +@pytest.mark.parametrize( + "test_case", + [ + ExplicitReferenceGoldenTestCase( + description="edge projects", + projects=EXPLICIT_REFERENCE_PROJECTS, + expected_codes=frozenset({"P005", "P007", "P008"}), + expected_raised=2, + ) + ], + ids=lambda case: case.description, +) +def test_given_reference_edge_projects_when_compiling_then_matches_python_golden( + test_case: ExplicitReferenceGoldenTestCase, tmp_path: Path +) -> None: + project_dirs: list[Path] = [ + tmp_path / f"project_{index}" for index in range(len(test_case.projects)) + ] + _ = [ + write_project(project_dir=project_dir, files=files, toml=toml) + for project_dir, (_, files, toml) in zip(project_dirs, test_case.projects, strict=True) + ] + outcomes: list[tuple[object, ...]] = [ + compile_outcome(project_dir=project_dir) for project_dir in project_dirs + ] + golden: list[GoldenEntry] = [ + golden_entry("explicit_references", outcome, masked=(str(project_dir),)) + for project_dir, outcome in zip(project_dirs, outcomes, strict=True) + ] + codes: frozenset[object] = frozenset(chain.from_iterable(map(outcome_codes, outcomes))) + + assert ( + golden_differences( + read_golden(golden_name("explicit_references", test_case.description)), golden + ), + test_case.expected_codes <= codes, + sum(outcome[0] == "error" for outcome in outcomes), + ) == ([], True, test_case.expected_raised) + + +if __name__ == "__main__": + pytest.main([__file__, "-vv"]) diff --git a/tests/integration/src/sqlbuild/compiler/helpers.py b/tests/integration/src/sqlbuild/compiler/helpers.py index 1043358d25..4b6a6df9d4 100644 --- a/tests/integration/src/sqlbuild/compiler/helpers.py +++ b/tests/integration/src/sqlbuild/compiler/helpers.py @@ -2,15 +2,22 @@ from __future__ import annotations +import dataclasses +import functools +import hashlib +import itertools import json import math import random +import re import struct from collections.abc import Callable from contextlib import suppress +from enum import Enum from itertools import compress from operator import ne from pathlib import Path +from typing import Any, cast import orjson @@ -337,3 +344,185 @@ def mutated_word(*, rng: random.Random, candidates: list[str]) -> str: for _ in range(rng.randint(0, 4)): rng.choice(MUTATIONS)(rng=rng, word=word, position=rng.randint(0, len(word))) return "".join(word) + + +GOLDEN_DIR: Path = Path(__file__).resolve().parents[4] / "goldens" / "python_oracle" + +type GoldenEntry = list[object] +type GoldenDifference = tuple[int, str, object, object] + + +def canonical(value: object) -> object: + """A JSON value standing for `value`, equal exactly when the Python values are equal.""" + + return _CANONICAL_VIEWS[_canonical_kind(value)](value) + + +def _canonical_kind(value: object) -> str: + kinds: tuple[tuple[str, bool], ...] = ( + ("enum", isinstance(value, Enum)), + ("dataclass", dataclasses.is_dataclass(value) and not isinstance(value, type)), + ("dict", isinstance(value, dict)), + ("sequence", isinstance(value, list | tuple)), + ("set", isinstance(value, frozenset | set)), + ("scalar", value is None or isinstance(value, bool | int | float | str)), + ("repr", True), + ) + return _first_matching(kinds) + + +def _canonical_enum(value: object) -> object: + return [type(value).__name__, canonical(cast(Enum, value).value)] + + +def _canonical_dataclass(value: object) -> object: + fields: tuple[dataclasses.Field[object], ...] = dataclasses.fields(cast(Any, value)) + return [ + type(value).__name__, + {field.name: canonical(getattr(value, field.name)) for field in fields}, + ] + + +def _canonical_dict(value: object) -> object: + items: list[tuple[object, object]] = sorted( + cast(dict[object, object], value).items(), + key=lambda pair: json.dumps(canonical(pair[0]), sort_keys=True), + ) + return [["key", canonical(key), canonical(item)] for key, item in items] + + +def _canonical_sequence(value: object) -> object: + return [type(value).__name__, [canonical(item) for item in cast(tuple[object, ...], value)]] + + +def _canonical_set(value: object) -> object: + return ["set", sorted((canonical(item) for item in cast(set[object], value)), key=json.dumps)] + + +_CANONICAL_VIEWS: dict[str, Callable[[object], object]] = { + "enum": _canonical_enum, + "dataclass": _canonical_dataclass, + "dict": _canonical_dict, + "sequence": _canonical_sequence, + "set": _canonical_set, + "scalar": lambda value: value, + "repr": lambda value: ["repr", repr(value)], +} + + +def digest(value: object, *, masked: tuple[str, ...] = ()) -> str: + """The short SHA-256 of `value`'s canonical JSON, with `masked` texts replaced.""" + + text: str = functools.reduce( + lambda current, mask: current.replace(mask, ""), + masked, + json.dumps(canonical(value), sort_keys=True, ensure_ascii=False), + ) + return hashlib.sha256(text.encode()).hexdigest()[:24] + + +def golden_entry(kind: str, view: object, *, masked: tuple[str, ...] = ()) -> GoldenEntry: + """One seam call's golden entry: a digest per named item for mappings, else one digest.""" + + entries: tuple[Callable[[], GoldenEntry], ...] = ( + lambda: [kind, digest(view, masked=masked)], + lambda: [ + kind, + { + str(name): digest(item, masked=masked) + for name, item in cast(dict[object, object], view).items() + }, + ], + ) + return entries[isinstance(view, dict)]() + + +def golden_name(prefix: str, description: str) -> str: + """The golden file name of a test case: its prefix and its description as a slug.""" + + return f"{prefix}_{re.sub(r'[^a-z0-9]+', '_', description.lower()).strip('_')}" + + +def read_golden(name: str) -> list[GoldenEntry]: + """The entries recorded once from the pre-port Python implementation, in call order.""" + + return json.loads((GOLDEN_DIR / f"{name}.json").read_text(encoding="utf-8")) + + +def write_golden(name: str, entries: list[GoldenEntry]) -> None: + """Record one golden file; used only by the one-off oracle recording.""" + + GOLDEN_DIR.mkdir(parents=True, exist_ok=True) + _ = (GOLDEN_DIR / f"{name}.json").write_text( + json.dumps(entries, indent=0, sort_keys=True) + "\n", encoding="utf-8" + ) + + +def golden_differences( + expected: list[GoldenEntry], actual: list[GoldenEntry] +) -> list[GoldenDifference]: + """`(index, kind, expected, actual)` for every entry that differs, names compared one by one.""" + + pairs: list[tuple[GoldenEntry | None, GoldenEntry | None]] = list( + itertools.zip_longest(expected, actual) + ) + return list( + itertools.chain.from_iterable( + _entry_differences(index, want, got) for index, (want, got) in enumerate(pairs) + ) + ) + + +def _entry_differences( + index: int, want: GoldenEntry | None, got: GoldenEntry | None +) -> list[GoldenDifference]: + kinds: tuple[tuple[str, bool], ...] = ( + ("equal", want == got), + ("named", _named_entries(want, got)), + ("whole", True), + ) + kind: str = _first_matching(kinds) + return _ENTRY_DIFFERENCES[kind](index, want, got) + + +def _named_entries(want: GoldenEntry | None, got: GoldenEntry | None) -> bool: + return ( + want is not None + and got is not None + and want[0] == got[0] + and isinstance(want[1], dict) + and isinstance(got[1], dict) + ) + + +def _named_differences( + index: int, want: GoldenEntry | None, got: GoldenEntry | None +) -> list[GoldenDifference]: + kind: object = cast(GoldenEntry, want)[0] + want_digests: dict[str, object] = cast(dict[str, object], cast(GoldenEntry, want)[1]) + got_digests: dict[str, object] = cast(dict[str, object], cast(GoldenEntry, got)[1]) + names: list[str] = sorted({*want_digests, *got_digests}) + differing: list[bool] = [want_digests.get(name) != got_digests.get(name) for name in names] + return [ + (index, f"{kind}:{name}", want_digests.get(name), got_digests.get(name)) + for name in itertools.compress(names, differing) + ] + + +def _whole_difference( + index: int, want: GoldenEntry | None, got: GoldenEntry | None +) -> list[GoldenDifference]: + return [(index, str((want or got or ["?"])[0]), want and want[1], got and got[1])] + + +_ENTRY_DIFFERENCES: dict[ + str, Callable[[int, GoldenEntry | None, GoldenEntry | None], list[GoldenDifference]] +] = { + "equal": lambda _index, _want, _got: [], + "named": _named_differences, + "whole": _whole_difference, +} + + +def _first_matching(kinds: tuple[tuple[str, bool], ...]) -> str: + return next(itertools.compress([kind for kind, _ in kinds], [matches for _, matches in kinds])) diff --git a/tests/integration/src/sqlbuild/compiler/lineage/_test_types.py b/tests/integration/src/sqlbuild/compiler/lineage/_test_types.py index e56e9b4f5e..5abec348b2 100644 --- a/tests/integration/src/sqlbuild/compiler/lineage/_test_types.py +++ b/tests/integration/src/sqlbuild/compiler/lineage/_test_types.py @@ -5,7 +5,7 @@ @dataclass(frozen=True) class GeneratedLineageParityTestCase: - """Seeded generated projects whose fast lineage Python and the native engine must agree on.""" + """Seeded generated projects whose fast lineage must not depend on the analysis catalog.""" description: str seed: int @@ -17,14 +17,14 @@ class GeneratedLineageParityTestCase: @dataclass(frozen=True) -class DeferredLineageTestCase: - """Parsed models the native engine hands back to Python, which records each deferral.""" +class FormerlyDeferredLineageTestCase: + """Parsed models Python once built, now answered natively or raising Python's error.""" description: str dialect: str keeps_catalog: bool expected_native_statuses: dict[str, int] - expected_kind: str + expected_error: str | None @dataclass(frozen=True) @@ -35,3 +35,13 @@ class UnparsedLineageTestCase: query_sql: str expected_status: str expected_messages: tuple[str, ...] + + +@dataclass(frozen=True) +class ParserPanicLineageTestCase: + """A model whose SQL panics the native parser, failing lineage as an internal error.""" + + description: str + dialect: str + query_sql: str + expected_message: str diff --git a/tests/integration/src/sqlbuild/compiler/lineage/helpers.py b/tests/integration/src/sqlbuild/compiler/lineage/helpers.py index 4a6af823e5..bcc175b0bd 100644 --- a/tests/integration/src/sqlbuild/compiler/lineage/helpers.py +++ b/tests/integration/src/sqlbuild/compiler/lineage/helpers.py @@ -14,7 +14,6 @@ from sqlbuild.adapters.duckdb.classes.duckdb_adapter import DuckDbAdapter from sqlbuild.compiler.compile.models import CompiledProject from sqlbuild.compiler.discovery.main.discover import discover_project_inputs -from sqlbuild.compiler.lineage._helpers.fast_columns import build_fast_project_column_lineage from sqlbuild.compiler.lineage.main._build_native_column_lineage import ( build_native_column_lineage, ) @@ -210,7 +209,7 @@ def generated_lineage_files(*, rng: random.Random, model_count: int) -> dict[str def compiled_project(*, project_dir: Path, files: dict[str, str]) -> CompiledProject: - """Write and compile a project with the Python compiler, keeping any diagnostics.""" + """Write and compile a project, keeping any diagnostics.""" for relative_path, contents in files.items(): path: Path = project_dir / relative_path @@ -236,24 +235,14 @@ def lineage_views( project: CompiledProject, dialect: str | None, model_names: frozenset[str] | None, -) -> tuple[list[object], list[object], list[object]]: - """Each public lineage view's name, Python's value and the native stage's value.""" +) -> tuple[list[object], list[object]]: + """Each public view of the native fast lineage: its name and value.""" - python: ProjectColumnLineage = cast( - ProjectColumnLineage, - build_fast_project_column_lineage( - project=project, dialect=dialect, model_names=model_names - ), - ) - native: ProjectColumnLineage = cast( + lineage: ProjectColumnLineage = cast( ProjectColumnLineage, - build_native_column_lineage(project=project, dialect=dialect, model_names=model_names) - or build_fast_project_column_lineage( - project=project, dialect=dialect, model_names=model_names - ), + build_native_column_lineage(project=project, dialect=dialect, model_names=model_names), ) - names, python_values = _public_views(project=project, lineage=python) - return names, python_values, _public_views(project=project, lineage=native)[1] + return _public_views(project=project, lineage=lineage) def _public_views( diff --git a/tests/integration/src/sqlbuild/compiler/lineage/test_native_fast_lineage.py b/tests/integration/src/sqlbuild/compiler/lineage/test_native_fast_lineage.py index 9894d30670..fd01d583e1 100644 --- a/tests/integration/src/sqlbuild/compiler/lineage/test_native_fast_lineage.py +++ b/tests/integration/src/sqlbuild/compiler/lineage/test_native_fast_lineage.py @@ -1,4 +1,4 @@ -"""Native fast column lineage equals Python's on generated projects, model by model.""" +"""Native fast column lineage: Python-oracle goldens, restored projects and internal failures.""" from __future__ import annotations @@ -10,17 +10,25 @@ import pytest +import sqlbuild._native as native_module from sqlbuild.compiler.compile.models import CompiledProject -from sqlbuild.compiler.lineage._helpers.fast_columns import build_fast_project_column_lineage from sqlbuild.compiler.lineage.main._build_native_column_lineage import ( build_native_column_lineage, ) from sqlbuild.compiler.lineage.models import ProjectColumnLineage from sqlbuild.compiler.sql_analysis.constants import ANALYSIS_RECORD_DIR_ENV_VAR -from tests.integration.src.sqlbuild.compiler.helpers import mismatches +from tests.integration.src.sqlbuild.compiler.helpers import ( + GoldenEntry, + golden_differences, + golden_entry, + golden_name, + mismatches, + read_golden, +) from tests.integration.src.sqlbuild.compiler.lineage._test_types import ( - DeferredLineageTestCase, + FormerlyDeferredLineageTestCase, GeneratedLineageParityTestCase, + ParserPanicLineageTestCase, UnparsedLineageTestCase, ) from tests.integration.src.sqlbuild.compiler.lineage.helpers import ( @@ -51,7 +59,7 @@ ], ids=lambda case: case.description, ) -def test_given_generated_projects_when_building_fast_lineage_natively_then_matches_python( +def test_given_generated_projects_when_building_fast_lineage_then_restored_projects_agree( test_case: GeneratedLineageParityTestCase, tmp_path: Path, monkeypatch: pytest.MonkeyPatch, @@ -59,6 +67,7 @@ def test_given_generated_projects_when_building_fast_lineage_natively_then_match rng: random.Random = random.Random(test_case.seed) statuses: Counter[str] = record_native_outcomes(monkeypatch=monkeypatch) differences: list[tuple[object, object, object]] = [] + golden: list[GoldenEntry] = [] for index in range(test_case.count): project: CompiledProject = compiled_project( project_dir=tmp_path / f"project_{index}", @@ -70,13 +79,35 @@ def test_given_generated_projects_when_building_fast_lineage_natively_then_match for variant in (project, without_compact_facts(project)): for dialect in test_case.dialects: for model_names in (None, selected): - names, python_views, native_views = lineage_views( + names, with_catalog = lineage_views( project=variant, dialect=dialect, model_names=model_names ) + golden.append( + golden_entry( + "lineage", + { + f"{position}:{name}": view + for position, (name, view) in enumerate( + zip(names, with_catalog, strict=True) + ) + }, + ) + ) + _, restored = lineage_views( + project=replace(variant, binding_catalog=None), + dialect=dialect, + model_names=model_names, + ) differences.extend( - mismatches(inputs=names, expected=python_views, actual=native_views) + mismatches(inputs=names, expected=with_catalog, actual=restored) ) + assert ( + golden_differences( + read_golden(golden_name("fast_lineage_generated", test_case.description)), golden + ) + == [] + ) assert differences == [] assert statuses["deferred"] == 0 assert sum(statuses.values()) >= test_case.expected_minimum_native @@ -102,7 +133,7 @@ def test_given_generated_projects_when_building_fast_lineage_natively_then_match ], ids=lambda case: case.description, ) -def test_given_unparsable_model_when_building_fast_lineage_then_logs_and_omits_like_python( +def test_given_unparsable_model_when_building_fast_lineage_then_logs_and_omits_it( test_case: UnparsedLineageTestCase, tmp_path: Path, monkeypatch: pytest.MonkeyPatch, @@ -122,44 +153,39 @@ def test_given_unparsable_model_when_building_fast_lineage_then_logs_and_omits_l ) with caplog.at_level(logging.DEBUG, logger="sqlbuild.lineage"): - python: ProjectColumnLineage | None = build_fast_project_column_lineage(project=broken) - python_records: list[tuple[str, str, object]] = lineage_log_records(caplog) - caplog.clear() native: ProjectColumnLineage | None = build_native_column_lineage( project=broken, dialect=None, model_names=None ) native_records: list[tuple[str, str, object]] = lineage_log_records(caplog) - assert native == python assert native is not None assert not native.has_model(project.models[0].name) assert statuses[test_case.expected_status] == 1 - assert native_records == python_records assert tuple(message for _, message, _ in native_records) == test_case.expected_messages @pytest.mark.parametrize( "test_case", [ - DeferredLineageTestCase( - description="a dialect outside the native parser build", + FormerlyDeferredLineageTestCase( + description="a dialect outside the old native parser build", dialect="mysql", keeps_catalog=True, - expected_native_statuses={"deferred": _MODEL_COUNT}, - expected_kind="unsupported_dialect", + expected_native_statuses={"built": _MODEL_COUNT}, + expected_error=None, ), - DeferredLineageTestCase( - description="a project without an analysis catalog to run on", + FormerlyDeferredLineageTestCase( + description="a project restored without its analysis catalog", dialect="duckdb", keeps_catalog=False, - expected_native_statuses={}, - expected_kind="no_analysis_catalog", + expected_native_statuses={"built": _MODEL_COUNT}, + expected_error=None, ), ], ids=lambda case: case.description, ) -def test_given_deferred_models_when_building_fast_lineage_then_python_builds_and_records( - test_case: DeferredLineageTestCase, +def test_given_formerly_deferred_models_when_building_fast_lineage_then_native_answers( + test_case: FormerlyDeferredLineageTestCase, tmp_path: Path, monkeypatch: pytest.MonkeyPatch, ) -> None: @@ -176,15 +202,84 @@ def test_given_deferred_models_when_building_fast_lineage_then_python_builds_and compiled, binding_catalog=(None, compiled.binding_catalog)[test_case.keeps_catalog] ) - names, python_views, native_views = lineage_views( - project=project, dialect=test_case.dialect, model_names=None + _ = lineage_views(project=project, dialect=test_case.dialect, model_names=None) + + assert statuses == Counter(test_case.expected_native_statuses), test_case.description + assert deferral_records(record_dir) == [] + + +@pytest.mark.parametrize( + "test_case", + [ + FormerlyDeferredLineageTestCase( + description="a dialect name Polyglot does not know raises Python's error", + dialect="nonsense", + keeps_catalog=True, + expected_native_statuses={"unknown_dialect": _MODEL_COUNT}, + expected_error="Unknown dialect: nonsense", + ), + ], + ids=lambda case: case.description, +) +def test_given_unknown_dialect_when_building_fast_lineage_then_python_error_raises( + test_case: FormerlyDeferredLineageTestCase, + tmp_path: Path, + monkeypatch: pytest.MonkeyPatch, +) -> None: + record_dir: Path = tmp_path / "records" + monkeypatch.setenv(ANALYSIS_RECORD_DIR_ENV_VAR, str(record_dir)) + statuses: Counter[str] = record_native_outcomes(monkeypatch=monkeypatch) + compiled: CompiledProject = without_compact_facts( + compiled_project( + project_dir=tmp_path / "project", + files=generated_lineage_files(rng=random.Random(7), model_count=_MODEL_COUNT), + ) ) + project: CompiledProject = replace( + compiled, binding_catalog=(None, compiled.binding_catalog)[test_case.keeps_catalog] + ) + + with pytest.raises(ValueError, match=test_case.expected_error): + _ = lineage_views(project=project, dialect=test_case.dialect, model_names=None) - assert mismatches(inputs=names, expected=python_views, actual=native_views) == [] - assert statuses == Counter(test_case.expected_native_statuses) - assert deferral_records(record_dir) == ( - [{"kind": test_case.expected_kind, "site": "fast_columns.py"}] * _MODEL_COUNT + assert statuses == Counter(test_case.expected_native_statuses), test_case.description + assert deferral_records(record_dir) == [] + + +@pytest.mark.parametrize( + "test_case", + [ + ParserPanicLineageTestCase( + description="truncated T-SQL the parser panics on, which crashes the wheel's process", + dialect="tsql", + query_sql="SELECT IF(region > 1, re", + expected_message=( + "NativeCompilerError: native SQL compilation panicked " + "(native fast lineage of request model 0)" + ), + ), + ], + ids=lambda case: case.description, +) +def test_given_parser_panic_when_building_fast_lineage_then_raises_native_compiler_error( + test_case: ParserPanicLineageTestCase, tmp_path: Path +) -> None: + project: CompiledProject = compiled_project( + project_dir=tmp_path / "project", + files=generated_lineage_files(rng=random.Random(11), model_count=_MODEL_COUNT), ) + broken: CompiledProject = replace( + project, + models=( + replace(project.models[0], query_sql=test_case.query_sql, fast_lineage_columns=None), + *project.models[1:], + ), + ) + + with pytest.raises(native_module.NativeCompilerError) as raised: + _ = build_native_column_lineage(project=broken, dialect=test_case.dialect, model_names=None) + + assert str(raised.value) == test_case.expected_message if __name__ == "__main__": diff --git a/tests/integration/src/sqlbuild/compiler/model_config/test_native_model_config.py b/tests/integration/src/sqlbuild/compiler/model_config/test_native_model_config.py index fdee70229f..7e88a5701c 100644 --- a/tests/integration/src/sqlbuild/compiler/model_config/test_native_model_config.py +++ b/tests/integration/src/sqlbuild/compiler/model_config/test_native_model_config.py @@ -49,14 +49,6 @@ def test_given_generated_header_metadata_when_parsing_then_native_matches_yaml_s @pytest.mark.parametrize( "test_case", [ - ModelConfigTierTestCase( - description="python oracle", - engine="python", - expected_native_calls={ - "parse_model_header_metadata": 2, - "expand_config_templates": 1, - }, - ), ModelConfigTierTestCase( description="shipped native stages", engine="native", @@ -82,13 +74,13 @@ def test_given_engine_tier_when_building_model_inputs_then_every_engine_runs_nat calls, config = model_config_engine_outcome( project_dir=tmp_path / test_case.engine, engine=test_case.engine, monkeypatch=monkeypatch ) - _, python_config = model_config_engine_outcome( - project_dir=tmp_path / "python", engine="python", monkeypatch=monkeypatch + _, shipped_config = model_config_engine_outcome( + project_dir=tmp_path / "shipped", engine="native", monkeypatch=monkeypatch ) - assert (calls, config.replace(test_case.engine, "python")) == ( + assert (calls, config.replace(test_case.engine, "shipped")) == ( test_case.expected_native_calls, - python_config, + shipped_config, ) diff --git a/tests/integration/src/sqlbuild/compiler/model_loop/_test_types.py b/tests/integration/src/sqlbuild/compiler/model_loop/_test_types.py deleted file mode 100644 index 9d48db4f9f..0000000000 --- a/tests/integration/src/sqlbuild/compiler/model_loop/_test_types.py +++ /dev/null @@ -1 +0,0 @@ -from __future__ import annotations diff --git a/tests/integration/src/sqlbuild/compiler/model_loop/helpers.py b/tests/integration/src/sqlbuild/compiler/model_loop/helpers.py deleted file mode 100644 index bc508ca764..0000000000 --- a/tests/integration/src/sqlbuild/compiler/model_loop/helpers.py +++ /dev/null @@ -1,175 +0,0 @@ -"""Generated SQL and declaration contexts for the native model loop parity tests.""" - -from __future__ import annotations - -import random -from pathlib import Path - -from sqlbuild.compiler.compile.models import ( - DeclarationResolutionContext, -) -from sqlbuild.compiler.discovery.models import ConstantDeclaration, EnumDeclaration, EnumMember -from sqlbuild.compiler.scopes.models import ( - DeclarationIdentity, - DeclarationRecord, - OwnershipRoot, - ResourceIdentity, - VisibilityRecord, -) -from sqlbuild.compiler.scopes.types import ( - DeclarationKind, - OwnershipRootKind, - ResourceKind, - ScopeKind, - VisibilityReason, -) -from sqlbuild.sql_values.main.normalize import normalize_sql_value - -_CONSUMER: ResourceIdentity = ResourceIdentity(ResourceKind.MODEL, "orders") -_FILE_PATH: Path = Path("models/orders.sql") -_ENUMS: dict[str, EnumDeclaration] = { - "order_status": EnumDeclaration( - "order_status", - (EnumMember("PLACED", "placed"), EnumMember("SHIPPED", 2), EnumMember("NOTED", "it's")), - "VARCHAR", - Path("enums/status.sql"), - ), -} -_CONSTANTS: dict[str, ConstantDeclaration] = { - "sales_cap": ConstantDeclaration( - "sales_cap", normalize_sql_value(raw_value=3, context="test"), Path("constants/cap.sql") - ), - "label": ConstantDeclaration( - "label", normalize_sql_value(raw_value="o'k \u00e9", context="test"), Path("c/label.sql") - ), - "regions": ConstantDeclaration( - "regions", - normalize_sql_value(raw_value=["north", "south"], context="test"), - Path("constants/regions.sql"), - ), - "quoted_note": ConstantDeclaration( - "quoted_note", - normalize_sql_value(raw_value="'" * 600_000, context="test"), - Path("constants/note.sql"), - ), -} -DECLARATIONS: DeclarationResolutionContext = DeclarationResolutionContext( - enums=_ENUMS, - constants=_CONSTANTS, - enum_visibility={ - "order_status": ( - VisibilityRecord( - _CONSUMER, - DeclarationIdentity(DeclarationKind.ENUM, "order_status"), - VisibilityReason.GLOBAL, - ), - ) - }, - constant_visibility={ - name: ( - VisibilityRecord( - _CONSUMER, - DeclarationIdentity(DeclarationKind.CONSTANT, name), - VisibilityReason.GLOBAL, - ), - ) - for name in _CONSTANTS - }, - inaccessible_enums={ - "staged_status": DeclarationRecord( - identity=DeclarationIdentity(DeclarationKind.ENUM, "staged_status"), - path="models/staging/_enums/status.sql", - line=1, - column=1, - scope=ScopeKind.LOCAL, - ownership_root=OwnershipRoot("models", OwnershipRootKind.RESOURCE, ResourceKind.MODEL), - owning_path="models/staging", - ) - }, - inaccessible_constants={ - "staged_cap": DeclarationRecord( - identity=DeclarationIdentity(DeclarationKind.CONSTANT, "staged_cap"), - path="models/staging/_constants/cap.sql", - line=1, - column=1, - scope=ScopeKind.INHERITED, - ownership_root=OwnershipRoot("models", OwnershipRootKind.RESOURCE, ResourceKind.MODEL), - owning_path="models/staging", - ) - }, - consumer=_CONSUMER, -) -_WHITESPACE: tuple[str, ...] = ("", " ", "\t", "\n ", "\x1c", "\u00a0", "\u2003") -_REFERENCES: tuple[str, ...] = ( - '@enum({s}"order_status"{s}){s}.{s}PLACED', - "@enum('order_status').SHIPPED", - '@enum("order_status").NOTED', - '@const("sales_cap")', - "@const({s}'label'{s})", - '@const("regions")', -) -_INVALID_REFERENCES: tuple[str, ...] = ( - '@enum("order_status").MISSING', - '@const("unknown_cap")', - '@const("_private_cap")', - '@enum("_private_status").PLACED', - '@enum("staged_status").PLACED', - '@const("staged_cap")', - '@const("quoted_note")', - '@enum("order_status")', - "@const(sales_cap)", - "@enum", - "@const\u00a0(", -) -_TEXT: tuple[str, ...] = ( - "SELECT ", - " FROM orders", - ", ", - "caf\u00e9 ", - "\U0001f600 ", - "@constant ", - "@enumerate ", - "price$1 ", - '$$ @const("sales_cap") $$', - '$tag$ @enum("x").Y $tag$', - "'@const(\"sales_cap\")'", - "'it''s'", - '"quoted @const(\\"label\\")"', - "`tick`", - '-- @const("sales_cap")\n', - '/* @enum("order_status").PLACED */', - "@\u00e9 ", -) -_RARE: tuple[str, ...] = ( - "'unterminated ", - "/* open ", - "`open ", - "$q$ open ", - "@const\u00e9 ", - *_INVALID_REFERENCES, - *_INVALID_REFERENCES, -) - - -def generated_reference_sql(*, rng: random.Random) -> str: - """Return SQL mixing references, quoted text, comments and Unicode in random order.""" - - return _reference_sql(rng=rng, rare_parts=int(rng.random() < 0.15)) - - -def _reference_sql(*, rng: random.Random, rare_parts: int) -> str: - parts: list[str] = [ - rng.choices((_reference_part, _text_part), weights=(4, 6))[0](rng) - for _ in range(rng.randint(1, 12)) - ] - parts.extend(rng.choices(_RARE, k=rare_parts)) - rng.shuffle(parts) - return "".join(parts) - - -def _reference_part(rng: random.Random) -> str: - return rng.choice(_REFERENCES).format(s=rng.choice(_WHITESPACE)) - - -def _text_part(rng: random.Random) -> str: - return rng.choice(_TEXT) diff --git a/tests/integration/src/sqlbuild/compiler/pipeline/_test_types.py b/tests/integration/src/sqlbuild/compiler/pipeline/_test_types.py index f34443dbe1..5a13a6279a 100644 --- a/tests/integration/src/sqlbuild/compiler/pipeline/_test_types.py +++ b/tests/integration/src/sqlbuild/compiler/pipeline/_test_types.py @@ -2,9 +2,7 @@ from collections.abc import Callable from dataclasses import dataclass, field -from pathlib import Path -from scripts.cold_compile_performance.models import RandomDagProject from sqlbuild.adapter.contract.classes.base_adapter import BaseAdapter @@ -15,6 +13,13 @@ class ExpressionMemoCase: expected_analysis_calls: int = 1 +@dataclass(frozen=True) +class RestoredShapeCase: + description: str + expressions: dict[str, str] + expected_shapes: dict[str, dict[str, str]] + + @dataclass(frozen=True) class ExpressionBatchCase: description: str @@ -359,18 +364,6 @@ class ReshapedStarLineageIntegrationTestCase: expected_sources: tuple[frozenset[tuple[str, str]], ...] -@dataclass(frozen=True) -class SharedBindingQueryCase: - description: str - orders_summary_sql: str - customers_summary_sql: str - expected_shared_queries: int - expected_codes: tuple[str, ...] = () - later_models: tuple[tuple[str, str], ...] = () - expected_lineage: tuple[tuple[str, str], ...] = () - expected_findings: tuple[tuple[str, str], ...] = () - - @dataclass(frozen=True) class SingularAuditAttachmentIntegrationTestCase: description: str @@ -397,113 +390,3 @@ class FunctionArgumentTypeCase: type PreparedCompile = tuple[ CompileOutcome, tuple[str, ...], dict[str, object | None], tuple[bytes, ...] ] - - -@dataclass(frozen=True) -class DataflowOracleCase: - description: str - project: RandomDagProject - reshaped_steps: tuple[tuple[int, ...], ...] - expected_exit_codes: tuple[int, ...] - compile_args: tuple[str, ...] = () - - -@dataclass(frozen=True) -class DataflowFixtureCase: - description: str - fixture: str - expected_exit_code: int - - -@dataclass(frozen=True) -class DataflowDenseCase: - description: str - model_count: int - expected_exit_codes: tuple[int, ...] - - -@dataclass(frozen=True) -class DataflowBuildCase: - description: str - project: RandomDagProject - expected_compile_exit_code: int - expected_build_exit_code: int - - -@dataclass(frozen=True) -class DataflowScheduleCase: - description: str - workers: int - batch_limit: int - max_delay_seconds: float - expected_cold_exit_code: int = 1 - expected_edit_exit_code: int = 1 - - -@dataclass(frozen=True) -class DataflowCaptureCase: - description: str - write_project: Callable[[Path], object] - schedules: tuple[DataflowScheduleCase, ...] - expected_exit_code: int - expected_minimum_shareable_members: int - expected_minimum_shared_reuse: int - expected_difference: str | None = None - - -@dataclass(frozen=True) -class DataflowFailureCase: - description: str - failing_models: tuple[str, ...] - expected_message: str - - -@dataclass(frozen=True) -class DataflowPoolCase: - description: str - compiles: int - minimum_batches: int - expected_pool_threads: int - - -@dataclass(frozen=True) -class DataflowInterruptCase: - description: str - expected_live_workers: tuple[str, ...] - expected_overlaps: tuple[str, ...] - expected_thread_errors: int - expected_notices: int - - -@dataclass(frozen=True) -class DataflowInterruptAfterFaultCase: - description: str - failing_model: str - interrupted_model: str - expected_wave_replays: int - - -@dataclass(frozen=True) -class DataflowStartFailureCase: - description: str - failing_start: int - interrupt_after_start: bool - expected_error_type: type[BaseException] - expected_error: str - expected_live_workers: tuple[str, ...] - expected_notices: int - - -@dataclass(frozen=True) -class BatchedPreparationCase: - description: str - write_project: Callable[[Path], tuple[str, ...]] - reshaped: tuple[int, ...] - expected_exit_code: int - - -@dataclass(frozen=True) -class PerturbedPreparationCase: - description: str - project: RandomDagProject - expected_payloads_match: bool diff --git a/tests/integration/src/sqlbuild/compiler/pipeline/helpers.py b/tests/integration/src/sqlbuild/compiler/pipeline/helpers.py index 21b584ac37..5dad53d70c 100644 --- a/tests/integration/src/sqlbuild/compiler/pipeline/helpers.py +++ b/tests/integration/src/sqlbuild/compiler/pipeline/helpers.py @@ -1,38 +1,17 @@ from __future__ import annotations -import itertools import json -import random -import shutil -import signal -import threading -import time -from collections.abc import Callable, Mapping, Sequence -from contextlib import suppress +from collections.abc import Callable from pathlib import Path -from types import ModuleType -from typing import Any, NamedTuple, cast +from typing import Any -import orjson import pytest -import sqlbuild._native as _native -from scripts.cold_compile_performance._helpers.dense_project import write_dense_compile_project -from scripts.cold_compile_performance._helpers.random_dag_project import write_random_dag_project -from scripts.cold_compile_performance.models import RandomDagProject +import sqlbuild._native as native_module from sqlbuild.adapter.contract.classes.base_adapter import BaseAdapter from sqlbuild.adapters.duckdb.classes.duckdb_adapter import DuckDbAdapter -from sqlbuild.cli.commands.main.entrypoint.entry import main -from sqlbuild.compiler.compile._helpers.analysis import compact -from sqlbuild.compiler.compile._helpers.analysis.compact import native_section -from sqlbuild.compiler.compile._helpers.assembly import binding_waves -from sqlbuild.compiler.compile._helpers.assembly import project as project_assembly -from sqlbuild.compiler.compile._helpers.assembly.binding_waves import analyze_binding_waves -from sqlbuild.compiler.compile._helpers.sharing import binding as binding_sharing -from sqlbuild.compiler.compile.classes.binding_dataflow import BindingDataflow from sqlbuild.compiler.compile.main._build_compile_inputs import build_compile_inputs from sqlbuild.compiler.compile.models import ( - CompactBatchPreparation, CompileAdapterContext, CompileAuditInput, CompiledLineageColumnFact, @@ -41,42 +20,14 @@ ) from sqlbuild.compiler.discovery.main.discover import discover_project_inputs from sqlbuild.compiler.discovery.models import DiscoveredProjectInputs -from sqlbuild.compiler.frontier.constants import STAGE_CAPTURE_DIR_ENV_VAR -from sqlbuild.compiler.frontier.types import CompilerStage from sqlbuild.compiler.manifest.main.build import build_manifest from sqlbuild.compiler.pipeline.main.compile import run_compile_pipeline from sqlbuild.compiler.pipeline.main.project import compile_project from sqlbuild.compiler.pipeline.models import CompilePipelineOptions, CompilePipelineResult -from sqlbuild.compiler.sql_analysis.main import _normalize_analysis_batch as normalize_batch -from sqlbuild.compiler.sql_analysis.types import NativePositionsModule, NativeProjectCatalog from sqlbuild.runtime.contracts.models import ConnectionHooks from sqlbuild.sql_values.types import CollectionRendering -from tests.integration.src.sqlbuild.compiler.pipeline._test_types import ( - CompileOutcome, - DataflowScheduleCase, - PreparedCompile, - SharedBindingQueryCase, -) - - -class CompiledProjectRun(NamedTuple): - """One cold compile's exit code, compiled-project capture and shared-analysis reuse.""" - - exit_code: int - capture: Path - shareable_members: int - deduplicated_queries: int - shared_memo_hits: int - - @property - def shared_reuse(self) -> int: - """Return how many member analyses were served by another member's analysis.""" - - return self.deduplicated_queries + self.shared_memo_hits - _REPOSITORY_ROOT: Path = Path(__file__).resolve().parents[6] -_NORMALIZATION_MODULES: tuple[ModuleType, ...] = (normalize_batch, binding_sharing, compact) _ANALYSIS_CACHE_METRICS: tuple[str, ...] = ( "analysis_batch_cache_hits", "analysis_entry_cache_hits", @@ -244,32 +195,6 @@ def lineage_source_pairs(column: CompiledLineageColumnFact) -> frozenset[tuple[s ) -def write_shared_binding_project(*, project_dir: Path, test_case: SharedBindingQueryCase) -> None: - (project_dir / "sqlbuild_project.toml").write_text( - 'name = "orders"\nadapter = "duckdb"\n[rules]\nselect = []\n' - ) - models: Path = project_dir / "models" - models.mkdir() - (models / "orders.sql").write_text(_SHARED_BINDING_UPSTREAM_SQL) - (models / "customers.sql").write_text(_SHARED_BINDING_UPSTREAM_SQL) - (models / "orders_summary.sql").write_text(test_case.orders_summary_sql) - (models / "customers_summary.sql").write_text(test_case.customers_summary_sql) - for name, sql in test_case.later_models: - (models / f"{name}.sql").write_text(sql) - - -def trace_native_compact_batches(monkeypatch: pytest.MonkeyPatch) -> list[CompactBatchPreparation]: - original: Callable[..., object] = compact._run_compact_analysis_batch - preparations: list[CompactBatchPreparation] = [] - - def traced(*, preparation: CompactBatchPreparation) -> object: - preparations.append(preparation) - return original(preparation=preparation) - - monkeypatch.setattr(compact, "_run_compact_analysis_batch", traced) - return preparations - - def apply_warehouse_setup_sql(*, project_dir: Path, statements: tuple[str, ...]) -> None: """Create pre-existing warehouse objects in the project's file-backed DuckDB database.""" @@ -284,468 +209,15 @@ def apply_warehouse_setup_sql(*, project_dir: Path, statements: tuple[str, ...]) connection.close() -def reshape_random_dag_model(*, project_dir: Path, name: str) -> None: - """Add one leading output column, changing the model's published shape signature.""" - - path: Path = project_dir / "models" / f"{name}.sql" - header, body = path.read_text(encoding="utf-8").split("\n", 1) - path.write_text( - f"{header}\nSELECT CAST(7 AS INTEGER) AS reshaped, *\n" - f"FROM ({body.strip()}) AS reshaped_input\n", - encoding="utf-8", - ) - - -def compile_outcome( - *, project_dir: Path, args: tuple[str, ...], capsys: pytest.CaptureFixture[str] -) -> CompileOutcome: - """Compile through the CLI; return the exit code, timing-free JSON, and artifacts.""" - - return timed_compile_outcome(project_dir=project_dir, args=args, capsys=capsys)[0] - - -def timed_compile_outcome( - *, project_dir: Path, args: tuple[str, ...], capsys: pytest.CaptureFixture[str] -) -> tuple[CompileOutcome, dict[str, object]]: - """Compile through the CLI; return the timing-free outcome and its compile timings.""" - - exit_code: int = main(["--project-dir", str(project_dir), "compile", "--json", *args]) - payload: dict[str, object] = json.loads( - capsys.readouterr().out.replace(str(project_dir), "") - ) - timings: dict[str, object] = cast(dict[str, object], payload.pop("compile_timings", {})) - compiled: Path = project_dir / "target" / "compiled" - return ( - exit_code, - payload, - { - path.relative_to(compiled).as_posix(): path.read_bytes() - for path in compiled.rglob("*.sql") - }, - ), timings - - -def compiled_project_capture( - *, - project_dir: Path, - capture_dir: Path, - capsys: pytest.CaptureFixture[str], - monkeypatch: pytest.MonkeyPatch, -) -> CompiledProjectRun: - """Cold-compile once with stage captures, counting how often shared analyses were reused.""" - - keys: list[object] = [] - deduplicated: list[int] = [] - memo_hits: list[int] = [] - with monkeypatch.context() as capture_patch: - capture_patch.setenv(STAGE_CAPTURE_DIR_ENV_VAR, str(capture_dir)) - record_shared_analysis_reuse( - monkeypatch=capture_patch, keys=keys, deduplicated=deduplicated, memo_hits=memo_hits - ) - exit_code: int = main( - ["--project-dir", str(project_dir), "compile", "--json", "--no-cache"] - ) - _ = capsys.readouterr() - return CompiledProjectRun( - exit_code=exit_code, - capture=next(capture_dir.glob(f"*-{CompilerStage.COMPILED_PROJECT.value}.json")), - shareable_members=len(keys) - len(set(keys)), - deduplicated_queries=sum(deduplicated), - shared_memo_hits=sum(memo_hits), - ) - - -def record_shared_analysis_reuse( - *, - monkeypatch: pytest.MonkeyPatch, - keys: list[object], - deduplicated: list[int], - memo_hits: list[int], -) -> None: - """Record shared-result keys, each batch's deduplicated queries and its memo hits.""" - - member_keys: Callable[..., tuple[object, ...]] = compact.shared_result_keys - - def counted_keys(**kwargs: Any) -> tuple[object, ...]: - computed: tuple[object, ...] = member_keys(**kwargs) - keys.extend(filter(None, computed)) - return computed - - prepare: Callable[..., CompactBatchPreparation] = compact._prepare_compact_analysis_batch - reuse: Callable[..., Mapping[int, object]] = compact.reused_shared_results - - def counted_prepare(**kwargs: Any) -> CompactBatchPreparation: - preparation: CompactBatchPreparation = prepare(**kwargs) - deduplicated.append(len(preparation.cleaned_sql) - len(preparation.queries)) - return preparation - - def counted_reuse(**kwargs: Any) -> Mapping[int, object]: - reused: Mapping[int, object] = reuse(**kwargs) - memo_hits.append(len(reused)) - return reused - - monkeypatch.setattr(compact, "_prepare_compact_analysis_batch", counted_prepare) - monkeypatch.setattr(compact, "reused_shared_results", counted_reuse) - monkeypatch.setattr(compact, "shared_result_keys", counted_keys) - - -def reshape_models(*, project_dir: Path, names: tuple[str, ...], indexes: tuple[int, ...]) -> None: - """Reshape the models at `indexes` of the generated topological name order.""" - - for index in indexes: - reshape_random_dag_model(project_dir=project_dir, name=names[index]) - - -def use_wave_analysis(monkeypatch: pytest.MonkeyPatch) -> None: - """Analyze one topological level at a time, the reference schedule.""" - - monkeypatch.setattr(project_assembly, "analyze_binding_dataflow", analyze_binding_waves) - - -def analyze_single_model_batches(monkeypatch: pytest.MonkeyPatch) -> None: - """Analyze every model in its own native batch on one worker.""" - - monkeypatch.setattr(binding_waves, "_DATAFLOW_WORKERS", 1) - monkeypatch.setattr(binding_waves, "_DATAFLOW_BATCH_MIN", 1) - monkeypatch.setattr(binding_waves, "_DATAFLOW_BATCH_LIMIT", 1) - - -def perturb_dataflow_schedule( - *, monkeypatch: pytest.MonkeyPatch, case: DataflowScheduleCase, seed: int -) -> None: - """Change worker count and batch size, and delay native completions at random.""" - - rng: random.Random = random.Random(seed) - original: Callable[..., object] = compact._run_compact_analysis_batch - - def delayed(*, preparation: CompactBatchPreparation) -> object: - result: object = original(preparation=preparation) - with native_section(): - time.sleep(rng.random() * case.max_delay_seconds) - return result - - monkeypatch.setattr(binding_waves, "_DATAFLOW_WORKERS", case.workers) - monkeypatch.setattr(binding_waves, "_DATAFLOW_BATCH_MIN", 1) - monkeypatch.setattr(binding_waves, "_DATAFLOW_BATCH_LIMIT", case.batch_limit) - monkeypatch.setattr(compact, "_run_compact_analysis_batch", delayed) - - -def fail_model_analysis(*, monkeypatch: pytest.MonkeyPatch, model_names: tuple[str, ...]) -> None: - """Raise from analysis of a batch holding a named model, as an internal fault would.""" - - original: Callable[..., tuple[Any, ...]] = project_assembly._analyze_model_sql_requests - failing_names: frozenset[str] = frozenset(model_names) - - def failing(**kwargs: Any) -> tuple[Any, ...]: - batch_names: set[str] = { - request.model_input.model_file.file_path.stem for request in kwargs["requests"] - } - for name in sorted(batch_names & failing_names)[:1]: - _raise_analysis_fault(name) - return original(**kwargs) - - monkeypatch.setattr(project_assembly, "_analyze_model_sql_requests", failing) - - -def _raise_analysis_fault(name: str) -> None: - raise RuntimeError(f"analysis fault in {name}") +def traced_shape_batches(monkeypatch: pytest.MonkeyPatch) -> list[tuple[str, ...]]: + """Record the expressions of every native expression-source shape batch.""" + original: Callable[..., Any] = native_module.infer_expression_source_shapes + batches: list[tuple[str, ...]] = [] -def analysis_pool_thread_ids(monkeypatch: pytest.MonkeyPatch) -> list[set[str]]: - """Record native analysis threads now, then again after each compact batch.""" + def traced(catalog: object, request: tuple[Any, ...], *rules: Any) -> Any: + batches.append(tuple(request[4])) + return original(catalog, request, *rules) - original: Callable[..., object] = compact._run_compact_analysis_batch - observed: list[set[str]] = [_analysis_thread_ids()] - - def traced(*, preparation: CompactBatchPreparation) -> object: - result: object = original(preparation=preparation) - observed.append(_analysis_thread_ids()) - return result - - monkeypatch.setattr(compact, "_run_compact_analysis_batch", traced) - return observed - - -def _analysis_thread_ids() -> set[str]: - threads_by_name: dict[str, set[str]] = {} - for task in Path("/proc/self/task").iterdir(): - with suppress(OSError): - name: str = (task / "comm").read_text(encoding="utf-8").strip() - threads_by_name.setdefault(name, set()).add(task.name) - return threads_by_name.get(_ANALYSIS_THREAD_NAME, set()) - - -def interrupt_reacquiring_analysis(*, monkeypatch: pytest.MonkeyPatch) -> list[str]: - """Send SIGINT while a worker thread holds the analysis lock and others reacquire it. - - Return overlaps, which name any batch that entered Python analysis while another held it. - """ - - original: Callable[..., object] = compact._run_compact_analysis_batch - holder: threading.Event = threading.Event() - owner: list[str] = [] - overlaps: list[str] = [] - worker_calls: itertools.count[int] = itertools.count() - hold_calls: dict[bool, Callable[[], int]] = { - False: lambda: next(worker_calls), - True: lambda: -1, - } - - def guarded(*, preparation: CompactBatchPreparation) -> object: - overlaps.extend(owner) - owner.append(threading.current_thread().name) - call: int = hold_calls[threading.current_thread() is threading.main_thread()]() - {0: _hold_analysis_lock}.get(call, _skip_hold)(holder) - owner.clear() - result: object = original(preparation=preparation) - with native_section(): - time.sleep(_REACQUIRE_DELAY_SECONDS) - return result - - def interrupt() -> None: - _ = holder.wait(_INTERRUPT_TIMEOUT_SECONDS) - time.sleep(_INTERRUPT_DELAY_SECONDS) - signal.pthread_kill(threading.main_thread().ident or 0, signal.SIGINT) - - monkeypatch.setattr(binding_waves, "_DATAFLOW_BATCH_MIN", 1) - monkeypatch.setattr(binding_waves, "_DATAFLOW_BATCH_LIMIT", 1) - monkeypatch.setattr(compact, "_run_compact_analysis_batch", guarded) - threading.Thread(target=interrupt, daemon=True).start() - return overlaps - - -def _hold_analysis_lock(holder: threading.Event) -> None: - holder.set() - time.sleep(_HOLD_SECONDS) - - -def _skip_hold(holder: threading.Event) -> None: - del holder - - -def interrupt_after_analysis_fault( - *, monkeypatch: pytest.MonkeyPatch, failing_model: str, interrupted_model: str -) -> list[int]: - """Fail one batch, then interrupt a batch that started beside it; return wave replays.""" - - original: Callable[..., tuple[Any, ...]] = project_assembly._analyze_model_sql_requests - actions: dict[str, Callable[[str], None]] = { - failing_model: _fail_after_native_delay, - interrupted_model: _interrupt_after_native_delay, - } - replays: list[int] = [] - analyze_waves: Callable[..., Any] = BindingDataflow.analyze_waves - - def failing(**kwargs: Any) -> tuple[Any, ...]: - batch_names: set[str] = { - request.model_input.model_file.file_path.stem for request in kwargs["requests"] - } - for name in sorted(batch_names & actions.keys()): - actions[name](name) - return original(**kwargs) - - def replay(self: BindingDataflow) -> Any: - replays.append(1) - return analyze_waves(self) - - monkeypatch.setattr(binding_waves, "_DATAFLOW_BATCH_MIN", 1) - monkeypatch.setattr(binding_waves, "_DATAFLOW_BATCH_LIMIT", 1) - monkeypatch.setattr(project_assembly, "_analyze_model_sql_requests", failing) - monkeypatch.setattr(BindingDataflow, "analyze_waves", replay) - return replays - - -def _fail_after_native_delay(name: str) -> None: - with native_section(): - time.sleep(_REACQUIRE_DELAY_SECONDS) - raise RuntimeError(f"analysis fault in {name}") - - -def _interrupt_after_native_delay(name: str) -> None: - with native_section(): - time.sleep(_HOLD_SECONDS) - raise KeyboardInterrupt(name) - - -def fail_worker_start( - *, monkeypatch: pytest.MonkeyPatch, failing_start: int, interrupt_after_start: bool -) -> list[str]: - """Fail one analysis worker start; return the names of analysis batches' threads. - - The failing start either never starts its thread or starts it and is then interrupted. - """ - - original_start: Callable[[threading.Thread], None] = threading.Thread.start - starts: itertools.count[int] = itertools.count() - batches: list[str] = trace_analysis_threads(monkeypatch) - - def start_then_interrupt(thread: threading.Thread) -> None: - original_start(thread) - raise KeyboardInterrupt(thread.name) - - failing: Callable[[threading.Thread], None] = { - False: _refuse_start, - True: start_then_interrupt, - }[interrupt_after_start] - - def counted_start(thread: threading.Thread) -> None: - {failing_start: failing}.get(next(starts), original_start)(thread) - - def start(thread: threading.Thread) -> None: - {True: counted_start, False: original_start}[ - thread.name.startswith(_MODEL_ANALYSIS_THREAD_PREFIX) - ](thread) - - monkeypatch.setattr(binding_waves, "_DATAFLOW_BATCH_MIN", 1) - monkeypatch.setattr(binding_waves, "_DATAFLOW_BATCH_LIMIT", 1) - monkeypatch.setattr(threading.Thread, "start", start) + monkeypatch.setattr(native_module, "infer_expression_source_shapes", traced) return batches - - -def _refuse_start(thread: threading.Thread) -> None: - raise RuntimeError(f"cannot start {thread.name}") - - -def trace_analysis_threads(monkeypatch: pytest.MonkeyPatch) -> list[str]: - """Record the thread that runs each compact analysis batch, slowed to overlap batches.""" - - original: Callable[..., object] = compact._run_compact_analysis_batch - threads: list[str] = [] - - def traced(*, preparation: CompactBatchPreparation) -> object: - threads.append(threading.current_thread().name) - with native_section(): - time.sleep(_REACQUIRE_DELAY_SECONDS) - return original(preparation=preparation) - - monkeypatch.setattr(compact, "_run_compact_analysis_batch", traced) - return threads - - -def live_model_analysis_threads() -> list[str]: - """Return model analysis worker threads that are still alive.""" - - names_by_kind: dict[bool, list[str]] = {} - for thread in threading.enumerate(): - names_by_kind.setdefault(thread.name.startswith(_MODEL_ANALYSIS_THREAD_PREFIX), []).append( - thread.name - ) - return sorted(names_by_kind.get(True, [])) - - -def random_dag_writer(project: RandomDagProject) -> Callable[[Path], tuple[str, ...]]: - return lambda project_dir: write_random_dag_project(project_dir=project_dir, project=project) - - -def fixture_writer(relative: str) -> Callable[[Path], tuple[str, ...]]: - def write(project_dir: Path) -> tuple[str, ...]: - _ = shutil.copytree( - _REPOSITORY_ROOT / relative, - project_dir, - ignore=shutil.ignore_patterns("target", "*.duckdb"), - ) - return () - - return write - - -def dense_writer(model_count: int) -> Callable[[Path], tuple[str, ...]]: - def write(project_dir: Path) -> tuple[str, ...]: - write_dense_compile_project(project_dir=project_dir, model_count=model_count) - return () - - return write - - -def use_per_model_normalization(monkeypatch: pytest.MonkeyPatch) -> None: - """Normalize each batch member with its own native call, the reference preparation.""" - - for module in _NORMALIZATION_MODULES: - monkeypatch.setattr(module, "normalize_analysis_sql_results", _per_model_normalization) - - -def keep_batched_normalization(monkeypatch: pytest.MonkeyPatch) -> None: - """Leave batched normalization in place, the preparation under test.""" - - _ = monkeypatch - - -def perturb_batched_normalization(monkeypatch: pytest.MonkeyPatch) -> None: - """Change the last member of every batched normalization, which comparisons must catch.""" - - batched: Callable[..., list[str | Exception]] = normalize_batch.normalize_analysis_sql_results - - def perturbed(**arguments: Any) -> list[str | Exception]: - results: list[str | Exception] = batched(**arguments) - return [*results[:-1], *(f"{result} " for result in results[-1:])] - - for module in _NORMALIZATION_MODULES: - monkeypatch.setattr(module, "normalize_analysis_sql_results", perturbed) - - -def prepared_compile( - *, - project_dir: Path, - args: tuple[str, ...], - capsys: pytest.CaptureFixture[str], - monkeypatch: pytest.MonkeyPatch, - normalization: Callable[[pytest.MonkeyPatch], None], -) -> PreparedCompile: - """Compile once; return the outcome, cache keys, cache metrics, and native batch payloads.""" - - with monkeypatch.context() as patch: - normalization(patch) - preparations: list[CompactBatchPreparation] = trace_native_compact_batches(patch) - cache_keys: list[str] = _trace_analysis_cache_keys(patch) - outcome: CompileOutcome - timings: dict[str, object] - outcome, timings = timed_compile_outcome(project_dir=project_dir, args=args, capsys=capsys) - return ( - outcome, - tuple(sorted(cache_keys)), - {name: timings.get(name) for name in _ANALYSIS_CACHE_METRICS}, - tuple(_preparation_payload(preparation) for preparation in preparations), - ) - - -def _trace_analysis_cache_keys(monkeypatch: pytest.MonkeyPatch) -> list[str]: - original: Callable[..., str] = project_assembly.model_analysis_cache_key - keys: list[str] = [] - - def traced(**arguments: Any) -> str: - key: str = original(**arguments) - keys.append(key) - return key - - monkeypatch.setattr(project_assembly, "model_analysis_cache_key", traced) - return keys - - -def _per_model_normalization( - *, - dialect: str | None, - requests: Sequence[tuple[str, Mapping[str, str] | None, Mapping[str, str] | None]], - catalog: NativeProjectCatalog | None, -) -> list[str | Exception]: - _ = catalog - native: NativePositionsModule = cast(NativePositionsModule, _native) - return [ - native.normalize_analysis_sqls( - dialect=dialect or "generic", - requests=[(sql, dict(stubs or {}), dict(placeholders or {}))], - )[0] - for sql, stubs, placeholders in requests - ] - - -def _preparation_payload(preparation: CompactBatchPreparation) -> bytes: - return orjson.dumps( - { - "cleaned_sql": preparation.cleaned_sql, - "queries": preparation.queries, - "templates": preparation.templates, - "projections": preparation.projections, - "shared_query_indexes": sorted(preparation.shared_query_indexes), - }, - option=orjson.OPT_SORT_KEYS, - ) diff --git a/tests/integration/src/sqlbuild/compiler/pipeline/test_batched_analysis_preparation.py b/tests/integration/src/sqlbuild/compiler/pipeline/test_batched_analysis_preparation.py deleted file mode 100644 index 05f2af995f..0000000000 --- a/tests/integration/src/sqlbuild/compiler/pipeline/test_batched_analysis_preparation.py +++ /dev/null @@ -1,201 +0,0 @@ -"""Batched analysis preparation must match per-model preparation byte for byte.""" - -from pathlib import Path - -import pytest - -from scripts.cold_compile_performance.models import RandomDagProject -from sqlbuild.compiler.compile.main import _build_compile_inputs -from tests.integration.src.sqlbuild.compiler.pipeline._test_types import ( - BatchedPreparationCase, - PerturbedPreparationCase, - PreparedCompile, -) -from tests.integration.src.sqlbuild.compiler.pipeline.helpers import ( - dense_writer, - fixture_writer, - keep_batched_normalization, - perturb_batched_normalization, - prepared_compile, - random_dag_writer, - reshape_models, - use_per_model_normalization, - use_wave_analysis, -) - -pytestmark: pytest.MarkDecorator = pytest.mark.usefixtures("python_compiler_engine") - - -@pytest.mark.parametrize( - "test_case", - [ - BatchedPreparationCase( - "inferred shapes", - random_dag_writer(RandomDagProject(seed=11, model_count=48)), - (16,), - 0, - ), - BatchedPreparationCase( - "binding errors mid-graph", - random_dag_writer(RandomDagProject(seed=23, model_count=48, errors=True)), - (24,), - 1, - ), - BatchedPreparationCase( - "run ids and analysis opt-outs", - random_dag_writer( - RandomDagProject(seed=37, model_count=40, run_ids=True, analysis_opt_outs=True) - ), - (20,), - 0, - ), - BatchedPreparationCase( - "reference cycle", - random_dag_writer(RandomDagProject(seed=67, model_count=24, cycle=True)), - (8,), - 0, - ), - BatchedPreparationCase( - "waffle shop fixture", fixture_writer("tests/e2e/fixtures/waffle_shop"), (), 0 - ), - BatchedPreparationCase( - "tidy shop example", fixture_writer("website/examples/tidy-shop"), (), 0 - ), - BatchedPreparationCase("dense single batch", dense_writer(120), (), 0), - ], - ids=lambda case: case.description, -) -def test_given_project_when_compiling_in_waves_then_batched_preparation_matches_per_model( - test_case: BatchedPreparationCase, - tmp_path: Path, - capsys: pytest.CaptureFixture[str], - monkeypatch: pytest.MonkeyPatch, -) -> None: - batched_dir: Path = tmp_path / "batched" - reference_dir: Path = tmp_path / "reference" - names: tuple[str, ...] = test_case.write_project(batched_dir) - _ = test_case.write_project(reference_dir) - monkeypatch.setattr( - _build_compile_inputs, - "resolve_run_id", - lambda *, selected_run_id: selected_run_id or "run-0", - ) - use_wave_analysis(monkeypatch) - for step, reshaped, args in ( - ("cold", (), ()), - ("warm", (), ()), - ("edit", test_case.reshaped, ()), - ("uncached", (), ("--no-cache",)), - ): - reshape_models(project_dir=batched_dir, names=names, indexes=reshaped) - reshape_models(project_dir=reference_dir, names=names, indexes=reshaped) - expected: PreparedCompile = prepared_compile( - project_dir=reference_dir, - args=args, - capsys=capsys, - monkeypatch=monkeypatch, - normalization=use_per_model_normalization, - ) - actual: PreparedCompile = prepared_compile( - project_dir=batched_dir, - args=args, - capsys=capsys, - monkeypatch=monkeypatch, - normalization=keep_batched_normalization, - ) - - assert actual[3] == expected[3], f"{step} native batch payloads differ" - assert actual[1] == expected[1], f"{step} analysis cache keys differ" - assert actual[2] == expected[2], f"{step} analysis cache hits differ" - assert actual[0] == expected[0], f"{step} compile differs from per-model preparation" - assert actual[0][0] == test_case.expected_exit_code - - -@pytest.mark.parametrize( - "test_case", - [ - BatchedPreparationCase( - "inferred shapes", random_dag_writer(RandomDagProject(seed=13, model_count=48)), (), 0 - ), - BatchedPreparationCase( - "binding errors mid-graph", - random_dag_writer(RandomDagProject(seed=29, model_count=48, errors=True)), - (), - 1, - ), - ], - ids=lambda case: case.description, -) -def test_given_duckdb_project_when_compiling_dataflow_with_and_without_cache_then_matches_per_model( - test_case: BatchedPreparationCase, - tmp_path: Path, - capsys: pytest.CaptureFixture[str], - monkeypatch: pytest.MonkeyPatch, -) -> None: - batched_dir: Path = tmp_path / "batched" - reference_dir: Path = tmp_path / "reference" - _ = test_case.write_project(batched_dir) - _ = test_case.write_project(reference_dir) - monkeypatch.setattr( - _build_compile_inputs, - "resolve_run_id", - lambda *, selected_run_id: selected_run_id or "run-0", - ) - for args in ((), (), ("--no-cache",)): - expected: PreparedCompile = prepared_compile( - project_dir=reference_dir, - args=args, - capsys=capsys, - monkeypatch=monkeypatch, - normalization=use_per_model_normalization, - ) - actual: PreparedCompile = prepared_compile( - project_dir=batched_dir, - args=args, - capsys=capsys, - monkeypatch=monkeypatch, - normalization=keep_batched_normalization, - ) - - assert actual[:3] == expected[:3] - assert actual[0][0] == test_case.expected_exit_code - - -@pytest.mark.parametrize( - "test_case", - [PerturbedPreparationCase("last member", RandomDagProject(seed=11, model_count=24), False)], - ids=lambda case: case.description, -) -def test_given_perturbed_batch_result_when_compiling_then_payloads_differ_from_per_model( - test_case: PerturbedPreparationCase, - tmp_path: Path, - capsys: pytest.CaptureFixture[str], - monkeypatch: pytest.MonkeyPatch, -) -> None: - batched_dir: Path = tmp_path / "batched" - reference_dir: Path = tmp_path / "reference" - _ = random_dag_writer(test_case.project)(batched_dir) - _ = random_dag_writer(test_case.project)(reference_dir) - use_wave_analysis(monkeypatch) - - expected: PreparedCompile = prepared_compile( - project_dir=reference_dir, - args=("--no-cache",), - capsys=capsys, - monkeypatch=monkeypatch, - normalization=use_per_model_normalization, - ) - actual: PreparedCompile = prepared_compile( - project_dir=batched_dir, - args=("--no-cache",), - capsys=capsys, - monkeypatch=monkeypatch, - normalization=perturb_batched_normalization, - ) - - assert len(actual[3]) == len(expected[3]) > 0 - assert (actual[3] == expected[3]) is test_case.expected_payloads_match - - -if __name__ == "__main__": - raise SystemExit(pytest.main([__file__, "-n", "auto", "--dist", "loadfile"])) diff --git a/tests/integration/src/sqlbuild/compiler/pipeline/test_binding_waves.py b/tests/integration/src/sqlbuild/compiler/pipeline/test_binding_waves.py index c4ff500ce8..62d45e3e63 100644 --- a/tests/integration/src/sqlbuild/compiler/pipeline/test_binding_waves.py +++ b/tests/integration/src/sqlbuild/compiler/pipeline/test_binding_waves.py @@ -1,14 +1,12 @@ """Dependency-ready models bind against producer outputs in their first analysis.""" import json -from collections.abc import Callable from pathlib import Path from typing import Any import pytest from sqlbuild.cli.commands.main.entrypoint.entry import main -from sqlbuild.compiler.compile._helpers.assembly import project from tests.integration.src.sqlbuild.compiler.pipeline._test_types import NativeCatalogCase @@ -17,11 +15,10 @@ [NativeCatalogCase("closed dependency waves", 'SELECT id FROM __ref("orders")')], ids=lambda case: case.description, ) -def test_given_inferred_producer_when_binding_consumers_then_avoids_deferred_requests_and_invalidates_changed_shapes( +def test_given_inferred_producer_when_binding_consumers_then_binds_and_invalidates_changed_shapes( test_case: NativeCatalogCase, tmp_path: Path, capsys: pytest.CaptureFixture[str], - monkeypatch: pytest.MonkeyPatch, ) -> None: (tmp_path / "sqlbuild_project.toml").write_text( 'name = "orders"\nadapter = "duckdb"\n[rules]\nselect = []\n' @@ -38,19 +35,10 @@ def test_given_inferred_producer_when_binding_consumers_then_avoids_deferred_req (tmp_path / "models/report.sql").write_text( "MODEL (description 'Test model report.', materialized view); " + test_case.sql ) - original: Callable[..., Any] = project.get_schema_validations - requests: list[Any] = [] - - def traced(**kwargs: Any) -> Any: - requests.extend(kwargs["requests"]) - return original(**kwargs) - - monkeypatch.setattr(project, "get_schema_validations", traced) args: list[str] = ["--project-dir", str(tmp_path), "compile", "--json"] assert main(args) == 0 cold: dict[str, Any] = json.loads(capsys.readouterr().out) assert tuple(item["code"] for item in cold["diagnostics"]) == test_case.expected_codes - assert requests == [] assert main(args) == 0 warm: dict[str, Any] = json.loads(capsys.readouterr().out) assert warm["resources"] == cold["resources"] @@ -58,7 +46,6 @@ def traced(**kwargs: Any) -> Any: assert main(args) == 1 changed: dict[str, Any] = json.loads(capsys.readouterr().out) assert [item["code"] for item in changed["diagnostics"]] == ["B002"] - assert requests == [] assert main([*args, "--no-cache"]) == 1 oracle: dict[str, Any] = json.loads(capsys.readouterr().out) assert oracle["diagnostics"] == changed["diagnostics"] diff --git a/tests/integration/src/sqlbuild/compiler/pipeline/test_dataflow_analysis_oracle.py b/tests/integration/src/sqlbuild/compiler/pipeline/test_dataflow_analysis_oracle.py deleted file mode 100644 index 7e278c7872..0000000000 --- a/tests/integration/src/sqlbuild/compiler/pipeline/test_dataflow_analysis_oracle.py +++ /dev/null @@ -1,215 +0,0 @@ -"""Dependency-driven model analysis must compile exactly what wave-by-wave analysis compiles.""" - -import shutil -from pathlib import Path - -import pytest - -from scripts.cold_compile_performance._helpers.dense_project import write_dense_compile_project -from scripts.cold_compile_performance._helpers.random_dag_project import write_random_dag_project -from scripts.cold_compile_performance.models import RandomDagProject -from sqlbuild.cli.commands.main.entrypoint.entry import main -from sqlbuild.compiler.compile.main import _build_compile_inputs -from tests.integration.src.sqlbuild.compiler.pipeline._test_types import ( - CompileOutcome, - DataflowBuildCase, - DataflowDenseCase, - DataflowFixtureCase, - DataflowOracleCase, -) -from tests.integration.src.sqlbuild.compiler.pipeline.helpers import ( - compile_outcome, - reshape_models, - use_wave_analysis, -) - -_REPOSITORY_ROOT: Path = Path(__file__).resolve().parents[6] - - -@pytest.mark.parametrize( - "test_case", - [ - DataflowOracleCase( - description="inferred shapes", - project=RandomDagProject(seed=11, model_count=48), - reshaped_steps=((), (), (16,), (24, 40), ()), - expected_exit_codes=(0, 0, 0, 0, 0), - ), - DataflowOracleCase( - description="binding errors mid-graph", - project=RandomDagProject(seed=23, model_count=48, errors=True), - reshaped_steps=((), (), (16,), (24, 40), ()), - expected_exit_codes=(1, 1, 1, 1, 1), - ), - DataflowOracleCase( - description="run ids and analysis opt-outs", - project=RandomDagProject(seed=37, model_count=40, run_ids=True, analysis_opt_outs=True), - reshaped_steps=((), (), (13,), (20,), ()), - expected_exit_codes=(0, 0, 0, 0, 0), - ), - DataflowOracleCase( - description="built-in rules", - project=RandomDagProject(seed=41, model_count=32, rules=("SQBR",)), - reshaped_steps=((), (10,), ()), - expected_exit_codes=(1, 1, 1), - ), - DataflowOracleCase( - description="analysis cache disabled", - project=RandomDagProject(seed=53, model_count=48, errors=True), - reshaped_steps=((), (16,)), - expected_exit_codes=(1, 1), - compile_args=("--no-cache",), - ), - DataflowOracleCase( - description="missing reference", - project=RandomDagProject(seed=61, model_count=24, missing_reference=True), - reshaped_steps=((), (8,)), - expected_exit_codes=(1, 1), - ), - DataflowOracleCase( - description="reference cycle", - project=RandomDagProject(seed=67, model_count=24, cycle=True), - reshaped_steps=((), (8,)), - expected_exit_codes=(0, 0), - ), - ], - ids=lambda case: case.description, -) -def test_given_random_dag_edit_sequence_when_compiling_then_dataflow_matches_waves( - test_case: DataflowOracleCase, - tmp_path: Path, - capsys: pytest.CaptureFixture[str], - monkeypatch: pytest.MonkeyPatch, -) -> None: - waves_dir: Path = tmp_path / "waves" - dataflow_dir: Path = tmp_path / "dataflow" - names: tuple[str, ...] = write_random_dag_project( - project_dir=waves_dir, project=test_case.project - ) - _ = write_random_dag_project(project_dir=dataflow_dir, project=test_case.project) - exit_codes: list[int] = [] - for step, indexes in enumerate(test_case.reshaped_steps): - monkeypatch.setattr( - _build_compile_inputs, - "resolve_run_id", - lambda *, selected_run_id, run_id=f"run-{step}": selected_run_id or run_id, - ) - reshape_models(project_dir=waves_dir, names=names, indexes=indexes) - reshape_models(project_dir=dataflow_dir, names=names, indexes=indexes) - with monkeypatch.context() as waves_patch: - use_wave_analysis(waves_patch) - expected: CompileOutcome = compile_outcome( - project_dir=waves_dir, args=test_case.compile_args, capsys=capsys - ) - actual: CompileOutcome = compile_outcome( - project_dir=dataflow_dir, args=test_case.compile_args, capsys=capsys - ) - uncached: CompileOutcome = compile_outcome( - project_dir=dataflow_dir, args=("--no-cache",), capsys=capsys - ) - exit_codes.append(actual[0]) - - assert actual == expected, f"step {step} differs from wave analysis" - assert actual == uncached, f"step {step} differs from an uncached compile" - - assert tuple(exit_codes) == test_case.expected_exit_codes - - -@pytest.mark.parametrize( - "test_case", - [ - DataflowFixtureCase("waffle shop fixture", "tests/e2e/fixtures/waffle_shop", 0), - DataflowFixtureCase("waffle shop example", "website/examples/waffle-shop", 0), - DataflowFixtureCase("tidy shop example", "website/examples/tidy-shop", 0), - DataflowFixtureCase("hero shop example", "website/examples/hero-shop", 0), - ], - ids=lambda case: case.description, -) -def test_given_repository_fixture_when_compiling_cold_then_dataflow_matches_waves( - test_case: DataflowFixtureCase, - tmp_path: Path, - capsys: pytest.CaptureFixture[str], - monkeypatch: pytest.MonkeyPatch, -) -> None: - project_dir: Path = tmp_path / "project" - _ = shutil.copytree( - _REPOSITORY_ROOT / test_case.fixture, - project_dir, - ignore=shutil.ignore_patterns("target", "*.duckdb"), - ) - monkeypatch.setattr( - _build_compile_inputs, - "resolve_run_id", - lambda *, selected_run_id: selected_run_id or "run-0", - ) - with monkeypatch.context() as waves_patch: - use_wave_analysis(waves_patch) - expected: CompileOutcome = compile_outcome(project_dir=project_dir, args=(), capsys=capsys) - shutil.rmtree(project_dir / "target") - actual: CompileOutcome = compile_outcome(project_dir=project_dir, args=(), capsys=capsys) - - assert actual == expected - assert actual[0] == test_case.expected_exit_code - - -@pytest.mark.parametrize( - "test_case", - [DataflowDenseCase("dense joins unions macros and functions", 64, (0, 0))], - ids=lambda case: case.description, -) -def test_given_dense_fixture_when_compiling_cold_and_warm_then_dataflow_matches_waves( - test_case: DataflowDenseCase, - tmp_path: Path, - capsys: pytest.CaptureFixture[str], - monkeypatch: pytest.MonkeyPatch, -) -> None: - waves_dir: Path = tmp_path / "waves" - dataflow_dir: Path = tmp_path / "dataflow" - write_dense_compile_project(project_dir=waves_dir, model_count=test_case.model_count) - write_dense_compile_project(project_dir=dataflow_dir, model_count=test_case.model_count) - with monkeypatch.context() as waves_patch: - use_wave_analysis(waves_patch) - expected: tuple[CompileOutcome, CompileOutcome] = ( - compile_outcome(project_dir=waves_dir, args=(), capsys=capsys), - compile_outcome(project_dir=waves_dir, args=(), capsys=capsys), - ) - actual: tuple[CompileOutcome, CompileOutcome] = ( - compile_outcome(project_dir=dataflow_dir, args=(), capsys=capsys), - compile_outcome(project_dir=dataflow_dir, args=(), capsys=capsys), - ) - - assert actual == expected - assert (actual[0][0], actual[1][0]) == test_case.expected_exit_codes - - -@pytest.mark.parametrize( - "test_case", - [DataflowBuildCase("inferred shapes", RandomDagProject(seed=79, model_count=24), 0, 0)], - ids=lambda case: case.description, -) -def test_given_random_dag_when_building_on_duckdb_then_every_model_materializes( - test_case: DataflowBuildCase, tmp_path: Path, capsys: pytest.CaptureFixture[str] -) -> None: - project_dir: Path = tmp_path / "orders" - names: tuple[str, ...] = write_random_dag_project( - project_dir=project_dir, project=test_case.project - ) - config: Path = project_dir / "sqlbuild_project.toml" - _ = config.write_text( - config.read_text(encoding="utf-8") - + f'[connection]\ndatabase = "{project_dir / "orders.duckdb"}"\n', - encoding="utf-8", - ) - - compiled: int = main(["--project-dir", str(project_dir), "compile", "--json"]) - compile_output: str = capsys.readouterr().out - built: int = main(["--project-dir", str(project_dir), "build", "--no-tests", "--no-audits"]) - build_output: str = "".join(capsys.readouterr()) - - assert compiled == test_case.expected_compile_exit_code, compile_output - assert built == test_case.expected_build_exit_code, build_output - assert all(name in build_output for name in names) - - -if __name__ == "__main__": - raise SystemExit(pytest.main([__file__, "-n", "auto", "--dist", "loadfile"])) diff --git a/tests/integration/src/sqlbuild/compiler/pipeline/test_dataflow_analysis_schedule.py b/tests/integration/src/sqlbuild/compiler/pipeline/test_dataflow_analysis_schedule.py deleted file mode 100644 index d3ad46ddad..0000000000 --- a/tests/integration/src/sqlbuild/compiler/pipeline/test_dataflow_analysis_schedule.py +++ /dev/null @@ -1,330 +0,0 @@ -"""Dataflow analysis output must not depend on worker count, batching, or completion order.""" - -import threading -import time -from pathlib import Path - -import pytest -from _pytest.capture import CaptureResult - -from scripts.cold_compile_performance._helpers.random_dag_project import write_random_dag_project -from scripts.cold_compile_performance.models import RandomDagProject -from scripts.compiler_differential._helpers.comparing.capture import first_capture_difference -from scripts.compiler_differential.main.generate_project import generate_project -from scripts.compiler_differential.models import Divergence -from sqlbuild.cli.commands.main.entrypoint.entry import main -from tests.integration.src.sqlbuild.compiler.pipeline._test_types import ( - CompileOutcome, - DataflowCaptureCase, - DataflowFailureCase, - DataflowInterruptAfterFaultCase, - DataflowInterruptCase, - DataflowPoolCase, - DataflowScheduleCase, - DataflowStartFailureCase, -) -from tests.integration.src.sqlbuild.compiler.pipeline.helpers import ( - CompiledProjectRun, - analysis_pool_thread_ids, - compile_outcome, - compiled_project_capture, - fail_model_analysis, - fail_worker_start, - interrupt_after_analysis_fault, - interrupt_reacquiring_analysis, - live_model_analysis_threads, - perturb_dataflow_schedule, - random_dag_writer, - reshape_models, - use_wave_analysis, -) - -pytestmark: pytest.MarkDecorator = pytest.mark.usefixtures("python_compiler_engine") - -_PROJECT: RandomDagProject = RandomDagProject(seed=97, model_count=40, errors=True) -_SHARED_ANALYSIS_SEED: int = 34 -_CAPTURE_SCHEDULES: tuple[DataflowScheduleCase, ...] = ( - DataflowScheduleCase("one worker with single models", 1, 1, 0.0), - DataflowScheduleCase("four workers with small batches", 4, 2, 0.004), - DataflowScheduleCase("four workers with wide batches", 4, 64, 0.002), -) -_EDITED: tuple[int, ...] = (10, 25) -_REPEATS: tuple[int, ...] = (0, 1) -_SETTLE_SECONDS: float = 0.3 -_INTERRUPT_NOTICE: str = "Interrupted; finishing in-flight model analysis..." - - -@pytest.mark.parametrize( - "test_case", - [ - DataflowScheduleCase("one worker with whole ready sets", 1, 64, 0.0), - DataflowScheduleCase("two workers with single models", 2, 1, 0.004), - DataflowScheduleCase("four workers with small batches", 4, 3, 0.004), - DataflowScheduleCase("four workers with wide batches", 4, 64, 0.002), - ], - ids=lambda case: case.description, -) -def test_given_perturbed_schedule_when_compiling_repeatedly_then_output_is_identical( - test_case: DataflowScheduleCase, - tmp_path: Path, - capsys: pytest.CaptureFixture[str], - monkeypatch: pytest.MonkeyPatch, -) -> None: - reference_dir: Path = tmp_path / "reference" - names: tuple[str, ...] = write_random_dag_project(project_dir=reference_dir, project=_PROJECT) - with monkeypatch.context() as waves_patch: - use_wave_analysis(waves_patch) - cold: CompileOutcome = compile_outcome(project_dir=reference_dir, args=(), capsys=capsys) - reshape_models(project_dir=reference_dir, names=names, indexes=_EDITED) - edit: CompileOutcome = compile_outcome(project_dir=reference_dir, args=(), capsys=capsys) - for repeat in _REPEATS: - project_dir: Path = tmp_path / f"dataflow-{repeat}" - _ = write_random_dag_project(project_dir=project_dir, project=_PROJECT) - with monkeypatch.context() as schedule_patch: - perturb_dataflow_schedule(monkeypatch=schedule_patch, case=test_case, seed=repeat) - actual_cold: CompileOutcome = compile_outcome( - project_dir=project_dir, args=(), capsys=capsys - ) - reshape_models(project_dir=project_dir, names=names, indexes=_EDITED) - actual_edit: CompileOutcome = compile_outcome( - project_dir=project_dir, args=(), capsys=capsys - ) - - assert actual_cold == cold, f"cold compile differs in repeat {repeat}" - assert actual_edit == edit, f"edited compile differs in repeat {repeat}" - assert actual_cold[0] == test_case.expected_cold_exit_code - assert actual_edit[0] == test_case.expected_edit_exit_code - - -@pytest.mark.parametrize( - "test_case", - [ - DataflowCaptureCase( - "random dag", - random_dag_writer(_PROJECT), - _CAPTURE_SCHEDULES, - expected_exit_code=1, - expected_minimum_shareable_members=0, - expected_minimum_shared_reuse=0, - ), - DataflowCaptureCase( - "differential seed with shared analyses", - generate_project(seed=_SHARED_ANALYSIS_SEED).write, - _CAPTURE_SCHEDULES, - expected_exit_code=0, - expected_minimum_shareable_members=1, - expected_minimum_shared_reuse=1, - ), - ], - ids=lambda case: case.description, -) -def test_given_perturbed_schedule_when_capturing_compiled_project_then_capture_is_identical( - test_case: DataflowCaptureCase, - tmp_path: Path, - capsys: pytest.CaptureFixture[str], - monkeypatch: pytest.MonkeyPatch, -) -> None: - project_dir: Path = tmp_path / "project" - _ = test_case.write_project(project_dir) - with monkeypatch.context() as waves_patch: - use_wave_analysis(waves_patch) - reference: CompiledProjectRun = compiled_project_capture( - project_dir=project_dir, - capture_dir=tmp_path / "reference", - capsys=capsys, - monkeypatch=monkeypatch, - ) - for index, schedule in enumerate(test_case.schedules): - with monkeypatch.context() as schedule_patch: - perturb_dataflow_schedule(monkeypatch=schedule_patch, case=schedule, seed=index) - actual: CompiledProjectRun = compiled_project_capture( - project_dir=project_dir, - capture_dir=tmp_path / f"schedule-{index}", - capsys=capsys, - monkeypatch=monkeypatch, - ) - - difference: Divergence | None = first_capture_difference( - left=reference.capture, right=actual.capture - ) - assert getattr(difference, "location", None) == test_case.expected_difference, schedule - assert ( - actual.exit_code, - actual.shareable_members >= test_case.expected_minimum_shareable_members, - actual.shared_reuse - >= test_case.expected_minimum_shared_reuse * (schedule.workers == 1), - ) == (test_case.expected_exit_code, True, True), (schedule, actual) - assert ( - reference.exit_code, - reference.shareable_members >= test_case.expected_minimum_shareable_members, - reference.shared_reuse >= test_case.expected_minimum_shared_reuse, - ) == (test_case.expected_exit_code, True, True), reference - - -@pytest.mark.parametrize( - "test_case", - [ - DataflowFailureCase("one failing model", ("orders_020",), "analysis fault in orders_020"), - DataflowFailureCase( - "an upstream failure wins", ("orders_035", "orders_004"), "analysis fault in orders_004" - ), - ], - ids=lambda case: case.description, -) -def test_given_analysis_fault_when_completion_order_varies_then_first_wave_error_is_raised( - test_case: DataflowFailureCase, - tmp_path: Path, - capsys: pytest.CaptureFixture[str], - monkeypatch: pytest.MonkeyPatch, -) -> None: - project_dir: Path = tmp_path / "orders" - _ = write_random_dag_project(project_dir=project_dir, project=_PROJECT) - args: list[str] = ["--project-dir", str(project_dir), "compile", "--json", "--no-cache"] - fail_model_analysis(monkeypatch=monkeypatch, model_names=test_case.failing_models) - with monkeypatch.context() as waves_patch: - use_wave_analysis(waves_patch) - with pytest.raises(RuntimeError) as expected: - _ = main(args) - _ = capsys.readouterr() - perturb_dataflow_schedule( - monkeypatch=monkeypatch, - case=DataflowScheduleCase("four workers with delays", 4, 3, 0.004), - seed=len(test_case.failing_models), - ) - with pytest.raises(RuntimeError) as actual: - _ = main(args) - - assert str(actual.value) == str(expected.value) - assert str(actual.value) == test_case.expected_message - - -@pytest.mark.parametrize( - "test_case", - [DataflowPoolCase("two multi-batch compiles", 2, 3, 4)], - ids=lambda case: case.description, -) -def test_given_multi_batch_compiles_when_analyzing_then_each_compile_reuses_one_native_pool( - test_case: DataflowPoolCase, - tmp_path: Path, - capsys: pytest.CaptureFixture[str], - monkeypatch: pytest.MonkeyPatch, -) -> None: - project_dir: Path = tmp_path / "orders" - _ = write_random_dag_project(project_dir=project_dir, project=_PROJECT) - for _ in range(test_case.compiles): - observed: list[set[str]] = analysis_pool_thread_ids(monkeypatch) - _ = compile_outcome(project_dir=project_dir, args=("--no-cache",), capsys=capsys) - - started: set[str] = set().union(*observed[1:]) - observed[0] - - assert len(observed) > test_case.minimum_batches - assert len(started) == test_case.expected_pool_threads - - -@pytest.mark.parametrize( - "test_case", - [DataflowInterruptCase("interrupt while workers reacquire the lock", (), (), 0, 1)], - ids=lambda case: case.description, -) -def test_given_sigint_while_workers_contend_for_lock_when_analyzing_then_interrupt_propagates_once( - test_case: DataflowInterruptCase, - tmp_path: Path, - capsys: pytest.CaptureFixture[str], - monkeypatch: pytest.MonkeyPatch, -) -> None: - project_dir: Path = tmp_path / "orders" - _ = write_random_dag_project(project_dir=project_dir, project=_PROJECT) - thread_errors: list[threading.ExceptHookArgs] = [] - monkeypatch.setattr(threading, "excepthook", thread_errors.append) - overlaps: list[str] = interrupt_reacquiring_analysis(monkeypatch=monkeypatch) - - with pytest.raises(KeyboardInterrupt): - _ = main(["--project-dir", str(project_dir), "compile", "--json", "--no-cache"]) - captured: CaptureResult[str] = capsys.readouterr() - - assert tuple(live_model_analysis_threads()) == test_case.expected_live_workers - assert tuple(overlaps) == test_case.expected_overlaps - assert len(thread_errors) == test_case.expected_thread_errors - assert captured.err.count(_INTERRUPT_NOTICE) == test_case.expected_notices - assert _INTERRUPT_NOTICE not in captured.out - - -@pytest.mark.parametrize( - "test_case", - [DataflowInterruptAfterFaultCase("interrupt after a fault", "orders_000", "orders_001", 0)], - ids=lambda case: case.description, -) -def test_given_interrupt_after_analysis_fault_when_analyzing_then_interrupt_wins_without_replay( - test_case: DataflowInterruptAfterFaultCase, - tmp_path: Path, - capsys: pytest.CaptureFixture[str], - monkeypatch: pytest.MonkeyPatch, -) -> None: - project_dir: Path = tmp_path / "orders" - _ = write_random_dag_project(project_dir=project_dir, project=_PROJECT) - replays: list[int] = interrupt_after_analysis_fault( - monkeypatch=monkeypatch, - failing_model=test_case.failing_model, - interrupted_model=test_case.interrupted_model, - ) - - with pytest.raises(KeyboardInterrupt, match=test_case.interrupted_model): - _ = main(["--project-dir", str(project_dir), "compile", "--json", "--no-cache"]) - _ = capsys.readouterr() - - assert len(replays) == test_case.expected_wave_replays - - -@pytest.mark.parametrize( - "test_case", - [ - DataflowStartFailureCase( - description="third worker cannot start", - failing_start=2, - interrupt_after_start=False, - expected_error_type=RuntimeError, - expected_error="cannot start", - expected_live_workers=(), - expected_notices=0, - ), - DataflowStartFailureCase( - description="interrupt after the first worker starts", - failing_start=0, - interrupt_after_start=True, - expected_error_type=KeyboardInterrupt, - expected_error="sqlbuild-model-analysis-0", - expected_live_workers=(), - expected_notices=1, - ), - ], - ids=lambda case: case.description, -) -def test_given_worker_start_failure_when_analyzing_then_started_workers_stop_before_raising( - test_case: DataflowStartFailureCase, - tmp_path: Path, - capsys: pytest.CaptureFixture[str], - monkeypatch: pytest.MonkeyPatch, -) -> None: - project_dir: Path = tmp_path / "orders" - _ = write_random_dag_project(project_dir=project_dir, project=_PROJECT) - batches: list[str] = fail_worker_start( - monkeypatch=monkeypatch, - failing_start=test_case.failing_start, - interrupt_after_start=test_case.interrupt_after_start, - ) - - with pytest.raises(test_case.expected_error_type, match=test_case.expected_error): - _ = main(["--project-dir", str(project_dir), "compile", "--json", "--no-cache"]) - live_at_failure: list[str] = live_model_analysis_threads() - batches_at_failure: int = len(batches) - captured: CaptureResult[str] = capsys.readouterr() - time.sleep(_SETTLE_SECONDS) - - assert tuple(live_at_failure) == test_case.expected_live_workers - assert len(batches) == batches_at_failure - assert captured.err.count(_INTERRUPT_NOTICE) == test_case.expected_notices - assert _INTERRUPT_NOTICE not in captured.out - - -if __name__ == "__main__": - raise SystemExit(pytest.main([__file__, "-n", "auto", "--dist", "loadfile"])) diff --git a/tests/integration/src/sqlbuild/compiler/pipeline/test_expression_catalog_cache.py b/tests/integration/src/sqlbuild/compiler/pipeline/test_expression_catalog_cache.py index 997772606c..6605544e64 100644 --- a/tests/integration/src/sqlbuild/compiler/pipeline/test_expression_catalog_cache.py +++ b/tests/integration/src/sqlbuild/compiler/pipeline/test_expression_catalog_cache.py @@ -1,20 +1,22 @@ """Expression schemas are memoized only within their owning compiler catalog.""" import json -from collections.abc import Callable +from dataclasses import replace from pathlib import Path from typing import Any import pytest from sqlbuild.cli.commands.main.entrypoint.entry import main -from sqlbuild.compiler.compile._helpers.assembly import semantic_shapes +from sqlbuild.compiler.compile._helpers.assembly.semantic_shapes import semantic_shapes +from sqlbuild.compiler.compile.models import CompiledProject +from tests.integration.src.sqlbuild.compiler.lineage.helpers import compiled_project from tests.integration.src.sqlbuild.compiler.pipeline._test_types import ( ExpressionBatchCase, ExpressionMemoCase, + RestoredShapeCase, ) - -pytestmark: pytest.MarkDecorator = pytest.mark.usefixtures("python_compiler_engine") +from tests.integration.src.sqlbuild.compiler.pipeline.helpers import traced_shape_batches @pytest.mark.parametrize( @@ -40,14 +42,7 @@ def test_given_equal_source_expressions_when_compiling_then_infers_once_and_inva source.write_text( f"sources:\n - name: raw_orders\n description: Test source raw_orders.\n expression: {test_case.expression}\n - name: raw_customers\n description: Test source raw_customers.\n expression: {test_case.expression}\n" ) - original: Callable[..., Any] = semantic_shapes.analyze_queries_with_compact_polyglot_batch - calls: list[object] = [] - - def traced(**kwargs: Any) -> Any: - calls.append(kwargs["query_sqls"]) - return original(**kwargs) - - monkeypatch.setattr(semantic_shapes, "analyze_queries_with_compact_polyglot_batch", traced) + calls: list[tuple[str, ...]] = traced_shape_batches(monkeypatch) args: list[str] = ["--project-dir", str(tmp_path), "compile", "--json"] assert main(args) == 0 payload: dict[str, Any] = json.loads(capsys.readouterr().out) @@ -91,19 +86,56 @@ def test_given_distinct_source_expressions_when_compiling_then_infers_them_in_on f" - name: raw_orders\n description: Test source raw_orders.\n expression: {test_case.orders_expression}\n" f" - name: raw_customers\n description: Test source raw_customers.\n expression: {test_case.customers_expression}\n" ) - original: Callable[..., Any] = semantic_shapes.analyze_queries_with_compact_polyglot_batch - batches: list[tuple[str, ...]] = [] - - def traced(**kwargs: Any) -> Any: - batches.append(kwargs["query_sqls"]) - return original(**kwargs) - - monkeypatch.setattr(semantic_shapes, "analyze_queries_with_compact_polyglot_batch", traced) + batches: list[tuple[str, ...]] = traced_shape_batches(monkeypatch) assert main(["--project-dir", str(tmp_path), "compile", "--json"]) == 0 payload: dict[str, Any] = json.loads(capsys.readouterr().out) assert payload["diagnostics"] == [] assert tuple(batches) == test_case.expected_batches +@pytest.mark.parametrize( + "test_case", + [ + RestoredShapeCase( + description="closed and open expression sources", + expressions={ + "raw_orders": "SELECT 1 AS id, 'placed' AS status", + "raw_events": "SELECT mystery_fn(1) AS event_id, NULL AS note", + "raw_open": "SELECT * FROM somewhere", + }, + expected_shapes={ + "raw_orders": {"id": "INT", "status": "TEXT"}, + "raw_events": {"event_id": "UNKNOWN", "note": "UNKNOWN"}, + }, + ) + ], + ids=lambda case: case.description, +) +def test_given_restored_project_without_catalog_when_reading_shapes_then_infers_natively( + test_case: RestoredShapeCase, tmp_path: Path +) -> None: + sources: str = "sources:\n" + "".join( + f" - name: {name}\n description: Test source {name}.\n expression: {expression}\n" + for name, expression in test_case.expressions.items() + ) + project: CompiledProject = compiled_project( + project_dir=tmp_path, + files={ + "sqlbuild_project.toml": 'name = "orders"\nadapter = "duckdb"\n', + "sources/sources.yml": sources, + }, + ) + + restored: dict[str, dict[str, str]] = semantic_shapes( + project=replace(project, binding_catalog=None) + ) + + assert {name: restored.get(name) for name in test_case.expected_shapes} == ( + test_case.expected_shapes + ) + assert "raw_open" not in restored + assert restored == semantic_shapes(project=project) + + if __name__ == "__main__": pytest.main([__file__, "-vv"]) diff --git a/tests/integration/src/sqlbuild/compiler/pipeline/test_review_bindings.py b/tests/integration/src/sqlbuild/compiler/pipeline/test_review_bindings.py index bf704a1dc1..ff964c9df2 100644 --- a/tests/integration/src/sqlbuild/compiler/pipeline/test_review_bindings.py +++ b/tests/integration/src/sqlbuild/compiler/pipeline/test_review_bindings.py @@ -1,14 +1,12 @@ """Real compiler regressions for binding boundary review findings.""" import json -from collections.abc import Callable from pathlib import Path from typing import Any import pytest from sqlbuild.cli.commands.main.entrypoint.entry import main -from sqlbuild.compiler.compile._helpers.assembly import project from sqlbuild.compiler.sql_analysis.main._normalize_analysis import normalize_analysis_sql from tests.integration.src.sqlbuild.compiler.pipeline._test_types import ( IdentifierBindingCase, @@ -134,6 +132,18 @@ def test_given_nested_function_calls_when_compiling_then_native_normalization_do "Postgres quoted mismatch", "postgres", '"Customer"', '"customer"', ("B002",) ), IdentifierBindingCase("Postgres unquoted lowercase", "postgres", "Customer", '"customer"'), + IdentifierBindingCase( + "Postgres unknown column", "postgres", "customer", "missing", ("B002",) + ), + IdentifierBindingCase( + "MotherDuck quoted insensitive", "motherduck", '"Customer"', '"CUSTOMER"' + ), + IdentifierBindingCase( + "MotherDuck unknown column", "motherduck", "customer", "missing", ("B002",) + ), + IdentifierBindingCase( + "SQL Server unknown column", "sqlserver", "customer", "missing", ("B002",) + ), ], ids=lambda case: case.description, ) @@ -141,15 +151,7 @@ def test_given_inferred_output_when_binding_downstream_then_preserves_dialect_id test_case: IdentifierBindingCase, tmp_path: Path, capsys: pytest.CaptureFixture[str], - monkeypatch: pytest.MonkeyPatch, ) -> None: - original: Callable[..., Any] = project.get_schema_validations - - def without_deferred_requests(**kwargs: Any) -> Any: - assert kwargs["requests"] == () - return original(**kwargs) - - monkeypatch.setattr(project, "get_schema_validations", without_deferred_requests) (tmp_path / "sqlbuild_project.toml").write_text( f'name = "orders"\nadapter = "{test_case.dialect}"\n[rules]\nselect = []\n' ) diff --git a/tests/integration/src/sqlbuild/compiler/pipeline/test_shared_binding_queries.py b/tests/integration/src/sqlbuild/compiler/pipeline/test_shared_binding_queries.py deleted file mode 100644 index 4d7cc12940..0000000000 --- a/tests/integration/src/sqlbuild/compiler/pipeline/test_shared_binding_queries.py +++ /dev/null @@ -1,351 +0,0 @@ -"""Binding-mode models with identical SQL shapes and inputs share one native query.""" - -import json -from pathlib import Path -from typing import Any - -import pytest - -from sqlbuild.cli.commands.main.entrypoint.entry import main -from sqlbuild.compiler.compile.models import CompactBatchPreparation -from tests.integration.src.sqlbuild.compiler.pipeline._test_types import SharedBindingQueryCase -from tests.integration.src.sqlbuild.compiler.pipeline.helpers import ( - analyze_single_model_batches, - trace_native_compact_batches, - write_shared_binding_project, -) - -pytestmark: pytest.MarkDecorator = pytest.mark.usefixtures("python_compiler_engine") - - -@pytest.mark.parametrize( - "test_case", - [ - SharedBindingQueryCase( - description="identical shapes and inputs share one query", - orders_summary_sql='MODEL (description "Test model.", materialized view); SELECT id, amount FROM __ref("orders")', - customers_summary_sql='MODEL (description "Test model.", materialized view); SELECT id, amount FROM __ref("customers")', - expected_shared_queries=1, - ), - SharedBindingQueryCase( - description="a relation name used as a qualifier is not shared", - orders_summary_sql=( - 'MODEL (description "Test model.", materialized view); SELECT orders.id FROM __ref("orders") AS orders' - ), - customers_summary_sql=( - 'MODEL (description "Test model.", materialized view); SELECT customers.id FROM __ref("customers") AS customers' - ), - expected_shared_queries=0, - ), - SharedBindingQueryCase( - description="an authored lowercase stub-named CTE is not shared", - orders_summary_sql=( - "MODEL (description 'Test model.', materialized view); WITH __sqlbuild_project_input_0 AS " - '(SELECT CAST(2 AS VARCHAR) AS id) SELECT id FROM __ref("orders")' - ), - customers_summary_sql=( - "MODEL (description 'Test model.', materialized view); WITH __sqlbuild_project_input_0 AS " - '(SELECT CAST(2 AS VARCHAR) AS id) SELECT id FROM __ref("customers")' - ), - expected_shared_queries=0, - later_models=( - ( - "next_orders", - 'MODEL (description "Test model.", materialized view); SELECT id + 1 AS next_id FROM __ref("orders_summary")', - ), - ), - ), - SharedBindingQueryCase( - description="an authored uppercase stub-named CTE is not shared", - orders_summary_sql=( - "MODEL (description 'Test model.', materialized view); WITH __SQLBUILD_PROJECT_INPUT_0 AS " - '(SELECT CAST(2 AS VARCHAR) AS id) SELECT id FROM __ref("orders")' - ), - customers_summary_sql=( - "MODEL (description 'Test model.', materialized view); WITH __SQLBUILD_PROJECT_INPUT_0 AS " - '(SELECT CAST(2 AS VARCHAR) AS id) SELECT id FROM __ref("customers")' - ), - expected_shared_queries=0, - later_models=( - ( - "next_orders", - 'MODEL (description "Test model.", materialized view); SELECT id + 1 AS next_id FROM __ref("orders_summary")', - ), - ), - ), - ], - ids=lambda case: case.description, -) -def test_given_models_with_equal_shapes_when_compiling_then_shares_only_lossless_queries( - test_case: SharedBindingQueryCase, - tmp_path: Path, - capsys: pytest.CaptureFixture[str], - monkeypatch: pytest.MonkeyPatch, -) -> None: - write_shared_binding_project(project_dir=tmp_path, test_case=test_case) - preparations: list[CompactBatchPreparation] = trace_native_compact_batches(monkeypatch) - - assert main(["--project-dir", str(tmp_path), "compile", "--json", "--no-cache"]) == 0 - payload: dict[str, Any] = json.loads(capsys.readouterr().out) - - assert payload["diagnostics"] == [] - assert ( - sum(len(preparation.shared_query_indexes) for preparation in preparations) - == test_case.expected_shared_queries - ) - for model, upstream in (("orders_summary", "orders"), ("customers_summary", "customers")): - assert ( - main( - [ - "--project-dir", - str(tmp_path), - "lineage", - f"{model}.id", - "--format", - "json", - "--direction", - "upstream", - ] - ) - == 0 - ) - lineage: dict[str, Any] = json.loads(capsys.readouterr().out) - assert [step["source"]["resource_name"] for step in lineage["trace"]] == [upstream] - - -@pytest.mark.parametrize( - "test_case", - [ - SharedBindingQueryCase( - description="findings after the relation keep each model's names and positions", - orders_summary_sql=( - 'MODEL (description "Test model.", materialized view); SELECT id FROM __ref("orders") WHERE missing > 0' - ), - customers_summary_sql=( - 'MODEL (description "Test model.", materialized view); SELECT id FROM __ref("customers") WHERE missing > 0' - ), - expected_shared_queries=1, - expected_codes=("B002",), - ), - ], - ids=lambda case: case.description, -) -def test_given_shared_query_with_finding_when_compiling_then_reports_each_model_exactly( - test_case: SharedBindingQueryCase, - tmp_path: Path, - capsys: pytest.CaptureFixture[str], - monkeypatch: pytest.MonkeyPatch, -) -> None: - write_shared_binding_project(project_dir=tmp_path, test_case=test_case) - preparations: list[CompactBatchPreparation] = trace_native_compact_batches(monkeypatch) - - assert main(["--project-dir", str(tmp_path), "compile", "--json", "--no-cache"]) == 1 - payload: dict[str, Any] = json.loads(capsys.readouterr().out) - - assert ( - sum(len(preparation.shared_query_indexes) for preparation in preparations) - == test_case.expected_shared_queries - ) - findings: dict[str, dict[str, Any]] = { - diagnostic["resource_name"]: diagnostic for diagnostic in payload["diagnostics"] - } - assert sorted(findings) == ["customers_summary", "orders_summary"] - for model, upstream, sql in ( - ("orders_summary", "orders", test_case.orders_summary_sql), - ("customers_summary", "customers", test_case.customers_summary_sql), - ): - finding: dict[str, Any] = findings[model] - assert (finding["code"],) == test_case.expected_codes - assert finding["message"] == f"Unknown column 'missing' in {upstream}" - assert finding["location"]["column"] == sql.index("missing") + 1 - assert finding["location"]["end_column"] == sql.index("missing") + len("missing") + 1 - - -@pytest.mark.parametrize( - "test_case", - [ - SharedBindingQueryCase( - description="later-wave members reuse an exact shared result", - orders_summary_sql='MODEL (description "Test model.", materialized view); SELECT id, amount FROM __ref("orders")', - customers_summary_sql=( - 'MODEL (description "Test model.", materialized view); SELECT id, amount FROM __ref("customers")' - ), - expected_shared_queries=1, - later_models=( - ( - "orders_rollup", - 'MODEL (description "Test model.", materialized view); SELECT id, amount FROM __ref("orders_summary")', - ), - ( - "customers_rollup", - 'MODEL (description "Test model.", materialized view); SELECT id, amount FROM __ref("customers_summary")', - ), - ), - expected_lineage=( - ("orders_rollup", "orders_summary"), - ("customers_rollup", "customers_summary"), - ), - ) - ], - ids=lambda case: case.description, -) -def test_given_later_wave_members_with_equal_keys_when_compiling_then_reuses_shared_result( - test_case: SharedBindingQueryCase, - tmp_path: Path, - capsys: pytest.CaptureFixture[str], - monkeypatch: pytest.MonkeyPatch, -) -> None: - write_shared_binding_project(project_dir=tmp_path, test_case=test_case) - preparations: list[CompactBatchPreparation] = trace_native_compact_batches(monkeypatch) - - assert main(["--project-dir", str(tmp_path), "compile", "--json", "--no-cache"]) == 0 - payload: dict[str, Any] = json.loads(capsys.readouterr().out) - - assert payload["diagnostics"] == [] - assert ( - sum(len(preparation.shared_query_indexes) for preparation in preparations) - == test_case.expected_shared_queries - ) - analyzed_sql: list[str] = [] - for preparation in preparations: - analyzed_sql.extend(str(query["sql"]) for query in preparation.queries) - assert not any("_summary" in sql for sql in analyzed_sql) - for model, upstream in test_case.expected_lineage: - assert ( - main( - [ - "--project-dir", - str(tmp_path), - "lineage", - f"{model}.amount", - "--format", - "json", - "--direction", - "upstream", - "--depth", - "1", - ] - ) - == 0 - ) - lineage: dict[str, Any] = json.loads(capsys.readouterr().out) - assert [step["source"]["resource_name"] for step in lineage["trace"]] == [upstream] - - -@pytest.mark.parametrize( - "test_case", - [ - SharedBindingQueryCase( - description="members analyzed in separate batches keep their own sources", - orders_summary_sql='MODEL (description "Test model.", materialized view); SELECT id, amount FROM __ref("orders")', - customers_summary_sql=( - 'MODEL (description "Test model.", materialized view); SELECT id, amount FROM __ref("customers")' - ), - expected_shared_queries=0, - expected_lineage=( - ("orders_summary", "orders"), - ("customers_summary", "customers"), - ), - ) - ], - ids=lambda case: case.description, -) -def test_given_equal_keys_in_separate_batches_when_tracing_lineage_then_each_model_keeps_its_source( - test_case: SharedBindingQueryCase, - tmp_path: Path, - capsys: pytest.CaptureFixture[str], - monkeypatch: pytest.MonkeyPatch, -) -> None: - write_shared_binding_project(project_dir=tmp_path, test_case=test_case) - analyze_single_model_batches(monkeypatch) - - for model, upstream in test_case.expected_lineage: - assert ( - main( - [ - "--project-dir", - str(tmp_path), - "lineage", - f"{model}.amount", - "--format", - "json", - "--direction", - "upstream", - "--depth", - "1", - "--mode", - "fast", - ] - ) - == 0 - ) - lineage: dict[str, Any] = json.loads(capsys.readouterr().out) - assert [step["source"]["resource_name"] for step in lineage["trace"]] == [upstream] - - -@pytest.mark.parametrize( - "test_case", - [ - SharedBindingQueryCase( - description="a later-wave member of a group with findings keeps its own names", - orders_summary_sql=( - 'MODEL (description "Test model.", materialized view); SELECT id FROM __ref("orders") WHERE missing > 0' - ), - customers_summary_sql=( - 'MODEL (description "Test model.", materialized view); SELECT id FROM __ref("customers") WHERE missing > 0' - ), - expected_shared_queries=2, - expected_codes=("B002",), - later_models=( - ( - "orders_mid", - 'MODEL (description "Test model.", materialized view); SELECT id, amount FROM __ref("orders")', - ), - ( - "orders_late", - 'MODEL (description "Test model.", materialized view); SELECT id FROM __ref("orders_mid") WHERE missing > 0', - ), - ), - expected_findings=( - ("orders_summary", "orders"), - ("customers_summary", "customers"), - ("orders_late", "orders_mid"), - ), - ) - ], - ids=lambda case: case.description, -) -def test_given_later_wave_member_of_group_with_findings_when_compiling_then_reports_it_exactly( - test_case: SharedBindingQueryCase, - tmp_path: Path, - capsys: pytest.CaptureFixture[str], - monkeypatch: pytest.MonkeyPatch, -) -> None: - write_shared_binding_project(project_dir=tmp_path, test_case=test_case) - preparations: list[CompactBatchPreparation] = trace_native_compact_batches(monkeypatch) - - assert main(["--project-dir", str(tmp_path), "compile", "--json", "--no-cache"]) == 1 - payload: dict[str, Any] = json.loads(capsys.readouterr().out) - - assert ( - sum(len(preparation.shared_query_indexes) for preparation in preparations) - == test_case.expected_shared_queries - ) - findings: dict[str, dict[str, Any]] = { - diagnostic["resource_name"]: diagnostic for diagnostic in payload["diagnostics"] - } - assert sorted(findings) == sorted(model for model, _ in test_case.expected_findings) - sql_by_model: dict[str, str] = { - "orders_summary": test_case.orders_summary_sql, - "customers_summary": test_case.customers_summary_sql, - **dict(test_case.later_models), - } - for model, upstream in test_case.expected_findings: - finding: dict[str, Any] = findings[model] - assert (finding["code"],) == test_case.expected_codes - assert finding["message"] == f"Unknown column 'missing' in {upstream}" - assert finding["location"]["column"] == sql_by_model[model].index("missing") + 1 - - -if __name__ == "__main__": - pytest.main([__file__, "-vv"]) diff --git a/tests/integration/src/sqlbuild/compiler/project_assembly/_test_types.py b/tests/integration/src/sqlbuild/compiler/project_assembly/_test_types.py index 1e010ed519..4377317896 100644 --- a/tests/integration/src/sqlbuild/compiler/project_assembly/_test_types.py +++ b/tests/integration/src/sqlbuild/compiler/project_assembly/_test_types.py @@ -12,29 +12,25 @@ class GeneratedAssemblyParityTestCase: count: int model_count: int environment: dict[str, str] - expected_minimum_python_calls: int expected_minimum_environment_reads: int @dataclass(frozen=True) class AssemblyDeferralTestCase: - """A project native hands back to Python, recording why, with Python's exact outcome.""" + """A project whose model SQL Python rejects with a syntax error.""" description: str files: dict[str, str] - expected_kind: str expected_error: str @dataclass(frozen=True) -class DeferredAssemblyTestCase: - """A project native hands back to Python, which assembles it without error.""" +class EdgeAssemblyTestCase: + """Projects whose assembly raises or reads Python-only values, against Python's golden.""" description: str - effective_vars: dict[str, object] - seed_schema: str - expected_schema: str - expected_kind: str + projects: tuple[tuple[str, dict[str, str], dict[str, object] | None], ...] + expected_raised: int @dataclass(frozen=True) @@ -54,4 +50,24 @@ class OptOutTestCase: description: str models: dict[str, str] expected_rejected: dict[str, bool] - expected_python_validations: int + + +@dataclass(frozen=True) +class GraphFactsTestCase: + """A project whose assembly request carries each resource's project-graph facts.""" + + description: str + files: dict[str, str] + expected_model_tags: tuple[list[str], ...] + expected_seeds: list[tuple[str, list[str]]] + expected_function_kinds: tuple[str, ...] + + +@dataclass(frozen=True) +class NativePanicTestCase: + """A project whose native assembly panics in the parser.""" + + description: str + files: dict[str, str] + dialect: str + expected_message: str diff --git a/tests/integration/src/sqlbuild/compiler/project_assembly/helpers.py b/tests/integration/src/sqlbuild/compiler/project_assembly/helpers.py index c8b4ded2df..b61931c5ed 100644 --- a/tests/integration/src/sqlbuild/compiler/project_assembly/helpers.py +++ b/tests/integration/src/sqlbuild/compiler/project_assembly/helpers.py @@ -2,20 +2,21 @@ from __future__ import annotations +import datetime import os import random from collections import Counter from collections.abc import Callable -from operator import methodcaller +from dataclasses import replace from pathlib import Path from typing import Any import pytest +import sqlbuild._native as _native from sqlbuild.adapters.duckdb.classes.duckdb_adapter import DuckDbAdapter from sqlbuild.compiler.compile._helpers.assembly import project as project_module from sqlbuild.compiler.compile._helpers.assembly.project import assemble_compiled_project -from sqlbuild.compiler.compile._helpers.diagnostics import sql_analysis_opt_outs from sqlbuild.compiler.compile.constants import COMPILE_INPUT_READS from sqlbuild.compiler.compile.main._build_compile_inputs import build_compile_inputs from sqlbuild.compiler.compile.models import ( @@ -26,20 +27,10 @@ from sqlbuild.compiler.discovery.main.discover import discover_project_inputs from sqlbuild.compiler.frontier.constants import COMPILER_ENGINE_ENV_VAR from sqlbuild.compiler.frontier.types import CompilerEngine +from sqlbuild.compiler.project_assembly.types import ProjectRequestRow from sqlbuild.sql_values.types import CollectionRendering -from tests.integration.src.sqlbuild.compiler.analysis_session.helpers import deferral_kinds - -_PYTHON_RESOURCE_FUNCTIONS: tuple[str, ...] = ( - "_build_source_relation_entry", - "build_seed_relation_target", - "validate_sql_syntax", - "validate_hook_sql_syntax", - "model_build_deps", - "function_build_deps", - "audit_scope_deps", -) -_ASSEMBLY_RECORD_PREFIX: str = "project_assembly:" -_OPT_OUT_VALIDATORS: tuple[str, ...] = ("validate_sql_syntax", "validate_hook_sql_syntax") + +_PYTHON_RESOURCE_FUNCTIONS: tuple[str, ...] = ("validate_sql_syntax", "validate_hook_sql_syntax") _ADAPTER_CONTEXT: CompileAdapterContext = CompileAdapterContext( value_renderer=DuckDbAdapter(), collection_rendering=CollectionRendering.VALUE_LIST, @@ -188,6 +179,35 @@ def recorded_assembly( return assembly_view(project), (reads.environment_names, reads.read_run_id) +def assembly_outcome( + *, + project_dir: Path, + files: dict[str, str], + effective_vars: dict[str, object] | None, + monkeypatch: pytest.MonkeyPatch, +) -> tuple[object, ...]: + """Attach and assemble `files`: `("ok", view)`, or the error's class, message, help and code.""" + + try: + inputs: CompileProjectInputs = project_inputs(project_dir=project_dir, files=files) + merged: CompileProjectInputs = replace( + inputs, effective_vars={**inputs.effective_vars, **(effective_vars or {})} + ) + return ( + "ok", + assembly_view( + assemble_with(inputs=merged, engine=CompilerEngine.NATIVE, monkeypatch=monkeypatch) + ), + ) + except Exception as error: + return ( + type(error).__name__, + str(error).replace(str(project_dir), ""), + getattr(error, "help", None), + getattr(error, "code", None), + ) + + def assembly_view(project: CompiledProject) -> object: """Return every resource fact native project assembly derives, with the diagnostics.""" @@ -207,45 +227,19 @@ def rejected_opt_outs( files: dict[str, str], engine: CompilerEngine, monkeypatch: pytest.MonkeyPatch, -) -> tuple[dict[str, bool], int]: - """Attach `files` with `engine`; return each opt-out's rejection and Python validations.""" +) -> dict[str, bool]: + """Attach `files` with `engine`; return whether each opt-out is rejected.""" - calls: Counter[str] = Counter() monkeypatch.setenv(COMPILER_ENGINE_ENV_VAR, engine.value) - with monkeypatch.context() as patch: - _ = [ - patch.setattr( - sql_analysis_opt_outs, - name, - _counted(name=name, function=getattr(sql_analysis_opt_outs, name), calls=calls), - ) - for name in _OPT_OUT_VALIDATORS - ] - inputs: CompileProjectInputs = project_inputs(project_dir=project_dir, files=files) - return ( - { - model_input.model_file.file_path.stem: ( - model_input.rejected_sql_analysis_opt_out is not None - ) - for model_input in inputs.model_inputs - }, - calls.total(), - ) - - -def assembly_deferrals(record_dir: Path) -> Counter[str]: - """Count the project assembly `site:kind` deferral records below `record_dir`.""" - - return Counter( - filter( - methodcaller("startswith", _ASSEMBLY_RECORD_PREFIX), - deferral_kinds(record_dir).elements(), - ) - ) + inputs: CompileProjectInputs = project_inputs(project_dir=project_dir, files=files) + return { + model_input.model_file.file_path.stem: model_input.rejected_sql_analysis_opt_out is not None + for model_input in inputs.model_inputs + } def python_resource_calls(*, monkeypatch: pytest.MonkeyPatch) -> Counter[str]: - """Count calls to Python's resource-fact functions from project assembly.""" + """Count calls to Python's model syntax error reporting from project assembly.""" calls: Counter[str] = Counter() _ = [ @@ -259,6 +253,20 @@ def python_resource_calls(*, monkeypatch: pytest.MonkeyPatch) -> Counter[str]: return calls +def record_assembly_requests(*, monkeypatch: pytest.MonkeyPatch) -> list[ProjectRequestRow]: + """Record every request the native project assembly receives.""" + + requests: list[ProjectRequestRow] = [] + original: Callable[..., Any] = _native.assemble_project_resource_facts + + def recording(request: ProjectRequestRow) -> Any: + requests.append(request) + return original(request) + + monkeypatch.setattr(_native, "assemble_project_resource_facts", recording) + return requests + + def _write(*, path: Path, contents: str) -> int: path.parent.mkdir(parents=True, exist_ok=True) return path.write_text(contents, encoding="utf-8") @@ -270,3 +278,305 @@ def counted(*args: Any, **kwargs: Any) -> Any: return function(*args, **kwargs) return counted + + +_EDGE_PROJECT: str = ( + 'name = "assembly"\nadapter = "duckdb"\ndefault_target = "dev"\n\n' + '[connection]\ndatabase = ":memory:"\n\n' +) +_EDGE_MODEL: str = ( + 'MODEL (description "Orders", database "lake", schema "orders");\n\nSELECT 1 AS n\n' +) +_EDGE_SOURCE: str = ( + "sources:\n - name: raw_orders\n description: Raw orders.\n managed: true\n" + " write_strategy: table\n{ns} columns:\n - name: n\n type: INTEGER\n" +) +_EDGE_LOADER: str = ( + "from sqlbuild.loaders import loader\n\n\n" + "@loader\ndef raw_orders(ctx):\n '''Load raw orders.'''\n return [{'n': 1}]\n" +) +_EDGE_VARS: dict[str, object] = { + "tags": ["daily", "x"], + "meta": {"b": 1, "a": "z"}, + "ratio": 1.5, + "day": datetime.date(2024, 1, 2), + "big": 10**30, + "flag": True, + "none": None, + "mixed": [datetime.date(2024, 1, 2)], + "name": "prod", +} + + +def _edge_seeds(*namespaces: str) -> str: + return "seeds:\n" + "".join( + f" - name: s{index}\n description: Seed {index}.\n{namespace}" + " columns:\n - name: n\n type: INTEGER\n" + for index, namespace in enumerate(namespaces) + ) + + +def _edge_seed_files(*namespaces: str) -> dict[str, str]: + return { + "seeds/lookups.yml": _edge_seeds(*namespaces), + "models/orders.sql": _EDGE_MODEL, + **{f"seeds/s{index}.csv": "n\n1\n" for index in range(len(namespaces))}, + } + + +def _edge_target(text: str) -> str: + return _EDGE_PROJECT + "[targets.dev]\n" + text + + +def _edge_source_files(ns: str = "") -> dict[str, str]: + return { + "sources/raw.yml": _EDGE_SOURCE.format(ns=ns), + "python/loaders/raw.py": _EDGE_LOADER, + "models/orders.sql": _EDGE_MODEL, + } + + +# Projects whose assembly raises, or reads variables only Python renders: (description, files, +# effective vars merged over the project's). +EDGE_ASSEMBLY_PROJECTS: tuple[tuple[str, dict[str, str], dict[str, object] | None], ...] = ( + ( + "seed schema missing env", + { + "sqlbuild_project.toml": _edge_target('schema = "dev"\n'), + **_edge_seed_files(' schema: "${ENV:SQB_EDGE_UNSET}"\n'), + }, + None, + ), + ( + "seed database unknown var", + { + "sqlbuild_project.toml": _edge_target('schema = "dev"\n'), + **_edge_seed_files(' database: "${var:nope}"\n'), + }, + None, + ), + ( + "seed unknown ctx", + { + "sqlbuild_project.toml": _edge_target('schema = "dev"\n'), + **_edge_seed_files(' schema: "${CTX:model.nope}"\n'), + }, + None, + ), + ( + "seed template syntax", + { + "sqlbuild_project.toml": _edge_target('schema = "dev"\n'), + **_edge_seed_files(' schema: "${coalesce(}"\n'), + }, + None, + ), + ( + "second seed fails after first", + { + "sqlbuild_project.toml": _edge_target('schema = "dev"\n'), + **_edge_seed_files(' schema: "ok"\n', ' schema: "${ENV:SQB_EDGE_UNSET}"\n'), + }, + None, + ), + ( + "preserved schema seed", + {"sqlbuild_project.toml": _edge_target('schema = "preserve"\n'), **_edge_seed_files("")}, + None, + ), + ( + "preserved database and schema seed", + { + "sqlbuild_project.toml": _edge_target('database = "preserve"\nschema = "preserve"\n'), + **_edge_seed_files(""), + }, + None, + ), + ( + "preserved managed source", + { + "sqlbuild_project.toml": _edge_target('database = "preserve"\nschema = "dev"\n'), + **_edge_source_files(), + }, + None, + ), + ( + "managed source target missing env", + { + "sqlbuild_project.toml": _edge_target('schema = "${ENV:SQB_EDGE_UNSET}"\n'), + **_edge_source_files(), + }, + None, + ), + ( + "managed source loader schema unknown var", + { + "sqlbuild_project.toml": _edge_target( + 'schema = "dev"\nloader_schema = "${var:nope}"\n' + ), + **_edge_source_files(), + }, + None, + ), + ( + "target schema override missing env", + { + "sqlbuild_project.toml": _edge_target('schema = "${ENV:SQB_EDGE_UNSET}"\n'), + **_edge_seed_files(""), + }, + None, + ), + ( + "target database override unknown var", + { + "sqlbuild_project.toml": _edge_target('database = "${var:nope}"\nschema = "dev"\n'), + **_edge_seed_files(""), + }, + None, + ), + ( + "default seed schema unknown var", + { + "sqlbuild_project.toml": _EDGE_PROJECT + + '[defaults]\nseed_schema = "${var:nope}"\n\n[targets.dev]\nschema = "dev"\n', + **_edge_seed_files(""), + }, + None, + ), + ( + "default database missing env", + { + "sqlbuild_project.toml": _EDGE_PROJECT + + '[defaults]\ndatabase = "${ENV:SQB_EDGE_UNSET}"\n\n[targets.dev]\nschema = "dev"\n', + **_edge_seed_files(""), + }, + None, + ), + ( + "model syntax error before seed error", + { + "sqlbuild_project.toml": _edge_target('schema = "dev"\n'), + **_edge_seed_files(' schema: "${ENV:SQB_EDGE_UNSET}"\n'), + "models/orders.sql": 'MODEL (description "Orders");\n\nSELECT FROM WHERE (\n', + }, + None, + ), + ( + "source error before seed error", + { + "sqlbuild_project.toml": _edge_target('schema = "${ENV:SQB_EDGE_UNSET}"\n'), + **_edge_source_files(), + "seeds/lookups.yml": _edge_seeds(' schema: "${var:nope}"\n'), + "seeds/s0.csv": "n\n1\n", + }, + None, + ), + ( + "list var whole", + { + "sqlbuild_project.toml": _edge_target('schema = "dev"\n'), + **_edge_seed_files(' schema: "${tags}"\n'), + }, + _EDGE_VARS, + ), + ( + "list var in text", + { + "sqlbuild_project.toml": _edge_target('schema = "dev"\n'), + **_edge_seed_files(' schema: "s_${tags}"\n'), + }, + _EDGE_VARS, + ), + ( + "dict var whole", + { + "sqlbuild_project.toml": _edge_target('schema = "dev"\n'), + **_edge_seed_files(' schema: "${meta}"\n'), + }, + _EDGE_VARS, + ), + ( + "dict var in text", + { + "sqlbuild_project.toml": _edge_target('schema = "dev"\n'), + **_edge_seed_files(' schema: "s_${var:meta}"\n'), + }, + _EDGE_VARS, + ), + ( + "float var whole and in text", + { + "sqlbuild_project.toml": _edge_target('schema = "dev"\n'), + **_edge_seed_files(' schema: "${ratio}"\n', ' schema: "s_${ratio}"\n'), + }, + _EDGE_VARS, + ), + ( + "date var whole", + { + "sqlbuild_project.toml": _edge_target('schema = "dev"\n'), + **_edge_seed_files(' schema: "${day}"\n'), + }, + _EDGE_VARS, + ), + ( + "date var in text", + { + "sqlbuild_project.toml": _edge_target('schema = "dev"\n'), + **_edge_seed_files(' schema: "s_${day}"\n'), + }, + _EDGE_VARS, + ), + ( + "big int var whole and in text", + { + "sqlbuild_project.toml": _edge_target('schema = "dev"\n'), + **_edge_seed_files(' schema: "${big}"\n', ' database: "d_${big}"\n'), + }, + _EDGE_VARS, + ), + ( + "bool and none vars", + { + "sqlbuild_project.toml": _edge_target('schema = "dev"\n'), + **_edge_seed_files(' schema: "${flag}"\n', ' schema: "s_${none}_${flag}"\n'), + }, + _EDGE_VARS, + ), + ( + "list of dates in text", + { + "sqlbuild_project.toml": _edge_target('schema = "dev"\n'), + **_edge_seed_files(' schema: "s_${mixed}"\n'), + }, + _EDGE_VARS, + ), + ( + "list var in coalesce", + { + "sqlbuild_project.toml": _edge_target('schema = "dev"\n'), + **_edge_seed_files(" schema: \"${coalesce(tags, 'x')}\"\n"), + }, + _EDGE_VARS, + ), + ( + "dict var in target schema text", + {"sqlbuild_project.toml": _edge_target('schema = "t_${meta}"\n'), **_edge_seed_files("")}, + _EDGE_VARS, + ), + ( + "float var in managed source target", + {"sqlbuild_project.toml": _edge_target('schema = "${ratio}"\n'), **_edge_source_files()}, + _EDGE_VARS, + ), + ( + "unused opaque vars", + { + "sqlbuild_project.toml": _EDGE_PROJECT + + '[vars]\nname = "prod"\n\n[targets.dev]\nschema = "dev_${name}"\n', + **_edge_seed_files(' schema: "s_${name}"\n'), + **_edge_source_files(), + }, + _EDGE_VARS, + ), +) diff --git a/tests/integration/src/sqlbuild/compiler/project_assembly/test_native_project_assembly.py b/tests/integration/src/sqlbuild/compiler/project_assembly/test_native_project_assembly.py index e88e498591..f7cf6d8ef6 100644 --- a/tests/integration/src/sqlbuild/compiler/project_assembly/test_native_project_assembly.py +++ b/tests/integration/src/sqlbuild/compiler/project_assembly/test_native_project_assembly.py @@ -1,34 +1,46 @@ -"""Native project assembly equals Python's resource assembly, or hands the project back.""" +"""Native project assembly equals Python's recorded resource assembly and its errors.""" from __future__ import annotations import os import random from collections import Counter -from dataclasses import replace from pathlib import Path import pytest +import sqlbuild._native as native_module +from sqlbuild.adapter.contract.models import ExpressionInferenceProfile +from sqlbuild.compiler.compile._helpers.assembly.project import assemble_compiled_project from sqlbuild.compiler.compile.exceptions import CompileInputError from sqlbuild.compiler.compile.models import CompiledProject, CompileProjectInputs +from sqlbuild.compiler.frontier.constants import COMPILER_ENGINE_ENV_VAR from sqlbuild.compiler.frontier.types import CompilerEngine -from sqlbuild.compiler.sql_analysis.constants import ANALYSIS_RECORD_DIR_ENV_VAR -from tests.integration.src.sqlbuild.compiler.helpers import mismatches +from sqlbuild.compiler.project_assembly.types import ProjectRequestRow +from tests.integration.src.sqlbuild.compiler.helpers import ( + GoldenEntry, + golden_differences, + golden_entry, + golden_name, + read_golden, +) from tests.integration.src.sqlbuild.compiler.project_assembly._test_types import ( AssemblyDeferralTestCase, - DeferredAssemblyTestCase, + EdgeAssemblyTestCase, GeneratedAssemblyParityTestCase, + GraphFactsTestCase, + NativePanicTestCase, OptOutTestCase, WindowsEnvironmentTestCase, ) from tests.integration.src.sqlbuild.compiler.project_assembly.helpers import ( + EDGE_ASSEMBLY_PROJECTS, assemble_with, - assembly_deferrals, - assembly_view, + assembly_outcome, generated_assembly_files, project_inputs, python_resource_calls, + record_assembly_requests, recorded_assembly, rejected_opt_outs, seed_yml, @@ -59,53 +71,87 @@ count=8, model_count=12, environment={"SQB_ASSEMBLY_LOADERS": "loaders"}, - expected_minimum_python_calls=200, expected_minimum_environment_reads=4, ) ], ids=lambda case: case.description, ) -def test_given_generated_projects_when_assembling_natively_then_matches_python( +def test_given_generated_projects_when_assembling_natively_then_matches_python_golden( test_case: GeneratedAssemblyParityTestCase, tmp_path: Path, monkeypatch: pytest.MonkeyPatch, ) -> None: - record_dir: Path = tmp_path / "records" - monkeypatch.setenv(ANALYSIS_RECORD_DIR_ENV_VAR, str(record_dir)) _ = [monkeypatch.setenv(name, value) for name, value in test_case.environment.items()] calls: Counter[str] = python_resource_calls(monkeypatch=monkeypatch) rng: random.Random = random.Random(test_case.seed) + project_dirs: list[Path] = [tmp_path / f"project_{index}" for index in range(test_case.count)] inputs: list[CompileProjectInputs] = [ project_inputs( - project_dir=tmp_path / f"project_{index}", + project_dir=project_dir, files=generated_assembly_files(rng=rng, model_count=test_case.model_count), ) - for index in range(test_case.count) - ] - python: list[tuple[object, tuple[tuple[str, ...], bool]]] = [ - recorded_assembly(inputs=item, engine=CompilerEngine.PYTHON, monkeypatch=monkeypatch) - for item in inputs + for project_dir in project_dirs ] - python_calls: int = calls.total() native: list[tuple[object, tuple[tuple[str, ...], bool]]] = [ - recorded_assembly( - inputs=item, engine=CompilerEngine.NATIVE_PREVIEW, monkeypatch=monkeypatch - ) + recorded_assembly(inputs=item, engine=CompilerEngine.NATIVE, monkeypatch=monkeypatch) for item in inputs ] + golden: list[GoldenEntry] = [ + golden_entry("project_assembly", view, masked=(str(project_dir),)) + for project_dir, view in zip(project_dirs, native, strict=True) + ] assert ( - mismatches( - inputs=list(range(test_case.count)), - expected=list[object](python), - actual=list[object](native), + golden_differences( + read_golden(golden_name("project_assembly", test_case.description)), golden ) == [] ) assert sum(len(reads[0]) for _, reads in native) >= test_case.expected_minimum_environment_reads - assert python_calls >= test_case.expected_minimum_python_calls - assert calls.total() == python_calls - assert assembly_deferrals(record_dir) == Counter() + assert calls == Counter() + + +@pytest.mark.parametrize( + "test_case", + [ + EdgeAssemblyTestCase( + description="error and python value edges", + projects=EDGE_ASSEMBLY_PROJECTS, + expected_raised=22, + ) + ], + ids=lambda case: case.description, +) +def test_given_projects_python_rejects_when_assembling_natively_then_matches_python_golden( + test_case: EdgeAssemblyTestCase, tmp_path: Path, monkeypatch: pytest.MonkeyPatch +) -> None: + monkeypatch.delenv("SQB_EDGE_UNSET", raising=False) + project_dirs: list[Path] = [ + tmp_path / f"edge_{index}" for index in range(len(test_case.projects)) + ] + outcomes: list[tuple[object, ...]] = [ + assembly_outcome( + project_dir=project_dir, + files=files, + effective_vars=effective_vars, + monkeypatch=monkeypatch, + ) + for project_dir, (_, files, effective_vars) in zip( + project_dirs, test_case.projects, strict=True + ) + ] + golden: list[GoldenEntry] = [ + golden_entry("project_assembly", outcome, masked=(str(project_dir),)) + for project_dir, outcome in zip(project_dirs, outcomes, strict=True) + ] + + assert ( + golden_differences( + read_golden(golden_name("project_assembly", test_case.description)), golden + ) + == [] + ) + assert sum(outcome[0] != "ok" for outcome in outcomes) == test_case.expected_raised @pytest.mark.parametrize( @@ -117,7 +163,6 @@ def test_given_generated_projects_when_assembling_natively_then_matches_python( "sqlbuild_project.toml": _PROJECT_TOML, "models/orders.sql": 'MODEL (description "Orders");\n\nSELECT FROM WHERE (\n', }, - expected_kind="syntax_error", expected_error="SQL syntax error in model 'orders'", ), AssemblyDeferralTestCase( @@ -129,106 +174,22 @@ def test_given_generated_projects_when_assembling_natively_then_matches_python( ");\n\nSELECT 1 AS n\n" ), }, - expected_kind="syntax_error", expected_error="Polyglot could not parse model 'orders' pre_hooks[0]", ), - AssemblyDeferralTestCase( - description="a seed schema reading an unset environment variable", - files={ - "sqlbuild_project.toml": _PROJECT_TOML, - "seeds/lookups.yml": seed_yml("${ENV:SQB_UNSET_SEED_SCHEMA}"), - **_SEED_FILES, - }, - expected_kind="target_template", - expected_error="references missing ENV variable 'SQB_UNSET_SEED_SCHEMA'", - ), - AssemblyDeferralTestCase( - description="a preserved target schema the seed does not own", - files={ - "sqlbuild_project.toml": ( - 'name = "assembly"\nadapter = "duckdb"\ndefault_target = "dev"\n\n' - '[connection]\ndatabase = ":memory:"\n\n[targets.dev]\nschema = "preserve"\n' - ), - "seeds/lookups.yml": ( - "seeds:\n - name: countries\n description: Countries.\n" - " columns:\n - name: n\n type: INTEGER\n" - ), - "seeds/countries.csv": "n\n1\n", - "models/orders.sql": ( - 'MODEL (description "Orders", schema "orders");\n\nSELECT 1 AS n\n' - ), - }, - expected_kind="preserved_namespace", - expected_error="Seed 'countries' has no logical schema", - ), ], ids=lambda case: case.description, ) -def test_given_projects_python_rejects_when_assembling_natively_then_defers_with_python_error( +def test_given_model_sql_the_parser_rejects_when_assembling_then_raises_python_error( test_case: AssemblyDeferralTestCase, tmp_path: Path, monkeypatch: pytest.MonkeyPatch, ) -> None: - record_dir: Path = tmp_path / "records" - monkeypatch.setenv(ANALYSIS_RECORD_DIR_ENV_VAR, str(record_dir)) inputs: CompileProjectInputs = project_inputs(project_dir=tmp_path, files=test_case.files) - with pytest.raises(CompileInputError) as python_error: - _ = assemble_with(inputs=inputs, engine=CompilerEngine.PYTHON, monkeypatch=monkeypatch) - with pytest.raises(CompileInputError) as native_error: - _ = assemble_with( - inputs=inputs, engine=CompilerEngine.NATIVE_PREVIEW, monkeypatch=monkeypatch - ) + with pytest.raises(CompileInputError) as raised: + _ = assemble_with(inputs=inputs, engine=CompilerEngine.NATIVE, monkeypatch=monkeypatch) - assert test_case.expected_error in str(python_error.value) - assert str(native_error.value) == str(python_error.value) - assert assembly_deferrals(record_dir) == Counter( - {f"project_assembly:{test_case.expected_kind}": 1} - ) - - -@pytest.mark.parametrize( - "test_case", - [ - DeferredAssemblyTestCase( - description="a seed schema reading a list variable", - effective_vars={"tags": ["daily"]}, - seed_schema="${tags}", - expected_schema="['daily']", - expected_kind="target_template", - ) - ], - ids=lambda case: case.description, -) -def test_given_a_variable_only_python_renders_when_assembling_natively_then_python_assembles( - test_case: DeferredAssemblyTestCase, tmp_path: Path, monkeypatch: pytest.MonkeyPatch -) -> None: - record_dir: Path = tmp_path / "records" - monkeypatch.setenv(ANALYSIS_RECORD_DIR_ENV_VAR, str(record_dir)) - inputs: CompileProjectInputs = replace( - project_inputs( - project_dir=tmp_path, - files={ - "sqlbuild_project.toml": _PROJECT_TOML, - "seeds/lookups.yml": seed_yml(test_case.seed_schema), - **_SEED_FILES, - }, - ), - effective_vars=test_case.effective_vars, - ) - - python: CompiledProject = assemble_with( - inputs=inputs, engine=CompilerEngine.PYTHON, monkeypatch=monkeypatch - ) - native: CompiledProject = assemble_with( - inputs=inputs, engine=CompilerEngine.NATIVE_PREVIEW, monkeypatch=monkeypatch - ) - - assert assembly_view(native) == assembly_view(python) - assert native.seeds[0].destination.schema == test_case.expected_schema - assert assembly_deferrals(record_dir) == Counter( - {f"project_assembly:{test_case.expected_kind}": 1} - ) + assert test_case.expected_error in str(raised.value) @pytest.mark.parametrize( @@ -246,9 +207,7 @@ def test_given_a_variable_only_python_renders_when_assembling_natively_then_pyth def test_given_windows_environment_when_assembling_natively_then_env_lookups_match_python( test_case: WindowsEnvironmentTestCase, tmp_path: Path, monkeypatch: pytest.MonkeyPatch ) -> None: - record_dir: Path = tmp_path / "records" monkeypatch.setattr(os, "environ", windows_environ(test_case.environment)) - monkeypatch.setenv(ANALYSIS_RECORD_DIR_ENV_VAR, str(record_dir)) inputs: CompileProjectInputs = project_inputs( project_dir=tmp_path, files={ @@ -258,16 +217,11 @@ def test_given_windows_environment_when_assembling_natively_then_env_lookups_mat }, ) - python: CompiledProject = assemble_with( - inputs=inputs, engine=CompilerEngine.PYTHON, monkeypatch=monkeypatch - ) native: CompiledProject = assemble_with( - inputs=inputs, engine=CompilerEngine.NATIVE_PREVIEW, monkeypatch=monkeypatch + inputs=inputs, engine=CompilerEngine.NATIVE, monkeypatch=monkeypatch ) - assert python.seeds[0].destination.schema == test_case.expected_schema - assert assembly_view(native) == assembly_view(python) - assert assembly_deferrals(record_dir) == Counter() + assert native.seeds[0].destination.schema == test_case.expected_schema @pytest.mark.parametrize( @@ -284,7 +238,6 @@ def test_given_windows_environment_when_assembling_natively_then_env_lookups_mat ), }, expected_rejected={"broken_hook": False, "broken_query": False, "parses": True}, - expected_python_validations=7, ) ], ids=lambda case: case.description, @@ -292,23 +245,114 @@ def test_given_windows_environment_when_assembling_natively_then_env_lookups_mat def test_given_sql_analysis_opt_outs_when_attaching_natively_then_python_rejections_match( test_case: OptOutTestCase, tmp_path: Path, monkeypatch: pytest.MonkeyPatch ) -> None: - record_dir: Path = tmp_path / "records" - monkeypatch.setenv(ANALYSIS_RECORD_DIR_ENV_VAR, str(record_dir)) files: dict[str, str] = {"sqlbuild_project.toml": _REQUIRED_ANALYSIS_TOML, **test_case.models} - python: tuple[dict[str, bool], int] = rejected_opt_outs( - project_dir=tmp_path / "python", + native: dict[str, bool] = rejected_opt_outs( + project_dir=tmp_path / "native", files=files, - engine=CompilerEngine.PYTHON, + engine=CompilerEngine.NATIVE, monkeypatch=monkeypatch, ) - native: tuple[dict[str, bool], int] = rejected_opt_outs( - project_dir=tmp_path / "native", - files=files, - engine=CompilerEngine.NATIVE_PREVIEW, + + assert native == test_case.expected_rejected + + +@pytest.mark.parametrize( + "test_case", + [ + GraphFactsTestCase( + description="tagged models in folders, tagged seeds and both function kinds", + files={ + "sqlbuild_project.toml": 'name = "orders"\nadapter = "duckdb"\n', + "models/staging/orders.sql": ( + "MODEL (description 'Orders.', tags [daily, finance]);\n\nSELECT 1 AS id\n" + ), + "models/customers.sql": ( + "MODEL (description 'Customers.');\n\nSELECT id FROM __ref(\"orders\")\n" + ), + "seeds/regions.yml": ( + "seeds:\n - name: regions\n description: Regions.\n" + " tags: [lookup]\n columns:\n - name: n\n type: INTEGER\n" + ), + "seeds/regions.csv": "n\n1\n", + "functions/sql/is_big.sql": ( + "FUNCTION (description 'Big.', arguments (x INTEGER), returns BOOLEAN," + " tags [math]);\n\nx > 100\n" + ), + "functions/sql/order_ids.sql": ( + "FUNCTION (description 'Ids.', arguments (x INTEGER)," + ' returns table (id INTEGER));\n\nSELECT id FROM __ref("orders")\n' + ), + }, + expected_model_tags=([], ["daily", "finance"]), + expected_seeds=[("regions", ["lookup"])], + expected_function_kinds=("udf", "table_fn"), + ) + ], + ids=lambda case: case.description, +) +def test_given_project_when_assembling_natively_then_request_carries_graph_facts( + test_case: GraphFactsTestCase, tmp_path: Path, monkeypatch: pytest.MonkeyPatch +) -> None: + requests: list[ProjectRequestRow] = record_assembly_requests(monkeypatch=monkeypatch) + project: CompiledProject = assemble_with( + inputs=project_inputs(project_dir=tmp_path / "project", files=test_case.files), + engine=CompilerEngine.NATIVE, monkeypatch=monkeypatch, ) + request: ProjectRequestRow = requests[0] + + assert ( + [(name, directory, tags) for name, directory, tags, _, _ in request[5]], + [(name, tags) for name, tags, _, _ in request[7]], + [(kind, name, tags) for kind, name, tags, _ in request[8]], + ) == ( + [ + (model.key.name, str(model.relative_path.parent)) + (tags,) + for model, tags in zip(project.models, test_case.expected_model_tags, strict=True) + ], + test_case.expected_seeds, + [ + (str(function.key.resource_type), function.key.name, list(function.tags)) + for function in project.functions + ], + ) + assert [kind for kind, _, _, _ in request[8]] == list(test_case.expected_function_kinds) + + +@pytest.mark.parametrize( + "test_case", + [ + NativePanicTestCase( + description="a T-SQL hook the parser panics on", + files={ + "sqlbuild_project.toml": _PROJECT_TOML, + "models/orders.sql": ( + 'MODEL (\n description "Orders",\n' + ' pre_hooks [inline_sql("SELECT IF(region > 1, re")],\n);\n\nSELECT 1 AS n\n' + ), + }, + dialect="tsql", + expected_message=( + "NativeCompilerError: native SQL compilation panicked (native project assembly)" + ), + ), + ], + ids=lambda case: case.description, +) +def test_given_native_assembly_panics_when_assembling_then_raises_without_python_retry( + test_case: NativePanicTestCase, tmp_path: Path, monkeypatch: pytest.MonkeyPatch +) -> None: + monkeypatch.setenv(COMPILER_ENGINE_ENV_VAR, CompilerEngine.NATIVE.value) + inputs: CompileProjectInputs = project_inputs( + project_dir=tmp_path / "project", files=test_case.files + ) + calls: Counter[str] = python_resource_calls(monkeypatch=monkeypatch) + + with pytest.raises(native_module.NativeCompilerError) as raised: + _ = assemble_compiled_project( + inputs=inputs, + inference_profile=ExpressionInferenceProfile(sql_analysis_dialect=test_case.dialect), + ) - assert python == (test_case.expected_rejected, test_case.expected_python_validations) - assert native == (test_case.expected_rejected, 0) - assert assembly_deferrals(record_dir) == Counter() + assert (str(raised.value), calls) == (test_case.expected_message, Counter()) diff --git a/tests/integration/src/sqlbuild/compiler/scopes/_test_types.py b/tests/integration/src/sqlbuild/compiler/scopes/_test_types.py index 7941204fd0..9dea85abbd 100644 --- a/tests/integration/src/sqlbuild/compiler/scopes/_test_types.py +++ b/tests/integration/src/sqlbuild/compiler/scopes/_test_types.py @@ -46,15 +46,24 @@ class ScopeEngineTierTestCase: @dataclass(frozen=True) class ExpectedNameScanTestCase: - """Seeded SQL test bodies scanned for expected models natively and in Python.""" + """Seeded SQL test bodies whose relationship scans match Python's recorded golden.""" description: str syntax: str seed: int count: int expected_minimum_scanned: int - expected_minimum_python_errors: int - expected_minimum_native_errors: int + expected_minimum_errors: int + + +@dataclass(frozen=True) +class RelationshipEdgeTestCase: + """SQL texts around Unicode identifier and keyword edges, against Python's golden.""" + + description: str + characters: tuple[str, ...] + expected_minimum_scanned: int + expected_minimum_errors: int @dataclass(frozen=True) diff --git a/tests/integration/src/sqlbuild/compiler/scopes/helpers.py b/tests/integration/src/sqlbuild/compiler/scopes/helpers.py index b747c973b0..1759570dc4 100644 --- a/tests/integration/src/sqlbuild/compiler/scopes/helpers.py +++ b/tests/integration/src/sqlbuild/compiler/scopes/helpers.py @@ -17,23 +17,14 @@ from sqlbuild.compiler.compile._helpers.attachment.declaration_scope import build_declaration_scope from sqlbuild.compiler.compile._helpers.render.declarations import resolve_declaration_context from sqlbuild.compiler.compile._helpers.render.macros import load_project_macros -from sqlbuild.compiler.compile._helpers.scenarios.core import ( - extract_sql_scenario_expected_model_names, -) -from sqlbuild.compiler.compile._helpers.sql_tests.core import ( - extract_sql_test_expected_model_names, - extract_top_level_ctes_with_scanner, -) from sqlbuild.compiler.compile._helpers.sql_tests.native import native_sql_test_ctes from sqlbuild.compiler.compile.exceptions import CompileInputError from sqlbuild.compiler.compile.models import ( - CompileSqlTestCte, DeclarationResolutionContext, DeclarationScopeBuild, DeclarationScopeResolver, LoadedMacro, ) -from sqlbuild.compiler.compile.types import SqlTestMode from sqlbuild.compiler.discovery.exceptions import DiscoveryError from sqlbuild.compiler.discovery.main.discover import discover_project_inputs from sqlbuild.compiler.discovery.models import ( @@ -73,7 +64,7 @@ VisibilityReason, ) from sqlbuild.compiler.sql_analysis.models import SqlLexicalSyntax -from tests.integration.src.sqlbuild.compiler.helpers import mismatches +from tests.integration.src.sqlbuild.compiler.helpers import GoldenEntry, golden_entry PROJECT_CONFIG: str = ( 'name = "scope_parity"\nadapter = "duckdb"\n\n[connection]\ndatabase = "scope.duckdb"\n' @@ -311,7 +302,7 @@ def _expected_model_test(*, index: int, calls: str, expected: list[str]) -> str: def scope_engine_outcomes( *, project_dir: Path, monkeypatch: pytest.MonkeyPatch ) -> tuple[ScopeOutcome, ScopeOutcome, bool]: - """Return the Python and native scope outcomes and whether the native index was built.""" + """Return the shipped and preview scope outcomes and whether the native index was built.""" try: discovered: DiscoveredProjectInputs = discover_project_inputs(project_dir=project_dir) @@ -320,11 +311,11 @@ def scope_engine_outcomes( failure: ScopeOutcome = ScopeOutcome(kind="discovery", value=(), error=str(error)) return failure, failure, True syntax: SqlLexicalSyntax = DuckDbAdapter().sql_lexical_syntax - python: ScopeOutcome = _scope_outcome( + shipped: ScopeOutcome = _scope_outcome( discovered=discovered, macros=macros, syntax=syntax, - engine="python", + engine=CompilerEngine.NATIVE.value, monkeypatch=monkeypatch, ) native: ScopeOutcome = _scope_outcome( @@ -335,19 +326,19 @@ def scope_engine_outcomes( monkeypatch=monkeypatch, ) _ = open_native_scope_index(discovered_inputs=discovered, loaded_macros=macros) - return python, native, True + return shipped, native, True def scope_command_indexes( *, project_dir: Path, monkeypatch: pytest.MonkeyPatch ) -> tuple[ScopeIndex, ScopeIndex]: - """Return the offline `sqb scope` index under the Python and native engines.""" + """Return the offline `sqb scope` index under the shipped and preview engines.""" - monkeypatch.setenv(COMPILER_ENGINE_ENV_VAR, "python") - python: ScopeIndex = load_or_build_scope_index(project_dir=project_dir, no_cache=True) + monkeypatch.setenv(COMPILER_ENGINE_ENV_VAR, CompilerEngine.NATIVE.value) + shipped: ScopeIndex = load_or_build_scope_index(project_dir=project_dir, no_cache=True) monkeypatch.setenv(COMPILER_ENGINE_ENV_VAR, CompilerEngine.NATIVE_PREVIEW.value) native: ScopeIndex = load_or_build_scope_index(project_dir=project_dir, no_cache=True) - return python, native + return shipped, native def native_scope_attempts( @@ -492,13 +483,12 @@ def _lookup_shape(lookup: ScopeLookup) -> tuple[object, ...]: @dataclass(frozen=True) -class ExpectedNameScanParity: - """How the native relationship scans compared with Python over one corpus.""" +class RelationshipScans: + """The native relationship scans of one corpus as golden entries, and how many failed.""" - mismatches: list[tuple[object, object, object]] + golden: list[GoldenEntry] scanned: int - python_errors: int - native_errors: int + errors: int def generated_expected_model_sqls(*, rng: random.Random, count: int) -> list[str]: @@ -515,62 +505,69 @@ def _generated_expected_model_sql(*, rng: random.Random) -> str: return f"{rng.choice(_LEADING)}{rng.choice(_WITH)}{','.join(ctes)}{rng.choice(_TRAILING)}" -def expected_name_scan_parity( - *, sqls: list[str], syntax: SqlLexicalSyntax -) -> ExpectedNameScanParity: - """Compare each native scan, test and scenario names and test CTEs, with Python's result.""" +def relationship_scans(*, sqls: list[str], syntax: SqlLexicalSyntax) -> RelationshipScans: + """Scan each SQL text's test names, scenario names and test CTEs natively.""" test_texts: list[tuple[str, str]] = [(sql, _TEST_LABEL) for sql in sqls] scenario_texts: list[tuple[str, str]] = [(sql, _SCENARIO_LABEL) for sql in sqls] - native: list[object] = [ - *native_expected_model_names(texts=test_texts, scenario=False, syntax=syntax), - *native_expected_model_names(texts=scenario_texts, scenario=True, syntax=syntax), - *native_sql_test_ctes(texts=test_texts, syntax=syntax), - ] - python: list[object] = [ - *(_python_expected_names(sql=sql, syntax=syntax) for sql in sqls), - *(_python_scenario_names(sql=sql, syntax=syntax) for sql in sqls), - *(_python_test_ctes(sql=sql, syntax=syntax) for sql in sqls), - ] - return ExpectedNameScanParity( - mismatches=mismatches(inputs=[*sqls, *sqls, *sqls], expected=python, actual=native), - scanned=sum(isinstance(outcome, tuple) for outcome in native), - python_errors=sum(isinstance(outcome, str) for outcome in python), - native_errors=sum(isinstance(outcome, str) for outcome in native), + outcomes: list[tuple[object, object, object]] = list( + zip( + native_expected_model_names(texts=test_texts, scenario=False, syntax=syntax), + native_expected_model_names(texts=scenario_texts, scenario=True, syntax=syntax), + native_sql_test_ctes(texts=test_texts, syntax=syntax), + strict=True, + ) + ) + flat: list[object] = list(chain.from_iterable(outcomes)) + return RelationshipScans( + golden=[golden_entry("relationship_scan", outcome) for outcome in outcomes], + scanned=sum(isinstance(outcome, tuple) for outcome in flat), + errors=sum(isinstance(outcome, str) for outcome in flat), ) -def _python_expected_names(*, sql: str, syntax: SqlLexicalSyntax) -> tuple[str, ...] | str: - try: - return extract_sql_test_expected_model_names( - sql=sql, file_label=_TEST_LABEL, syntax=syntax, mode=SqlTestMode.MODEL - ) - except CompileInputError as error: - return str(error) - +UNICODE_RELATIONSHIP_CHARACTERS: tuple[str, ...] = ( + "\u0345", + "\u216b", + "\u00b2", + "\u0663", + "\u00e9", + "\u1885", + "\u2160", + "\u00aa", + "\u02b0", + "\u0300", + "\U0001d7ce", + "\u2155", + "\u00df", + "\ufb00", + "\u0130", + "\u1e9e", +) +_UNICODE_RELATIONSHIP_TEMPLATES: tuple[str, ...] = ( + "WITH {c}x AS (SELECT 1) SELECT 1", + "WITH x{c} AS (SELECT 1) SELECT 1", + "WITH __expected__a{c} AS (SELECT 1)", + "WITH __expected__a AS (SELECT 1) {c}", + "{c}WITH x AS (SELECT 1)", + "WITH{c} x AS (SELECT 1)", + "WITH x AS{c}(SELECT 1)", + "WITH x AS (SELECT 1) SELECT{c} 1", + "WITH x AS (SELECT 1) ,{c}y AS (SELECT 2)", + "wit{c} x AS (SELECT 1)", + "WITH x a{c} (SELECT 1)", +) -def _python_scenario_names(*, sql: str, syntax: SqlLexicalSyntax) -> tuple[str, ...] | str: - try: - return extract_sql_scenario_expected_model_names( - sql=sql, file_label=_SCENARIO_LABEL, syntax=syntax - ) - except CompileInputError as error: - return str(error) +def unicode_relationship_sqls(characters: tuple[str, ...]) -> list[str]: + """Each template around each character: identifier, keyword and separator edges.""" -def _python_test_ctes(*, sql: str, syntax: SqlLexicalSyntax) -> tuple[tuple[str, str], ...] | str: - try: - ctes: tuple[CompileSqlTestCte, ...] = extract_top_level_ctes_with_scanner( - sql=sql, - file_label=_TEST_LABEL, - context_label="SQL test", - with_requirement="mock CTEs and one __expected__ CTE", - cte_type=CompileSqlTestCte, - syntax=syntax, + return list( + chain.from_iterable( + map(lambda template: template.format(c=character), _UNICODE_RELATIONSHIP_TEMPLATES) + for character in characters ) - except CompileInputError as error: - return str(error) - return tuple((cte.name, cte.sql_body) for cte in ctes) + ) @dataclass(frozen=True) diff --git a/tests/integration/src/sqlbuild/compiler/scopes/test_native_relationship_names.py b/tests/integration/src/sqlbuild/compiler/scopes/test_native_relationship_names.py index f895659c40..40eca955fc 100644 --- a/tests/integration/src/sqlbuild/compiler/scopes/test_native_relationship_names.py +++ b/tests/integration/src/sqlbuild/compiler/scopes/test_native_relationship_names.py @@ -1,4 +1,4 @@ -"""The native relationship scans return Python's names, CTEs and errors exactly.""" +"""The native relationship scans return Python's recorded names, CTEs and errors exactly.""" from __future__ import annotations @@ -6,12 +6,22 @@ import pytest -from tests.integration.src.sqlbuild.compiler.scopes._test_types import ExpectedNameScanTestCase +from tests.integration.src.sqlbuild.compiler.helpers import ( + golden_differences, + golden_name, + read_golden, +) +from tests.integration.src.sqlbuild.compiler.scopes._test_types import ( + ExpectedNameScanTestCase, + RelationshipEdgeTestCase, +) from tests.integration.src.sqlbuild.compiler.scopes.helpers import ( LEXICAL_SYNTAXES, - ExpectedNameScanParity, - expected_name_scan_parity, + UNICODE_RELATIONSHIP_CHARACTERS, + RelationshipScans, generated_expected_model_sqls, + relationship_scans, + unicode_relationship_sqls, ) @@ -24,35 +34,59 @@ seed=20261007 + offset, count=3000, expected_minimum_scanned=300, - expected_minimum_python_errors=300, - expected_minimum_native_errors=3000, + expected_minimum_errors=3000, ) for offset, syntax in enumerate(LEXICAL_SYNTAXES) ], ids=lambda case: case.description, ) -def test_given_generated_sql_when_scanning_relationships_then_native_matches_python( +def test_given_generated_sql_when_scanning_relationships_then_native_matches_python_golden( test_case: ExpectedNameScanTestCase, ) -> None: sqls: list[str] = generated_expected_model_sqls( rng=random.Random(test_case.seed), count=test_case.count ) - parity: ExpectedNameScanParity = expected_name_scan_parity( + scans: RelationshipScans = relationship_scans( sqls=sqls, syntax=LEXICAL_SYNTAXES[test_case.syntax] ) assert ( - parity.mismatches, - parity.scanned >= test_case.expected_minimum_scanned, - parity.python_errors >= test_case.expected_minimum_python_errors, - parity.native_errors >= test_case.expected_minimum_native_errors, - ) == ([], True, True, True), ( - parity.scanned, - parity.python_errors, - parity.native_errors, + golden_differences( + read_golden(golden_name("relationship_scan", test_case.description)), scans.golden + ), + scans.scanned >= test_case.expected_minimum_scanned, + scans.errors >= test_case.expected_minimum_errors, + ) == ([], True, True), (scans.scanned, scans.errors) + + +@pytest.mark.parametrize( + "test_case", + [ + RelationshipEdgeTestCase( + description="unicode identifier and keyword edges", + characters=UNICODE_RELATIONSHIP_CHARACTERS, + expected_minimum_scanned=100, + expected_minimum_errors=100, + ) + ], + ids=lambda case: case.description, +) +def test_given_unicode_edges_when_scanning_relationships_then_native_matches_python_golden( + test_case: RelationshipEdgeTestCase, +) -> None: + scans: RelationshipScans = relationship_scans( + sqls=unicode_relationship_sqls(test_case.characters), syntax=LEXICAL_SYNTAXES["generic"] ) + assert ( + golden_differences( + read_golden(golden_name("relationship_scan", test_case.description)), scans.golden + ), + scans.scanned >= test_case.expected_minimum_scanned, + scans.errors >= test_case.expected_minimum_errors, + ) == ([], True, True), (scans.scanned, scans.errors) + if __name__ == "__main__": pytest.main([__file__, "-vv"]) diff --git a/tests/integration/src/sqlbuild/compiler/scopes/test_native_scope_parity.py b/tests/integration/src/sqlbuild/compiler/scopes/test_native_scope_parity.py index 85375d41ea..50e759cac3 100644 --- a/tests/integration/src/sqlbuild/compiler/scopes/test_native_scope_parity.py +++ b/tests/integration/src/sqlbuild/compiler/scopes/test_native_scope_parity.py @@ -135,13 +135,13 @@ def test_given_scoped_project_when_building_scope_under_each_engine_then_outcome ) -> None: write_project(project_dir=tmp_path, files=test_case.files) - python, native, built = scope_engine_outcomes(project_dir=tmp_path, monkeypatch=monkeypatch) + shipped, native, built = scope_engine_outcomes(project_dir=tmp_path, monkeypatch=monkeypatch) assert ( - native == python, + native == shipped, built, - (python.kind == "error") == bool(test_case.expected_error), - test_case.expected_error in python.error, + (shipped.kind == "error") == bool(test_case.expected_error), + test_case.expected_error in shipped.error, native.grants >= test_case.expected_minimum_grants, ) == (True, True, True, True, True), test_case.description @@ -173,18 +173,18 @@ def test_given_generated_scoped_projects_when_building_scope_then_engines_match( for project_dir in project_dirs ] - python: list[ScopeOutcome] = [outcome[0] for outcome in outcomes] + shipped: list[ScopeOutcome] = [outcome[0] for outcome in outcomes] native: list[ScopeOutcome] = [outcome[1] for outcome in outcomes] assert ( mismatches( inputs=[path.name for path in project_dirs], - expected=[*python], + expected=[*shipped], actual=[*native], ), all(outcome[2] for outcome in outcomes), - sum(item.kind == "ok" for item in python) >= test_case.expected_minimum_valid, - sum(item.kind == "error" for item in python) >= test_case.expected_minimum_invalid, - sum(item.grants > 0 for item in python) >= test_case.expected_minimum_granting, + sum(item.kind == "ok" for item in shipped) >= test_case.expected_minimum_valid, + sum(item.kind == "error" for item in shipped) >= test_case.expected_minimum_invalid, + sum(item.grants > 0 for item in shipped) >= test_case.expected_minimum_granting, ) == (list(test_case.expected_mismatches), True, True, True, True), test_case.description @@ -204,9 +204,9 @@ def test_given_scoped_project_when_scope_command_builds_index_then_engines_match ) -> None: write_project(project_dir=tmp_path, files=test_case.files) - python, native = scope_command_indexes(project_dir=tmp_path, monkeypatch=monkeypatch) + shipped, native = scope_command_indexes(project_dir=tmp_path, monkeypatch=monkeypatch) - assert (native == python, len(native.grants) >= test_case.expected_minimum_grants) == ( + assert (native == shipped, len(native.grants) >= test_case.expected_minimum_grants) == ( True, True, ), test_case.description @@ -215,11 +215,6 @@ def test_given_scoped_project_when_scope_command_builds_index_then_engines_match @pytest.mark.parametrize( "test_case", [ - ScopeEngineTierTestCase( - description="python engine, since the compile scope index is native-only", - engine="python", - expected_native_attempts=1, - ), ScopeEngineTierTestCase( description="shipped native stages", engine="native", expected_native_attempts=1 ), diff --git a/tests/integration/src/sqlbuild/compiler/semantic_checks/_test_types.py b/tests/integration/src/sqlbuild/compiler/semantic_checks/_test_types.py index 10a8a6c3d3..eb81e271aa 100644 --- a/tests/integration/src/sqlbuild/compiler/semantic_checks/_test_types.py +++ b/tests/integration/src/sqlbuild/compiler/semantic_checks/_test_types.py @@ -5,7 +5,7 @@ @dataclass(frozen=True) class GeneratedSemanticParityTestCase: - """Seeded failing projects whose semantic completion Python and the native engine agree on.""" + """Seeded failing projects whose native completion matches the recorded Python outputs.""" description: str seed: int @@ -19,25 +19,36 @@ class GeneratedSemanticParityTestCase: @dataclass(frozen=True) -class DeferredSemanticTestCase: - """A project the native stage hands back to Python, which records the deferral.""" +class FormerlyDeferredSemanticTestCase: + """Projects the native stage once handed back to Python, now answered or raising natively.""" description: str - dialect: str - keeps_catalog: bool - non_ascii_comment: bool - expected_kinds: tuple[tuple[str, str], ...] + seed: int + count: int + non_ascii: bool + dialects: tuple[str | None, ...] + expected_outcomes: frozenset[str] + + +@dataclass(frozen=True) +class MissingCatalogTestCase: + """A project without the analysis catalog every compile builds.""" + + description: str + expected_message: str @dataclass(frozen=True) class GeneratedMetadataParityTestCase: - """Seeded projects whose metadata checks Python and the native engine must agree on.""" + """Seeded projects whose native metadata checks match the recorded Python outputs.""" description: str seed: int count: int model_count: int - dialects: tuple[str, ...] + dialects: tuple[str | None, ...] + non_ascii: bool + golden_prefix: str expected_minimum_native: int expected_minimum_families: dict[str, int] diff --git a/tests/integration/src/sqlbuild/compiler/semantic_checks/helpers.py b/tests/integration/src/sqlbuild/compiler/semantic_checks/helpers.py index 8cbb77988d..3807594f49 100644 --- a/tests/integration/src/sqlbuild/compiler/semantic_checks/helpers.py +++ b/tests/integration/src/sqlbuild/compiler/semantic_checks/helpers.py @@ -1,7 +1,8 @@ from __future__ import annotations -import json +import functools import random +import re from collections import Counter from collections.abc import Callable from dataclasses import dataclass, replace @@ -16,9 +17,6 @@ import sqlbuild.compiler.semantic_checks._helpers.stage as semantic_stage from sqlbuild.adapter.contract.models import ExpressionInferenceProfile from sqlbuild.adapters.duckdb.classes.duckdb_adapter import DuckDbAdapter -from sqlbuild.compiler.compile._helpers.assembly.metadata_validation import ( - get_semantic_metadata_diagnostics, -) from sqlbuild.compiler.compile._helpers.diagnostics.recovery import ( complete_semantic_diagnostics, ) @@ -67,12 +65,25 @@ type: DATE """ _OPT_OUT_SHARE: float = 0.2 +_NON_ASCII_NAMES: list[tuple[str, str]] = [ + ("amount", "am\u00f6unt"), + ("status", "\u017ftatus"), + ("customer_id", "customer_\u0130d"), + ("order_date", "order_d\u0101te"), + ("value", "va\u212alue"), + ("ordered_at", "ordered_\u0430t"), +] +_NON_ASCII_COMMENTS: tuple[str, ...] = ( + " /* caf\u00e9 \u00df \u2028 \u0131 */ ", + " -- na\u00efve\u0085x\n", + " /* \u0663\u0664 \u3000 */ ", + " ", +) _TYPO_SHARE: float = 0.45 _MIN_TYPO_LENGTH: int = 4 _ALIASES: tuple[tuple[str, str], ...] = (("", ""), ("o.", " AS o")) _SETTINGS: tuple[str, str] = ("", "\n[settings]\nrequire_sql_analysis = true\n") _OPT_OUTS: tuple[str, str] = ("", ", sql_analysis false") -_COMPLETION_STATUSES: tuple[str, str] = ("completion_native", "completion_deferred") _SOURCE_COMPARISON_SHARE: float = 0.6 type _Template = Callable[[random.Random, str, tuple[str, ...]], tuple[str, tuple[str, ...]]] @@ -183,7 +194,7 @@ def captured_semantic_inputs( project_dir: Path, files: dict[str, str], monkeypatch: pytest.MonkeyPatch, - engine: str = "python", + engine: str = "native", ) -> SemanticInputs: """Compile with `engine` and keep the semantic completion stage's inputs.""" @@ -207,7 +218,7 @@ def capture(**arguments: Any) -> CompiledProject: return captured[0] -def with_dialect(inputs: SemanticInputs, dialect: str) -> SemanticInputs: +def with_dialect(inputs: SemanticInputs, dialect: str | None) -> SemanticInputs: """The same stage inputs read under another SQL dialect.""" return replace( @@ -217,27 +228,10 @@ def with_dialect(inputs: SemanticInputs, dialect: str) -> SemanticInputs: ) -def python_completion( - *, inputs: SemanticInputs, monkeypatch: pytest.MonkeyPatch -) -> CompiledProject: - """The Python engine's completed project.""" - - with monkeypatch.context() as patch: - patch.setenv(COMPILER_ENGINE_ENV_VAR, "python") - return complete_semantic_diagnostics( - project=inputs.project, - profile=inputs.profile, - binding_results=inputs.binding_results, - resource_sql_analysis=inputs.resource_sql_analysis, - ) - - def completed_natively(inputs: SemanticInputs) -> CompiledProject: - """The native stage's completed project, which must not defer.""" + """The native stage's completed project.""" - project: CompiledProject | None = native_completion(inputs) - assert project is not None - return project + return native_completion(inputs) def note_kinds(project: CompiledProject, kinds: tuple[str, ...]) -> Counter[str]: @@ -250,8 +244,8 @@ def note_kinds(project: CompiledProject, kinds: tuple[str, ...]) -> Counter[str] return counts -def native_completion(inputs: SemanticInputs) -> CompiledProject | None: - """The native stage's completed project, or None when it defers.""" +def native_completion(inputs: SemanticInputs) -> CompiledProject: + """The native stage's completed project.""" return complete_native_semantic_diagnostics( project=inputs.project, @@ -322,7 +316,7 @@ def _model_view(model: CompiledModel) -> tuple[object, ...]: def record_native_statuses(*, monkeypatch: pytest.MonkeyPatch) -> Counter[str]: - """Count native type recovery plans and completed or deferred completions.""" + """Count native type recovery plans, completions and completed diagnostics.""" statuses: Counter[str] = Counter() plan: Callable[..., Any] = native_module.plan_semantic_type_recovery @@ -335,8 +329,8 @@ def counted_plan(*arguments: Any) -> Any: def counted_complete(*arguments: Any) -> Any: outcome: Any = complete(*arguments) - statuses[_COMPLETION_STATUSES[outcome[0] is not None]] += 1 - statuses["diagnostics_native"] += len(outcome[1]) + statuses["completion_native"] += 1 + statuses["diagnostics_native"] += len(outcome[0]) return outcome monkeypatch.setattr(native_module, "plan_semantic_type_recovery", counted_plan) @@ -344,15 +338,59 @@ def counted_complete(*arguments: Any) -> Any: return statuses -def deferral_records(record_dir: Path) -> tuple[tuple[str, str], ...]: - """Every `(kind, site)` deferral the native stage recorded below `record_dir`.""" +def non_ascii_variant(*, files: dict[str, str], rng: random.Random) -> dict[str, str]: + """The project with some column names spelt beyond ASCII and a comment after each model + header holding non-ASCII text, digits and Python-only line separators.""" + + renamed: list[tuple[str, str]] = rng.sample(_NON_ASCII_NAMES, k=rng.randint(1, 6)) + return { + path: _non_ascii_text(path=path, text=text, renamed=renamed, rng=rng) + for path, text in files.items() + } + + +def files_with_non_ascii( + *, files: dict[str, str], rng: random.Random, non_ascii: bool +) -> dict[str, str]: + """`files`, or with `non_ascii` their `non_ascii_variant`.""" + + variants: tuple[Callable[[], dict[str, str]], ...] = ( + lambda: files, + lambda: non_ascii_variant(files=files, rng=rng), + ) + return variants[non_ascii]() + + +def _non_ascii_text( + *, path: str, text: str, renamed: list[tuple[str, str]], rng: random.Random +) -> str: + renamed_text: str = functools.reduce( + lambda current, names: re.sub(rf"\b{names[0]}\b", names[1], current), renamed, text + ) + commented: bool = path.endswith(".sql") and ";" in renamed_text + comments: tuple[Callable[[], str], ...] = ( + lambda: "", + lambda: rng.choice(_NON_ASCII_COMMENTS), + ) + comment: str = comments[commented]() + header_end: int = renamed_text.find(";") + 1 + return renamed_text[:header_end] + comment + renamed_text[header_end:] + + +def semantic_outcome(complete: Callable[[], object]) -> tuple[str, object]: + """`("completed", result)`, or the type and message of the error the stage raised.""" + + try: + return ("completed", complete()) + except Exception as error: # noqa: BLE001 - the error is the outcome under comparison + return (type(error).__name__, str(error)) - records: list[tuple[str, str]] = [] - for path in sorted(record_dir.glob("analysis-deferrals-*.jsonl")): - for line in path.read_text("utf-8").splitlines(): - record: dict[str, str] = json.loads(line) - records.append((record["kind"], record["site"])) - return tuple(records) + +def outcome_label(outcome: tuple[str, object]) -> str: + """`completed`, or the error as `Type: message`.""" + + kind, value = outcome + return {"completed": kind}.get(kind, f"{kind}: {value}") _SOURCE_COLUMNS: tuple[str, ...] = ( @@ -506,22 +544,8 @@ def generated_metadata_files(*, rng: random.Random, model_count: int) -> dict[st return files -def python_metadata( - *, inputs: SemanticInputs, monkeypatch: pytest.MonkeyPatch -) -> tuple[CompilerDiagnostic, ...]: - """The Python engine's metadata diagnostics.""" - - with monkeypatch.context() as patch: - patch.setenv(COMPILER_ENGINE_ENV_VAR, "python") - return get_semantic_metadata_diagnostics( - project=inputs.project, - profile=inputs.profile, - resource_sql_analysis=inputs.resource_sql_analysis, - ) - - -def native_metadata(inputs: SemanticInputs) -> tuple[CompilerDiagnostic, ...] | None: - """The native stage's metadata diagnostics, or None when it defers.""" +def native_metadata(inputs: SemanticInputs) -> tuple[CompilerDiagnostic, ...]: + """The native stage's metadata diagnostics.""" catalog: Any = cast(Any, inputs.project.binding_catalog) return native_metadata_diagnostics( @@ -534,23 +558,23 @@ def native_metadata(inputs: SemanticInputs) -> tuple[CompilerDiagnostic, ...] | def _family_counts(outcome: Any) -> Counter[str]: counts: Counter[str] = Counter() - for function_rows, reference_rows in outcome[1]: + for function_rows, reference_rows in outcome[0]: counts.update(f"function {row[0]}" for row in function_rows) counts.update(f"reference {row[0]}" for row in reference_rows) - counts.update(f"source {row[0]}" for _, row in outcome[2]) - counts.update(f"sql_test {row[0]}" for _, row, _ in outcome[3]) + counts.update(f"source {row[0]}" for _, row in outcome[1]) + counts.update(f"sql_test {row[0]}" for _, row, _ in outcome[2]) return counts def record_metadata_families(*, monkeypatch: pytest.MonkeyPatch) -> Counter[str]: - """Count native metadata runs, deferrals and errors by family and code.""" + """Count native metadata runs and errors by family and code.""" counts: Counter[str] = Counter() check: Callable[..., Any] = native_module.check_semantic_metadata_rows def counted(*arguments: Any) -> Any: outcome: Any = check(*arguments) - counts[("native", "deferred")[outcome[0] is not None]] += 1 + counts["native"] += 1 counts.update(_family_counts(outcome)) return outcome diff --git a/tests/integration/src/sqlbuild/compiler/semantic_checks/test_native_metadata_checks.py b/tests/integration/src/sqlbuild/compiler/semantic_checks/test_native_metadata_checks.py index 144c7b8c8e..cd3675054c 100644 --- a/tests/integration/src/sqlbuild/compiler/semantic_checks/test_native_metadata_checks.py +++ b/tests/integration/src/sqlbuild/compiler/semantic_checks/test_native_metadata_checks.py @@ -1,24 +1,32 @@ -"""Native semantic metadata checks equal Python's on generated projects, family by family.""" +"""Native semantic metadata checks match the outputs recorded from Python's checks.""" from __future__ import annotations import random from collections import Counter +from functools import partial from pathlib import Path import pytest -from sqlbuild.compiler.compile.models import CompilerDiagnostic +from tests.integration.src.sqlbuild.compiler.helpers import ( + GoldenEntry, + golden_differences, + golden_entry, + golden_name, + read_golden, +) from tests.integration.src.sqlbuild.compiler.semantic_checks._test_types import ( GeneratedMetadataParityTestCase, ) from tests.integration.src.sqlbuild.compiler.semantic_checks.helpers import ( SemanticInputs, captured_semantic_inputs, + files_with_non_ascii, generated_metadata_files, native_metadata, - python_metadata, record_metadata_families, + semantic_outcome, with_dialect, ) @@ -32,6 +40,8 @@ count=8, model_count=10, dialects=("duckdb", "postgres", "snowflake", "bigquery"), + non_ascii=False, + golden_prefix="metadata_generated", expected_minimum_native=32, expected_minimum_families={ "function B102": 100, @@ -41,32 +51,54 @@ "source B300": 4, "sql_test B302": 16, }, - ) + ), + GeneratedMetadataParityTestCase( + description="non-ASCII names and comments, new and unknown dialects", + seed=20261017, + count=4, + model_count=10, + dialects=("duckdb", "mysql", "tsql", None, "nonsense"), + non_ascii=True, + golden_prefix="metadata_formerly_deferred", + expected_minimum_native=12, + expected_minimum_families={"function B301": 10, "reference B300": 4}, + ), ], ids=lambda case: case.description, ) -def test_given_generated_projects_when_checking_metadata_natively_then_matches_python( +def test_given_generated_projects_when_checking_metadata_natively_then_matches_recorded_python( test_case: GeneratedMetadataParityTestCase, tmp_path: Path, monkeypatch: pytest.MonkeyPatch, ) -> None: rng: random.Random = random.Random(test_case.seed) families: Counter[str] = record_metadata_families(monkeypatch=monkeypatch) - expected: list[tuple[CompilerDiagnostic, ...] | None] = [] - actual: list[tuple[CompilerDiagnostic, ...] | None] = [] + golden: list[GoldenEntry] = [] for index in range(test_case.count): + project_dir: Path = tmp_path / f"project_{index}" captured: SemanticInputs = captured_semantic_inputs( - project_dir=tmp_path / f"project_{index}", - files=generated_metadata_files(rng=rng, model_count=test_case.model_count), + project_dir=project_dir, + files=files_with_non_ascii( + files=generated_metadata_files(rng=rng, model_count=test_case.model_count), + rng=rng, + non_ascii=test_case.non_ascii, + ), monkeypatch=monkeypatch, ) - for dialect in test_case.dialects: - inputs: SemanticInputs = with_dialect(captured, dialect) - expected.append(python_metadata(inputs=inputs, monkeypatch=monkeypatch)) - actual.append(native_metadata(inputs)) + views: dict[str, object] = { + str(dialect): semantic_outcome( + partial(native_metadata, with_dialect(captured, dialect)) + ) + for dialect in test_case.dialects + } + golden.append(golden_entry("metadata", views, masked=(str(project_dir),))) - assert actual == expected - assert families["deferred"] == 0 + assert ( + golden_differences( + read_golden(golden_name(test_case.golden_prefix, test_case.description)), golden + ) + == [] + ) assert families["native"] >= test_case.expected_minimum_native assert { family: min(families[family], minimum) diff --git a/tests/integration/src/sqlbuild/compiler/semantic_checks/test_native_semantic_checks.py b/tests/integration/src/sqlbuild/compiler/semantic_checks/test_native_semantic_checks.py index 6fce08d692..41e10deb77 100644 --- a/tests/integration/src/sqlbuild/compiler/semantic_checks/test_native_semantic_checks.py +++ b/tests/integration/src/sqlbuild/compiler/semantic_checks/test_native_semantic_checks.py @@ -1,4 +1,4 @@ -"""Native semantic completion equals Python's on generated failing projects.""" +"""Native semantic completion matches the outputs recorded from Python's completion.""" from __future__ import annotations @@ -9,11 +9,19 @@ import pytest +import sqlbuild._native as native_module from sqlbuild.compiler.compile.models import CompiledProject -from sqlbuild.compiler.sql_analysis.constants import ANALYSIS_RECORD_DIR_ENV_VAR +from tests.integration.src.sqlbuild.compiler.helpers import ( + GoldenEntry, + golden_differences, + golden_entry, + golden_name, + read_golden, +) from tests.integration.src.sqlbuild.compiler.semantic_checks._test_types import ( - DeferredSemanticTestCase, + FormerlyDeferredSemanticTestCase, GeneratedSemanticParityTestCase, + MissingCatalogTestCase, SessionCompletionTestCase, ) from tests.integration.src.sqlbuild.compiler.semantic_checks.helpers import ( @@ -21,14 +29,15 @@ captured_semantic_inputs, completed_natively, completion_view, - deferral_records, + files_with_non_ascii, generated_semantic_files, native_completion, note_kinds, + outcome_label, proven_output_count, - python_completion, record_native_statuses, record_session_models, + semantic_outcome, session_corpus_files, with_dialect, without_session, @@ -62,7 +71,7 @@ ], ids=lambda case: case.description, ) -def test_given_generated_failing_projects_when_completing_natively_then_matches_python( +def test_given_generated_failing_projects_when_completing_natively_then_matches_recorded_python( test_case: GeneratedSemanticParityTestCase, tmp_path: Path, monkeypatch: pytest.MonkeyPatch, @@ -70,30 +79,33 @@ def test_given_generated_failing_projects_when_completing_natively_then_matches_ rng: random.Random = random.Random(test_case.seed) statuses: Counter[str] = record_native_statuses(monkeypatch=monkeypatch) codes: Counter[str] = Counter() - expected_views: list[tuple[object, ...]] = [] - native_views: list[tuple[object, ...]] = [] + golden: list[GoldenEntry] = [] for index in range(test_case.count): + project_dir: Path = tmp_path / f"project_{index}" captured: SemanticInputs = captured_semantic_inputs( - project_dir=tmp_path / f"project_{index}", + project_dir=project_dir, files=generated_semantic_files( rng=rng, model_count=test_case.model_count, require_analysis=index % 2 == 0 ), monkeypatch=monkeypatch, ) + views: dict[str, object] = {} for dialect in test_case.dialects: - inputs: SemanticInputs = with_dialect(captured, dialect) - python: CompiledProject = python_completion(inputs=inputs, monkeypatch=monkeypatch) - codes.update(item.code for item in python.diagnostics) - codes.update(note_kinds(python, _NOTE_KINDS)) - expected_views.append(completion_view(python)) - native_views.append(completion_view(completed_natively(inputs))) - - assert native_views == expected_views - assert statuses["completion_deferred"] == 0 - assert statuses["type_recovery_deferred"] == 0 + native: CompiledProject = completed_natively(with_dialect(captured, dialect)) + codes.update(item.code for item in native.diagnostics) + codes.update(note_kinds(native, _NOTE_KINDS)) + views[dialect] = completion_view(native) + golden.append(golden_entry("completion", views, masked=(str(project_dir),))) + + assert ( + golden_differences( + read_golden(golden_name("semantic_generated", test_case.description)), golden + ) + == [] + ) + assert statuses["type_recovery_planned"] >= test_case.expected_minimum_type_recovery_plans assert statuses["completion_native"] >= test_case.expected_minimum_native_completions assert statuses["diagnostics_native"] >= test_case.expected_minimum_native_diagnostics - assert statuses["type_recovery_planned"] >= test_case.expected_minimum_type_recovery_plans assert { code: min(codes[code], minimum) for code, minimum in test_case.expected_minimum_codes.items() @@ -103,60 +115,105 @@ def test_given_generated_failing_projects_when_completing_natively_then_matches_ @pytest.mark.parametrize( "test_case", [ - DeferredSemanticTestCase( - description="a dialect outside the native parser build", - dialect="mysql", - keeps_catalog=True, - non_ascii_comment=False, - expected_kinds=(("unsupported_dialect", "type_recovery.py"),), + FormerlyDeferredSemanticTestCase( + description="non-ASCII names, comments and line separators", + seed=20261014, + count=4, + non_ascii=True, + dialects=("duckdb", "postgres", "snowflake", "bigquery"), + expected_outcomes=frozenset({"completed"}), ), - DeferredSemanticTestCase( - description="non-ASCII authored SQL in an explained model", - dialect="duckdb", - keeps_catalog=True, - non_ascii_comment=True, - expected_kinds=(("non_ascii_text", "recovery.py"),), + FormerlyDeferredSemanticTestCase( + description="dialects added to the native parser build", + seed=20261015, + count=2, + non_ascii=False, + dialects=("mysql", "tsql", "databricks", "sqlite", "oracle", "trino"), + expected_outcomes=frozenset({"completed"}), ), - DeferredSemanticTestCase( - description="a project without an analysis catalog to run on", - dialect="duckdb", - keeps_catalog=False, - non_ascii_comment=False, - expected_kinds=(("no_analysis_catalog", "recovery.py"),), + FormerlyDeferredSemanticTestCase( + description="no dialect and an unknown dialect raise the wheel's errors", + seed=20261016, + count=2, + non_ascii=True, + dialects=(None, "nonsense"), + expected_outcomes=frozenset( + { + "TypeError: argument 'dialect': 'None' is not an instance of 'str'", + "ValueError: Unknown dialect: nonsense", + } + ), ), ], ids=lambda case: case.description, ) -def test_given_deferred_projects_when_completing_then_python_completes_and_records( - test_case: DeferredSemanticTestCase, +def test_given_formerly_deferred_projects_when_completing_natively_then_matches_recorded_python( + test_case: FormerlyDeferredSemanticTestCase, + tmp_path: Path, + monkeypatch: pytest.MonkeyPatch, +) -> None: + rng: random.Random = random.Random(test_case.seed) + golden: list[GoldenEntry] = [] + outcomes: set[str] = set() + for index in range(test_case.count): + project_dir: Path = tmp_path / f"project_{index}" + files: dict[str, str] = generated_semantic_files( + rng=rng, model_count=12, require_analysis=index % 2 == 0 + ) + captured: SemanticInputs = captured_semantic_inputs( + project_dir=project_dir, + files=files_with_non_ascii(files=files, rng=rng, non_ascii=test_case.non_ascii), + monkeypatch=monkeypatch, + ) + views: dict[str, object] = {} + for dialect in test_case.dialects: + inputs: SemanticInputs = with_dialect(captured, dialect) + outcome: tuple[str, object] = semantic_outcome( + lambda inputs=inputs: completion_view(completed_natively(inputs)) + ) + outcomes.add(outcome_label(outcome)) + views[str(dialect)] = outcome + golden.append(golden_entry("completion", views, masked=(str(project_dir),))) + + assert ( + golden_differences( + read_golden(golden_name("semantic_formerly_deferred", test_case.description)), golden + ) + == [] + ) + assert outcomes == test_case.expected_outcomes + + +@pytest.mark.parametrize( + "test_case", + [ + MissingCatalogTestCase( + description="a project without an analysis catalog is an internal failure", + expected_message=( + "NativeCompilerError: native semantic completion: " + "the project has no analysis catalog" + ), + ), + ], + ids=lambda case: case.description, +) +def test_given_project_without_catalog_when_completing_then_raises_native_compiler_error( + test_case: MissingCatalogTestCase, tmp_path: Path, monkeypatch: pytest.MonkeyPatch, ) -> None: - record_dir: Path = tmp_path / "records" captured: SemanticInputs = captured_semantic_inputs( project_dir=tmp_path / "project", files=generated_semantic_files(rng=random.Random(5), model_count=8, require_analysis=False), monkeypatch=monkeypatch, ) - inputs: SemanticInputs = with_dialect(captured, test_case.dialect) - project: CompiledProject = replace( - inputs.project, - binding_catalog=(None, inputs.project.binding_catalog)[test_case.keeps_catalog], - models=tuple( - replace( - model, - authored_sql=model.authored_sql - + ("", "-- caf\u00e9\n")[test_case.non_ascii_comment], - ) - for model in inputs.project.models - ), - ) - monkeypatch.setenv(ANALYSIS_RECORD_DIR_ENV_VAR, str(record_dir)) - native: CompiledProject | None = native_completion(replace(inputs, project=project)) + with pytest.raises(native_module.NativeCompilerError) as raised: + _ = native_completion( + replace(captured, project=replace(captured.project, binding_catalog=None)) + ) - assert native is None - assert deferral_records(record_dir) == test_case.expected_kinds + assert str(raised.value) == test_case.expected_message @pytest.mark.parametrize( @@ -206,22 +263,31 @@ def test_given_preview_compiles_when_completing_from_the_session_then_matches_pa ] selections: list[frozenset[str]] = record_session_models(monkeypatch=monkeypatch) codes: Counter[str] = Counter() - python_views: list[tuple[object, ...]] = [] + golden: list[GoldenEntry] = [] payload_views: list[tuple[object, ...]] = [] session_views: list[tuple[object, ...]] = [] - for inputs in captured: - python: CompiledProject = python_completion(inputs=inputs, monkeypatch=monkeypatch) - codes.update(item.code for item in python.diagnostics) - codes.update(note_kinds(python, _NOTE_KINDS)) - python_views.append(completion_view(python)) + for index, inputs in enumerate(captured): + completed: CompiledProject = completed_natively(inputs) + codes.update(item.code for item in completed.diagnostics) + codes.update(note_kinds(completed, _NOTE_KINDS)) + session_views.append(completion_view(completed)) payload_views.append(completion_view(completed_natively(without_session(inputs)))) - session_views.append(completion_view(completed_natively(inputs))) + golden.append( + golden_entry( + "completion", session_views[-1], masked=(str(tmp_path / f"project_{index}"),) + ) + ) session_models: int = sum(len(selected) for selected in selections) model_count: int = sum(len(inputs.project.models) for inputs in captured) assert all(inputs.native_session is not None for inputs in captured) - assert session_views == python_views - assert payload_views == python_views + assert ( + golden_differences( + read_golden(golden_name("semantic_session", test_case.description)), golden + ) + == [] + ) + assert payload_views == session_views assert ( session_models, model_count - session_models, diff --git a/tests/integration/src/sqlbuild/compiler/sql_analysis/_test_types.py b/tests/integration/src/sqlbuild/compiler/sql_analysis/_test_types.py index 5af0584a8f..53de15e7e9 100644 --- a/tests/integration/src/sqlbuild/compiler/sql_analysis/_test_types.py +++ b/tests/integration/src/sqlbuild/compiler/sql_analysis/_test_types.py @@ -13,3 +13,12 @@ class SiteRecorderTestCase: record_dir: str expected_rows: tuple[tuple[str, str, int], ...] expected_entry_point: str + + +@dataclass(frozen=True) +class RelationNamesTestCase: + """SQL texts whose hard-coded relation names Python's walk recorded in a golden.""" + + description: str + queries: tuple[tuple[str, str | None], ...] + expected_differences: list[tuple[int, str, object, object]] diff --git a/tests/integration/src/sqlbuild/compiler/sql_analysis/helpers.py b/tests/integration/src/sqlbuild/compiler/sql_analysis/helpers.py index 6f91e00bbe..5aee5106b2 100644 --- a/tests/integration/src/sqlbuild/compiler/sql_analysis/helpers.py +++ b/tests/integration/src/sqlbuild/compiler/sql_analysis/helpers.py @@ -4,8 +4,12 @@ import json from pathlib import Path +from typing import cast +from sqlbuild.compiler.references.main.extract_relation_names import extract_relation_names +from sqlbuild.compiler.references.models import RelationName from sqlbuild.compiler.sql_analysis.constants import POLYGLOT_SITE_RECORD_PREFIX +from tests.integration.src.sqlbuild.compiler.compile.helpers import ExpansionFailureCapture def recorded_rows(root: Path) -> tuple[tuple[str, str, int], ...]: @@ -16,3 +20,37 @@ def recorded_rows(root: Path) -> tuple[tuple[str, str, int], ...]: for site, api, count in json.loads(path.read_text(encoding="utf-8"))["calls"]: rows.append((str(site), str(api), int(count))) return tuple(rows) + + +def relation_names_outcome(sql: str, dialect: str | None) -> object: + """The extracted `(relations, sorted temporary names)`, None if unparseable, or the error.""" + + capture: ExpansionFailureCapture = ExpansionFailureCapture() + extracted: list[tuple[tuple[RelationName, ...], frozenset[str]] | None] = [None] + with capture: + extracted[0] = extract_relation_names(sql=sql, dialect=dialect) + return { + True: lambda: _relation_view(extracted[0]), + False: lambda: (type(capture.failure).__name__, str(capture.failure)), + }[capture.failure is None]() + + +def _relation_view( + extracted: tuple[tuple[RelationName, ...], frozenset[str]] | None, +) -> object: + return { + True: lambda: None, + False: lambda: _present_relation_view( + cast(tuple[tuple[RelationName, ...], frozenset[str]], extracted) + ), + }[extracted is None]() + + +def _present_relation_view( + extracted: tuple[tuple[RelationName, ...], frozenset[str]], +) -> tuple[tuple[tuple[str, str | None, str | None], ...], tuple[str, ...]]: + relations, temporary = extracted + return ( + tuple((relation.name, relation.schema, relation.database) for relation in relations), + tuple(sorted(temporary)), + ) diff --git a/tests/integration/src/sqlbuild/compiler/sql_analysis/test_native_relation_names.py b/tests/integration/src/sqlbuild/compiler/sql_analysis/test_native_relation_names.py new file mode 100644 index 0000000000..d863a5f9c2 --- /dev/null +++ b/tests/integration/src/sqlbuild/compiler/sql_analysis/test_native_relation_names.py @@ -0,0 +1,87 @@ +"""Hard-coded relation names come from the native parse and match Python's dict walk.""" + +from __future__ import annotations + +import pytest + +from tests.integration.src.sqlbuild.compiler.helpers import ( + GoldenEntry, + golden_differences, + golden_entry, + golden_name, + read_golden, +) +from tests.integration.src.sqlbuild.compiler.sql_analysis._test_types import ( + RelationNamesTestCase, +) +from tests.integration.src.sqlbuild.compiler.sql_analysis.helpers import relation_names_outcome + + +@pytest.mark.parametrize( + "test_case", + [ + RelationNamesTestCase( + description="hard coded relation edges", + queries=( + ("SELECT * FROM orders", None), + ( + "SELECT * FROM analytics.orders o JOIN db.sales.customers c ON o.id = c.id", + "duckdb", + ), + ( + "WITH Recent AS (SELECT * FROM orders) SELECT * FROM recent JOIN RECENT r2 ON 1=1", + "duckdb", + ), + ("WITH recent AS (SELECT 1) SELECT * FROM s.recent", "duckdb"), + ( + "CREATE TEMPORARY TABLE Staging AS SELECT * FROM raw.events; INSERT INTO staging SELECT * FROM raw.events", + "duckdb", + ), + ("CREATE TEMP TABLE t1 (id INT); SELECT * FROM T1", "postgres"), + ("SELECT * FROM `proj.dataset.table` JOIN `a.b` USING (id)", "bigquery"), + ('SELECT * FROM "Weird.Name"', "duckdb"), + ("SELECT * FROM a.b.c.d", "duckdb"), + ("SELECT (", "duckdb"), + ("", "duckdb"), + ("SELECT 1; SELECT * FROM x; SELECT * FROM x", ""), + ("UPDATE inventory SET qty = 0 WHERE id IN (SELECT id FROM products)", "snowflake"), + ( + "DELETE FROM sales.orders USING customers WHERE orders.cid = customers.id", + "postgres", + ), + ( + "MERGE INTO tgt USING src ON tgt.id = src.id WHEN MATCHED THEN UPDATE SET v = src.v", + "snowflake", + ), + ("SELECT * FROM [dbo].[Orders]", "sqlserver"), + ("SELECT * FROM Größe, ÉTÉ", "duckdb"), + ("WITH ÉTÉ AS (SELECT 1) SELECT * FROM été", "duckdb"), + ("CREATE TABLE perm AS SELECT 1", "duckdb"), + ("SELECT * FROM orders", "motherduck"), + ("SELECT * FROM read_csv('x.csv'), generate_series(1, 3)", "duckdb"), + ( + "SELECT * FROM t1 WHERE EXISTS (SELECT 1 FROM t2 WHERE t2.id = t1.id) UNION SELECT * FROM t3", + "databricks", + ), + ), + expected_differences=[], + ), + ], + ids=lambda case: case.description, +) +def test_given_python_node_sql_when_extracting_relation_names_then_matches_python_golden( + test_case: RelationNamesTestCase, +) -> None: + outcomes: list[object] = [ + relation_names_outcome(sql, dialect) for sql, dialect in test_case.queries + ] + expected: list[GoldenEntry] = read_golden(golden_name("relation_names", test_case.description)) + + assert ( + golden_differences(expected, [golden_entry("relation_names", item) for item in outcomes]) + == test_case.expected_differences + ) + + +if __name__ == "__main__": + pytest.main([__file__, "-vv"]) diff --git a/tests/integration/src/sqlbuild/compiler/sql_analysis/test_polyglot_site_recorder.py b/tests/integration/src/sqlbuild/compiler/sql_analysis/test_polyglot_site_recorder.py index de009bcc7f..8f926f2bea 100644 --- a/tests/integration/src/sqlbuild/compiler/sql_analysis/test_polyglot_site_recorder.py +++ b/tests/integration/src/sqlbuild/compiler/sql_analysis/test_polyglot_site_recorder.py @@ -14,15 +14,14 @@ from tests.integration.src.sqlbuild.compiler.sql_analysis.helpers import recorded_rows _PROCESS: str = ( - "from sqlbuild.compiler.references.main.extract_relation_names import " - "extract_relation_names\n" + "from sqlbuild.rule_engine.classes.sql_document import SqlDocument\n" "from sqlbuild.compiler.sql_analysis.main.import_polyglot_sql import import_polyglot_sql\n" "for _ in range(2):\n" - " assert extract_relation_names(sql='SELECT 1 FROM main.orders', dialect='duckdb')\n" + " assert SqlDocument(source='SELECT 1 FROM main.orders', dialect='duckdb').polyglot_ast()\n" "module = import_polyglot_sql()\n" "print(type(module.parse_one).__name__, isinstance(module.PolyglotError, type))\n" ) -_SITE: str = "compiler/references/_helpers/relation_names.py:extract_relation_names_impl" +_SITE: str = "rule_engine/classes/sql_document.py:SqlDocument.polyglot_ast" @pytest.mark.parametrize( @@ -31,7 +30,7 @@ SiteRecorderTestCase( description="recording", record_dir="records", - expected_rows=((_SITE, "parse", 2),), + expected_rows=((_SITE, "parse_one", 2),), expected_entry_point="_RecordedEntryPoint", ), SiteRecorderTestCase( diff --git a/tests/integration/src/sqlbuild/compiler/sql_test_glue/_test_types.py b/tests/integration/src/sqlbuild/compiler/sql_test_glue/_test_types.py index f4abf5a7a3..f7f45a42ef 100644 --- a/tests/integration/src/sqlbuild/compiler/sql_test_glue/_test_types.py +++ b/tests/integration/src/sqlbuild/compiler/sql_test_glue/_test_types.py @@ -6,31 +6,31 @@ @dataclass(frozen=True) -class GeneratedSqlTestPlanningParityTestCase: - """Seeded SQL-test projects the native planning glue and the JSON request must agree on.""" +class GeneratedSqlTestAssemblyParityTestCase: + """Seeded SQL-test projects native assembly must compile as Python's recorded assembly did.""" description: str seed: int count: int test_count: int shape: SqlTestCorpusShape - adapter_names: tuple[str, ...] - expected_minimum_native_planned: int - expected_minimum_native_with_errors: int - expected_minimum_native_chains: int - expected_minimum_native_raised: int - expected_native_raised_kinds: frozenset[str] - expected_minimum_answered_batches: int - expected_minimum_raised_outcomes: int + expected_native_assemblies: dict[str, int] @dataclass(frozen=True) -class GeneratedSqlTestAssemblyParityTestCase: - """Seeded SQL-test projects native and Python assembly must compile identically.""" +class EdgeSqlTestAssemblyTestCase: + """One project whose SQL test Python's assembly once answered alone, and its outcome kind.""" description: str - seed: int - count: int - test_count: int - shape: SqlTestCorpusShape - expected_native_assemblies: dict[str, int] + files: dict[str, str] + expected_outcome: str + + +@dataclass(frozen=True) +class HelperReadsTestCase: + """CTE bodies whose helper-key reads Python's `_parsed_reads` recorded in a golden.""" + + description: str + keys: frozenset[str] + bodies: tuple[str, ...] + expected_differences: list[tuple[int, str, object, object]] diff --git a/tests/integration/src/sqlbuild/compiler/sql_test_glue/helpers.py b/tests/integration/src/sqlbuild/compiler/sql_test_glue/helpers.py index 8cc9dbc032..21f55641e9 100644 --- a/tests/integration/src/sqlbuild/compiler/sql_test_glue/helpers.py +++ b/tests/integration/src/sqlbuild/compiler/sql_test_glue/helpers.py @@ -5,7 +5,7 @@ import random from collections import Counter from collections.abc import Callable -from dataclasses import dataclass, replace +from dataclasses import dataclass from itertools import chain, compress from pathlib import Path from typing import cast @@ -13,31 +13,23 @@ import pytest import sqlbuild._native as native_module -from sqlbuild.adapter.contract.classes.base_adapter import BaseAdapter from sqlbuild.adapters.duckdb.classes.duckdb_adapter import DuckDbAdapter from sqlbuild.compiler.compile._helpers.native_stages import sql_tests as sql_test_stage from sqlbuild.compiler.compile.models import ( - CompiledModelSqlTestPayload, CompiledProject, CompiledSqlTest, CompileProjectInputs, - CompileSqlTestCte, ) from sqlbuild.compiler.discovery.main.discover import discover_project_inputs -from sqlbuild.compiler.frontier.types import NativeStage from sqlbuild.compiler.pipeline.main.graph import build_project_graph -from sqlbuild.compiler.planner._helpers.sql_tests import native_planning -from sqlbuild.compiler.planner.models import NativeSqlTestArtifact from sqlbuild.compiler.sql_test_glue.models import ( NativeSqlTestAssembly, NativeSqlTestAssemblyRequest, - NativeSqlTestChainRequest, - NativeSqlTestPlanningRequest, ) from sqlbuild.compiler.sql_test_glue.types import ( NativeSqlTestAssemblyRow, - NativeSqlTestPlanRow, ) +from tests.integration.src.sqlbuild.compiler.helpers import GoldenEntry, golden_entry @dataclass(frozen=True) @@ -185,12 +177,7 @@ class SqlTestCorpusShape: _MOCK_SHARE: float = 0.85 _MACRO_MOCK_SHARE: float = 0.5 _HELPER_SHARE: float = 0.4 -_UNMOCKED_ASSERTION: CompileSqlTestCte = CompileSqlTestCte( - name="__assert__no_returns", sql_body='SELECT order_id FROM __source("raw_returns") WHERE 1 = 0' -) _REGIONS_ASSERTION: str = 'SELECT * FROM __ref("fct_regions") WHERE 1 = 0' -_NATIVE_ERROR_KIND_SEPARATOR: str = ":" -_NATIVE_RAISED_PREFIX: str = "native_raised:" NO_WINDOW: str = "" VALID_WINDOW: str = ', cursor_start "2026-02-01", cursor_end "2026-02-03"' INVERTED_WINDOW: str = ', cursor_start "2026-02-03", cursor_end "2026-02-01"' @@ -201,6 +188,24 @@ def generated_sql_test_files( ) -> dict[str, str]: """A project of mocked, expected, asserted, helper, direct and failing SQL tests.""" + files: dict[str, str] = _project_files() + files.update( + (f"tests/unit/test_generated_{index}.sql", _model_test(rng=rng, index=index, shape=shape)) + for index in range(test_count) + ) + files.update( + compress( + ( + (f"tests/unit/test_direct_{index}.sql", sql) + for index, sql in enumerate(_DIRECT_TESTS) + ), + [rng.random() < _DIRECT_TEST_SHARE for _ in _DIRECT_TESTS], + ) + ) + return files + + +def _project_files() -> dict[str, str]: files: dict[str, str] = { "sqlbuild_project.toml": _PROJECT_TOML, "sources/raw.yml": _SOURCES, @@ -215,22 +220,66 @@ def generated_sql_test_files( (f"models/{name}.sql", f'MODEL (description "Model {name}.");\n\n{sql}\n') for name, sql in _BASE_MODELS.items() ) - files.update( - (f"tests/unit/test_generated_{index}.sql", _model_test(rng=rng, index=index, shape=shape)) - for index in range(test_count) - ) - files.update( - compress( - ( - (f"tests/unit/test_direct_{index}.sql", sql) - for index, sql in enumerate(_DIRECT_TESTS) - ), - [rng.random() < _DIRECT_TEST_SHARE for _ in _DIRECT_TESTS], - ) - ) return files +def edge_sql_test_files(*, extra_files: dict[str, str]) -> dict[str, str]: + """The planning project's models, sources and functions plus `extra_files`.""" + + return {**_project_files(), **extra_files} + + +_DEEP_SUBQUERIES: int = 100 +EDGE_UNICODE_CONTENTS: str = ( + 'TEST (name "unicode_contents");\n\nWITH\n' + "-- r\u00e9sum\u00e9: \u212aelvin_rows AS (a comment, not the header)\n" + "kelvin_rows AS (\n" + " SELECT order_id, amount, 'caf\u00e9 \u2603' AS note " + 'FROM __source("raw_orders")\n),\n' + "via_rows AS (SELECT *, '\u017f' AS long_s FROM kelvin_rows),\n" + "__source__raw_orders AS (SELECT * FROM via_rows),\n" + "__expected__stg_orders AS (SELECT order_id FROM KELVIN_ROWS)\nSELECT 1\n" +) +EDGE_DEEP_HELPER: str = ( + 'TEST (name "deep_helper");\n\nWITH\n' + "deep_rows AS (SELECT * FROM " + + "(SELECT * FROM " * _DEEP_SUBQUERIES + + "(WITH shadow AS (SELECT 1 AS order_id) SELECT * FROM shadow) AS s" + + ") AS d" * _DEEP_SUBQUERIES + + "),\n" + 'shadow AS (SELECT order_id, amount FROM __source("raw_orders")),\n' + "__source__raw_orders AS (SELECT * FROM deep_rows),\n" + "__expected__stg_orders AS (SELECT 1 AS order_id)\nSELECT 1\n" +) +EDGE_DECIMAL_CONTEXT: str = ( + 'TEST (name "decimal_context", parameters (p_decimal (type decimal, nullable true)), ' + 'cases (rounded (p_decimal "1.23456789012345678901234567895"), ' + 'carried (p_decimal "9.99999999999999999999999999995E+999998"), ' + 'subnormal (p_decimal "123456E-1000030"), ' + 'flushed (p_decimal "-6E-1000028"), ' + 'half_even (p_decimal "5E-1000027")));\n\n' + 'WITH\n__source__raw_orders AS (SELECT 1 AS order_id, @param("p_decimal") AS p),\n' + '__assert__stg_orders_rows AS (SELECT * FROM __ref("stg_orders") WHERE 1 = 0)\nSELECT 1\n' +) +EDGE_DECIMAL_OVERFLOW: str = EDGE_DECIMAL_CONTEXT.replace( + '"5E-1000027"', '"9.99999999999999999999999999995E+999999"' +) +EDGE_UNICODE_MACRO_SCOPE: dict[str, str] = { + "models/weird_amounts.sql": ( + 'MODEL (description "Model weird_amounts.");\n\n' + 'WITH o AS (SELECT amount FROM __source("raw_orders"))\nSELECT amount@\u00f6re FROM o\n' + ), + "tests/unit/test_direct_macro.sql": _DIRECT_TESTS[0], +} +EDGE_INVALID_UNREAD_HELPER: str = ( + 'TEST (name "invalid_unread_helper");\n\nWITH\n' + "bad_rows AS (SELECT * FROM __ref(1)),\n" + 'source_rows AS (SELECT order_id FROM __source("raw_orders")),\n' + "__source__raw_orders AS (SELECT * FROM source_rows),\n" + "__expected__stg_orders AS (SELECT 1 AS order_id)\nSELECT 1\n" +) + + def _model_test(*, rng: random.Random, index: int, shape: SqlTestCorpusShape) -> str: """One model test: the first target's first mock, then random mocks, helper and checks. @@ -402,59 +451,9 @@ def write_project(*, project_dir: Path, files: dict[str, str]) -> None: _ = path.write_text(contents, encoding="utf-8") -def compiled_project(*, project_dir: Path, files: dict[str, str]) -> CompiledProject: - """Write and compile a project, keeping any compile diagnostics on it.""" - - write_project(project_dir=project_dir, files=files) - return build_project_graph( - discovered_inputs=discover_project_inputs(project_dir=project_dir), - adapter=DuckDbAdapter(), - ).project - +def assembly_outcome(*, project_dir: Path) -> PlanningCallOutcome: + """The compiled SQL tests and diagnostics with native assembly, or what it raises.""" -def with_unmocked_assertion(*, project: CompiledProject) -> CompiledSqlTest: - """The first model test with an assertion calling a source nothing mocks. - - The compiler reports such a call itself, so this stands in for a reference it missed and - reaches the planner's own unresolved-reference error. - """ - - test: CompiledSqlTest = next( - filter( - lambda test: isinstance(test.payload, CompiledModelSqlTestPayload), project.sql_tests - ) - ) - payload: CompiledModelSqlTestPayload = cast(CompiledModelSqlTestPayload, test.payload) - return replace( - test, - payload=replace( - payload, - assertion_ctes=(*payload.assertion_ctes, _UNMOCKED_ASSERTION), - authored_ctes=(*payload.authored_ctes, _UNMOCKED_ASSERTION), - ), - ) - - -def use_sql_test_glue(*, monkeypatch: pytest.MonkeyPatch, enabled: bool) -> None: - """Route SQL-test planning through the native glue, or through the JSON request.""" - - monkeypatch.setattr( - native_planning, - "native_stage_enabled", - lambda stage: enabled and stage is NativeStage.SQL_TEST_GLUE, - ) - - -def assembly_outcome( - *, project_dir: Path, monkeypatch: pytest.MonkeyPatch, native: bool -) -> PlanningCallOutcome: - """The compiled SQL tests and diagnostics with native or Python assembly, or what it raises.""" - - monkeypatch.setattr( - sql_test_stage, - "native_stage_enabled", - lambda stage: native and stage is NativeStage.SQL_TEST_GLUE, - ) return _outcome(lambda: _compiled_tests_and_diagnostics(project_dir=project_dir)) @@ -467,94 +466,51 @@ def _compiled_tests_and_diagnostics(*, project_dir: Path) -> tuple[object, objec def record_native_assemblies(*, monkeypatch: pytest.MonkeyPatch) -> Counter[str]: - """Count tests compile takes from the native assembly, with diagnostics, cases, or defers. + """Count tests compile takes from the native assembly, with diagnostics, cases or failures. - `native_assembled` counts only assemblies the stage seam hands compile; a deferred test - counts under `deferred_` and is assembled by Python, so it never counts as native work. + A test whose assembly raises counts under `failed_`. """ answers: Counter[str] = Counter() assemble: Callable[[NativeSqlTestAssemblyRequest], list[NativeSqlTestAssemblyRow]] = ( native_module.assemble_compiled_sql_tests ) - seam: Callable[..., tuple[NativeSqlTestAssembly | None, ...]] = ( + seam: Callable[..., tuple[NativeSqlTestAssembly, ...]] = ( sql_test_stage.assemble_native_sql_tests ) - def counted_deferrals(request: NativeSqlTestAssemblyRequest) -> list[NativeSqlTestAssemblyRow]: + def counted_failures(request: NativeSqlTestAssemblyRequest) -> list[NativeSqlTestAssemblyRow]: rows: list[NativeSqlTestAssemblyRow] = assemble(request) - deferrals: list[str] = list(filter(None, (row[1] for row in rows))) - answers.update(f"deferred_{kind}" for kind in deferrals) + failures: list[tuple[str, str] | None] = [failure for _, failure in rows] + answers.update(f"failed_{failure[0]}" for failure in filter(None, failures)) return rows - def counted_assemblies( - *, inputs: CompileProjectInputs - ) -> tuple[NativeSqlTestAssembly | None, ...]: - assemblies: tuple[NativeSqlTestAssembly | None, ...] = seam(inputs=inputs) - native: list[NativeSqlTestAssembly] = list(filter(None, assemblies)) + def counted_assemblies(*, inputs: CompileProjectInputs) -> tuple[NativeSqlTestAssembly, ...]: + assemblies: tuple[NativeSqlTestAssembly, ...] = seam(inputs=inputs) + tests: list[CompiledSqlTest | None] = [item.test for item in assemblies] + native: list[CompiledSqlTest] = list(filter(None, tests)) answers["native_assembled"] += len(native) - answers["native_with_diagnostics"] += sum(bool(item.diagnostics) for item in native) + answers["native_with_diagnostics"] += sum(bool(item.diagnostics) for item in assemblies) answers["native_case_fingerprints"] += sum( - item.test.case_fingerprint is not None for item in native + test.case_fingerprint is not None for test in native ) return assemblies - monkeypatch.setattr(native_module, "assemble_compiled_sql_tests", counted_deferrals) + monkeypatch.setattr(native_module, "assemble_compiled_sql_tests", counted_failures) monkeypatch.setattr(sql_test_stage, "assemble_native_sql_tests", counted_assemblies) return answers -def planning_outcome( - *, - project: CompiledProject, - tests: tuple[CompiledSqlTest, ...], - adapter: BaseAdapter, - render_sql: bool, -) -> PlanningCallOutcome: - """The plans `plan_sql_tests_natively` returns, or what it raises.""" - - return _outcome( - lambda: native_planning.plan_sql_tests_natively( - project=project, - tests=tests, - adapter=adapter, - sql_analysis_enabled=project.settings.sql_analysis, - render_sql=render_sql, - include_plan=not render_sql, - ) - ) - +def assembly_golden_entry(*, outcome: PlanningCallOutcome, project_dir: Path) -> GoldenEntry: + """One project's compiled SQL tests, diagnostics and raised error as a golden entry.""" -def artifact_outcome( - *, - project: CompiledProject, - tests: tuple[CompiledSqlTest, ...], - adapter: BaseAdapter, - glue: bool, -) -> PlanningCallOutcome: - """Rendered artifacts from the glue or from the JSON request, or what planning raises.""" - - plan: Callable[..., tuple[NativeSqlTestArtifact, ...]] = ( - native_planning.plan_and_render_sql_test_artifacts, - native_planning.plan_compiled_sql_test_artifacts, - )[glue] - return _outcome( - lambda: plan( - project=project, - tests=tests, - adapter=adapter, - sql_analysis_enabled=project.settings.sql_analysis, - ) + tests, diagnostics = cast( + tuple[object, object], (outcome.value, (None, None))[outcome.raised is not None] ) - - -def chain_outcome( - *, project: CompiledProject, tests: tuple[CompiledSqlTest, ...] -) -> PlanningCallOutcome: - """Each test's model chain, or what chain resolution raises.""" - - return _outcome( - lambda: native_planning.resolve_sql_test_model_chains(project=project, tests=tests) + return golden_entry( + "sql_test_assembly", + {"sql_tests": tests, "diagnostics": diagnostics, "raised": outcome.raised}, + masked=(str(project_dir),), ) @@ -565,64 +521,15 @@ def outcome_kind(outcome: object) -> str: return ("answered", "raised")[called.raised is not None] -def record_native_answers(*, monkeypatch: pytest.MonkeyPatch) -> Counter[str]: - """Count the plans, chains and errors the native glue itself returns for the rest of the test. - - A plan with native error messages counts as `native_with_errors`, any other as - `native_planned`; an error a glue binding raises counts as `native_raised` and under - `native_raised:`. JSON-path planning never reaches these bindings, and errors Python - raises before calling them are never counted. - """ - - answers: Counter[str] = Counter() - plan: Callable[[NativeSqlTestPlanningRequest], tuple[list[NativeSqlTestPlanRow], int, int]] = ( - native_module.plan_compiled_sql_tests - ) - resolve: Callable[[NativeSqlTestChainRequest], list[list[str]]] = ( - native_module.resolve_compiled_sql_test_chains - ) - - def counted_plans( - request: NativeSqlTestPlanningRequest, - ) -> tuple[list[NativeSqlTestPlanRow], int, int]: - response: tuple[list[NativeSqlTestPlanRow], int, int] = _counting_raises( - call=lambda: plan(request), answers=answers - ) - answers.update( - ("native_planned", "native_with_errors")[bool(row[5])] for row in response[0] - ) - return response - - def counted_chains(request: NativeSqlTestChainRequest) -> list[list[str]]: - chains: list[list[str]] = _counting_raises(call=lambda: resolve(request), answers=answers) - answers["native_chains"] += len(chains) - return chains - - monkeypatch.setattr(native_module, "plan_compiled_sql_tests", counted_plans) - monkeypatch.setattr(native_module, "resolve_compiled_sql_test_chains", counted_chains) - return answers - - -def native_raised_kinds(*, answers: Counter[str]) -> frozenset[str]: - """The kinds (message prefixes) of the errors the native glue bindings raised.""" - - return frozenset( - kind.removeprefix(_NATIVE_RAISED_PREFIX) - for kind in filter(lambda kind: kind.startswith(_NATIVE_RAISED_PREFIX), answers) - ) - - -def _counting_raises[T](*, call: Callable[[], T], answers: Counter[str]) -> T: - try: - return call() - except ValueError as error: - answers["native_raised"] += 1 - answers[_NATIVE_RAISED_PREFIX + str(error).partition(_NATIVE_ERROR_KIND_SEPARATOR)[0]] += 1 - raise - - def _outcome(call: Callable[[], object]) -> PlanningCallOutcome: try: return PlanningCallOutcome(value=call(), raised=None) except Exception as error: # noqa: BLE001 - both paths must raise the same error return PlanningCallOutcome(value=None, raised=(type(error).__name__, str(error))) + + +def helper_reads_view(sql: str, keys: frozenset[str]) -> tuple[str, ...] | None: + """The native helper reads of `sql` as Python's `_parsed_reads` returned them.""" + + reads: list[str] | None = native_module.sql_test_helper_reads(sql, sorted(keys)) + return {True: lambda: None, False: lambda: tuple(cast(list[str], reads))}[reads is None]() diff --git a/tests/integration/src/sqlbuild/compiler/sql_test_glue/test_native_helper_reads.py b/tests/integration/src/sqlbuild/compiler/sql_test_glue/test_native_helper_reads.py new file mode 100644 index 0000000000..7e12a8a639 --- /dev/null +++ b/tests/integration/src/sqlbuild/compiler/sql_test_glue/test_native_helper_reads.py @@ -0,0 +1,60 @@ +"""SQL-test helper CTE reads come from the native parse and match Python's `_parsed_reads`.""" + +from __future__ import annotations + +import pytest + +from tests.integration.src.sqlbuild.compiler.helpers import ( + GoldenEntry, + golden_differences, + golden_entry, + golden_name, + read_golden, +) +from tests.integration.src.sqlbuild.compiler.sql_test_glue._test_types import HelperReadsTestCase +from tests.integration.src.sqlbuild.compiler.sql_test_glue.helpers import helper_reads_view + + +@pytest.mark.parametrize( + "test_case", + [ + HelperReadsTestCase( + description="helper cte read edges", + keys=frozenset({"base", "helper", "mock_orders", "étapé"}), + bodies=( + "SELECT * FROM base", + "SELECT * FROM BASE JOIN helper h ON 1=1 JOIN base b2 ON 1=1", + "SELECT * FROM s.base JOIN db.s.helper ON 1=1", + "WITH base AS (SELECT 1) SELECT * FROM base, helper", + "SELECT * FROM (WITH Helper AS (SELECT 1) SELECT * FROM helper) x JOIN base ON 1=1", + "SELECT 1", + "SELECT * FROM unrelated", + "SELECT * FROM base WHERE (", + "SELECT * FROM ÉTAPÉ", + 'SELECT * FROM "Base"', + "SELECT * FROM mock_orders UNION ALL SELECT * FROM helper WHERE id IN (SELECT id FROM base)", + "SELECT base FROM other", + "SELECT * FROM helper; SELECT * FROM base", + "SELECT * FROM t WHERE EXISTS (SELECT 1 FROM helper)", + ), + expected_differences=[], + ), + ], + ids=lambda case: case.description, +) +def test_given_cte_bodies_when_reading_helper_keys_then_matches_python_golden( + test_case: HelperReadsTestCase, +) -> None: + views: list[tuple[str, ...] | None] = [ + helper_reads_view(body, test_case.keys) for body in test_case.bodies + ] + expected: list[GoldenEntry] = read_golden(golden_name("helper_reads", test_case.description)) + + assert ( + golden_differences(expected, [golden_entry("helper_reads", view) for view in views]) + == test_case.expected_differences + ) + + +if __name__ == "__main__": + pytest.main([__file__, "-vv"]) diff --git a/tests/integration/src/sqlbuild/compiler/sql_test_glue/test_native_sql_test_assembly.py b/tests/integration/src/sqlbuild/compiler/sql_test_glue/test_native_sql_test_assembly.py new file mode 100644 index 0000000000..a553eeefa3 --- /dev/null +++ b/tests/integration/src/sqlbuild/compiler/sql_test_glue/test_native_sql_test_assembly.py @@ -0,0 +1,155 @@ +"""SQL tests assembled natively match the tests, diagnostics and errors recorded from Python's +assembly, which the native assembly replaces. + +Expected outputs were recorded once from the pre-port Python assembly (`_assemble_compiled_sql_test`) +into `tests/goldens/python_oracle/sql_test_assembly_*.json`. +""" + +from __future__ import annotations + +import random +from collections import Counter +from pathlib import Path + +import pytest + +from tests.integration.src.sqlbuild.compiler.helpers import ( + GoldenEntry, + golden_differences, + golden_name, + read_golden, +) +from tests.integration.src.sqlbuild.compiler.sql_test_glue._test_types import ( + EdgeSqlTestAssemblyTestCase, + GeneratedSqlTestAssemblyParityTestCase, +) +from tests.integration.src.sqlbuild.compiler.sql_test_glue.helpers import ( + EDGE_DECIMAL_CONTEXT, + EDGE_DECIMAL_OVERFLOW, + EDGE_DEEP_HELPER, + EDGE_INVALID_UNREAD_HELPER, + EDGE_UNICODE_CONTENTS, + EDGE_UNICODE_MACRO_SCOPE, + INVERTED_WINDOW, + NO_WINDOW, + VALID_WINDOW, + PlanningCallOutcome, + SqlTestCorpusShape, + assembly_golden_entry, + assembly_outcome, + edge_sql_test_files, + generated_sql_test_assembly_files, + outcome_kind, + record_native_assemblies, + write_project, +) + + +@pytest.mark.parametrize( + "test_case", + [ + GeneratedSqlTestAssemblyParityTestCase( + description="model, direct, parameterized and mock-reads-helper tests", + seed=20261010, + count=4, + test_count=12, + shape=SqlTestCorpusShape( + windows=(NO_WINDOW, VALID_WINDOW, INVERTED_WINDOW), + stray_window_share=0.1, + helper_redefinition_share=0.15, + assertion_share=0.2, + unflattenable_assertion_share=0.1, + ), + expected_native_assemblies={ + "native_assembled": 201, + "native_with_diagnostics": 26, + "native_case_fingerprints": 101, + }, + ) + ], + ids=lambda case: case.description, +) +def test_given_generated_sql_tests_when_assembling_natively_then_compiled_tests_match_python( + test_case: GeneratedSqlTestAssemblyParityTestCase, + tmp_path: Path, + monkeypatch: pytest.MonkeyPatch, +) -> None: + rng: random.Random = random.Random(test_case.seed) + native_assemblies: Counter[str] = record_native_assemblies(monkeypatch=monkeypatch) + entries: list[GoldenEntry] = [] + outcomes: Counter[str] = Counter() + for index in range(test_case.count): + project_dir: Path = tmp_path / f"project_{index}" + write_project( + project_dir=project_dir, + files=generated_sql_test_assembly_files( + rng=rng, test_count=test_case.test_count, shape=test_case.shape + ), + ) + actual: PlanningCallOutcome = assembly_outcome(project_dir=project_dir) + entries.append(assembly_golden_entry(outcome=actual, project_dir=project_dir)) + outcomes[outcome_kind(actual)] += 1 + + assert ( + golden_differences( + read_golden(golden_name("sql_test_assembly", test_case.description)), entries + ), + dict(native_assemblies), + ) == ([], test_case.expected_native_assemblies), outcomes + + +@pytest.mark.parametrize( + "test_case", + [ + EdgeSqlTestAssemblyTestCase( + description="non-ASCII test contents, case-folded reads and located diagnostics", + files={"tests/unit/test_unicode.sql": EDGE_UNICODE_CONTENTS}, + expected_outcome="answered", + ), + EdgeSqlTestAssemblyTestCase( + description="a mock reading a deeply nested helper whose nested CTE shadows another", + files={"tests/unit/test_deep.sql": EDGE_DEEP_HELPER}, + expected_outcome="answered", + ), + EdgeSqlTestAssemblyTestCase( + description="decimal case parameters the default context rounds and flushes", + files={"tests/unit/test_decimal.sql": EDGE_DECIMAL_CONTEXT}, + expected_outcome="answered", + ), + EdgeSqlTestAssemblyTestCase( + description="a decimal case parameter the default context overflows", + files={"tests/unit/test_decimal.sql": EDGE_DECIMAL_OVERFLOW}, + expected_outcome="raised", + ), + EdgeSqlTestAssemblyTestCase( + description="a macro test over a model with a non-ASCII name after @", + files=EDGE_UNICODE_MACRO_SCOPE, + expected_outcome="answered", + ), + EdgeSqlTestAssemblyTestCase( + description="an unread helper with an invalid reference call", + files={"tests/unit/test_invalid.sql": EDGE_INVALID_UNREAD_HELPER}, + expected_outcome="answered", + ), + ], + ids=lambda case: case.description, +) +def test_given_edge_sql_test_when_assembling_natively_then_matches_recorded_python( + test_case: EdgeSqlTestAssemblyTestCase, tmp_path: Path +) -> None: + project_dir: Path = tmp_path / golden_name("edge", test_case.description) + write_project(project_dir=project_dir, files=edge_sql_test_files(extra_files=test_case.files)) + + actual: PlanningCallOutcome = assembly_outcome(project_dir=project_dir) + + assert ( + golden_differences( + read_golden(golden_name("sql_test_assembly", test_case.description)), + [assembly_golden_entry(outcome=actual, project_dir=project_dir)], + ), + outcome_kind(actual), + ) == ([], test_case.expected_outcome) + + +if __name__ == "__main__": + pytest.main([__file__, "-vv"]) diff --git a/tests/integration/src/sqlbuild/compiler/sql_test_glue/test_native_sql_test_planning_glue.py b/tests/integration/src/sqlbuild/compiler/sql_test_glue/test_native_sql_test_planning_glue.py deleted file mode 100644 index 22cc63e2ea..0000000000 --- a/tests/integration/src/sqlbuild/compiler/sql_test_glue/test_native_sql_test_planning_glue.py +++ /dev/null @@ -1,237 +0,0 @@ -"""SQL tests assembled and planned natively equal Python's assembly and the JSON-request plans.""" - -from __future__ import annotations - -import random -from collections import Counter -from pathlib import Path - -import pytest - -from sqlbuild.adapter.contract.classes.base_adapter import BaseAdapter -from sqlbuild.adapters.bigquery.classes.bigquery_adapter import BigQueryAdapter -from sqlbuild.adapters.duckdb.classes.duckdb_adapter import DuckDbAdapter -from sqlbuild.adapters.postgres.classes.postgres_adapter import PostgresAdapter -from sqlbuild.adapters.snowflake.classes.snowflake_adapter import SnowflakeAdapter -from sqlbuild.adapters.sqlserver.classes.sqlserver_adapter import SqlServerAdapter -from sqlbuild.compiler.compile.models import CompiledProject, CompiledSqlTest -from tests.integration.src.sqlbuild.compiler.helpers import mismatches -from tests.integration.src.sqlbuild.compiler.sql_test_glue._test_types import ( - GeneratedSqlTestAssemblyParityTestCase, - GeneratedSqlTestPlanningParityTestCase, -) -from tests.integration.src.sqlbuild.compiler.sql_test_glue.helpers import ( - INVERTED_WINDOW, - NO_WINDOW, - VALID_WINDOW, - PlanningCallOutcome, - SqlTestCorpusShape, - artifact_outcome, - assembly_outcome, - chain_outcome, - compiled_project, - generated_sql_test_assembly_files, - generated_sql_test_files, - native_raised_kinds, - outcome_kind, - planning_outcome, - record_native_answers, - record_native_assemblies, - use_sql_test_glue, - with_unmocked_assertion, - write_project, -) - -_ADAPTERS: dict[str, BaseAdapter] = { - "duckdb": DuckDbAdapter(), - "postgres": PostgresAdapter(), - "snowflake": SnowflakeAdapter(), - "bigquery": BigQueryAdapter(), - "sqlserver": SqlServerAdapter(), -} - - -@pytest.mark.parametrize( - "test_case", - [ - GeneratedSqlTestPlanningParityTestCase( - description="mocks, expected outputs, assertions, helpers, windows and failing tests", - seed=20261009, - count=4, - test_count=12, - shape=SqlTestCorpusShape( - windows=(NO_WINDOW, VALID_WINDOW, INVERTED_WINDOW), - stray_window_share=0.1, - helper_redefinition_share=0.15, - assertion_share=0.2, - unflattenable_assertion_share=0.1, - ), - adapter_names=("duckdb", "postgres", "snowflake", "bigquery", "sqlserver"), - expected_minimum_native_planned=624, - expected_minimum_native_with_errors=144, - expected_minimum_native_chains=398, - expected_minimum_native_raised=102, - expected_native_raised_kinds=frozenset( - {"compile_input", "planner_input", "sql_test_reference"} - ), - expected_minimum_answered_batches=0, - expected_minimum_raised_outcomes=108, - ), - GeneratedSqlTestPlanningParityTestCase( - description="multi-test batches that plan without window or helper errors", - seed=20261010, - count=3, - test_count=12, - shape=SqlTestCorpusShape( - windows=(NO_WINDOW, VALID_WINDOW), - stray_window_share=0.0, - helper_redefinition_share=0.0, - assertion_share=0.3, - unflattenable_assertion_share=0.0, - ), - adapter_names=("duckdb", "postgres", "snowflake", "bigquery", "sqlserver"), - expected_minimum_native_planned=1068, - expected_minimum_native_with_errors=192, - expected_minimum_native_chains=122, - expected_minimum_native_raised=45, - expected_native_raised_kinds=frozenset({"sql_test_reference"}), - expected_minimum_answered_batches=30, - expected_minimum_raised_outcomes=30, - ), - ], - ids=lambda case: case.description, -) -def test_given_generated_sql_tests_when_planning_natively_then_plans_match_the_json_request( - test_case: GeneratedSqlTestPlanningParityTestCase, - tmp_path: Path, - monkeypatch: pytest.MonkeyPatch, -) -> None: - rng: random.Random = random.Random(test_case.seed) - native_answers: Counter[str] = record_native_answers(monkeypatch=monkeypatch) - outcomes: Counter[str] = Counter() - differences: list[tuple[object, object, object]] = [] - for index in range(test_case.count): - project: CompiledProject = compiled_project( - project_dir=tmp_path / f"project_{index}", - files=generated_sql_test_files( - rng=rng, test_count=test_case.test_count, shape=test_case.shape - ), - ) - batches: tuple[tuple[CompiledSqlTest, ...], ...] = ( - project.sql_tests, - *((test,) for test in project.sql_tests), - (with_unmocked_assertion(project=project),), - ) - for adapter_name in test_case.adapter_names: - adapter: BaseAdapter = _ADAPTERS[adapter_name] - for render_sql in (False, True): - inputs: list[object] = [] - expected: list[object] = [] - actual: list[object] = [] - for tests in batches: - use_sql_test_glue(monkeypatch=monkeypatch, enabled=False) - expected.append( - planning_outcome( - project=project, tests=tests, adapter=adapter, render_sql=render_sql - ) - ) - use_sql_test_glue(monkeypatch=monkeypatch, enabled=True) - actual.append( - planning_outcome( - project=project, tests=tests, adapter=adapter, render_sql=render_sql - ) - ) - inputs.append((adapter_name, render_sql, tuple(test.name for test in tests))) - differences.extend(mismatches(inputs=inputs, expected=expected, actual=actual)) - outcomes.update(map(outcome_kind, actual[1:])) - outcomes[f"batch_{outcome_kind(actual[0])}"] += 1 - differences.extend( - mismatches( - inputs=[(adapter_name, "artifacts", tests) for tests in batches], - expected=[ - artifact_outcome(project=project, tests=tests, adapter=adapter, glue=False) - for tests in batches - ], - actual=[ - artifact_outcome(project=project, tests=tests, adapter=adapter, glue=True) - for tests in batches - ], - ) - ) - use_sql_test_glue(monkeypatch=monkeypatch, enabled=False) - python_chains: PlanningCallOutcome = chain_outcome(project=project, tests=project.sql_tests) - use_sql_test_glue(monkeypatch=monkeypatch, enabled=True) - native_chains: PlanningCallOutcome = chain_outcome(project=project, tests=project.sql_tests) - differences.extend( - mismatches(inputs=["chains"], expected=[python_chains], actual=[native_chains]) - ) - - assert ( - differences, - native_answers["native_planned"] >= test_case.expected_minimum_native_planned, - native_answers["native_with_errors"] >= test_case.expected_minimum_native_with_errors, - native_answers["native_chains"] >= test_case.expected_minimum_native_chains, - native_answers["native_raised"] >= test_case.expected_minimum_native_raised, - native_raised_kinds(answers=native_answers) >= test_case.expected_native_raised_kinds, - outcomes["batch_answered"] >= test_case.expected_minimum_answered_batches, - outcomes["raised"] >= test_case.expected_minimum_raised_outcomes, - ) == ([], True, True, True, True, True, True, True), (native_answers, outcomes) - - -@pytest.mark.parametrize( - "test_case", - [ - GeneratedSqlTestAssemblyParityTestCase( - description="model, direct, parameterized and mock-reads-helper tests", - seed=20261010, - count=4, - test_count=12, - shape=SqlTestCorpusShape( - windows=(NO_WINDOW, VALID_WINDOW, INVERTED_WINDOW), - stray_window_share=0.1, - helper_redefinition_share=0.15, - assertion_share=0.2, - unflattenable_assertion_share=0.1, - ), - expected_native_assemblies={ - "native_assembled": 181, - "native_with_diagnostics": 17, - "native_case_fingerprints": 96, - "deferred_macro_mocks": 4, - "deferred_non_ascii_text": 11, - "deferred_decimal_context": 5, - }, - ) - ], - ids=lambda case: case.description, -) -def test_given_generated_sql_tests_when_assembling_natively_then_compiled_tests_match_python( - test_case: GeneratedSqlTestAssemblyParityTestCase, - tmp_path: Path, - monkeypatch: pytest.MonkeyPatch, -) -> None: - rng: random.Random = random.Random(test_case.seed) - native_assemblies: Counter[str] = record_native_assemblies(monkeypatch=monkeypatch) - differences: list[tuple[object, object, object]] = [] - outcomes: Counter[str] = Counter() - for index in range(test_case.count): - project_dir: Path = tmp_path / f"project_{index}" - write_project( - project_dir=project_dir, - files=generated_sql_test_assembly_files( - rng=rng, test_count=test_case.test_count, shape=test_case.shape - ), - ) - expected: PlanningCallOutcome = assembly_outcome( - project_dir=project_dir, monkeypatch=monkeypatch, native=False - ) - actual: PlanningCallOutcome = assembly_outcome( - project_dir=project_dir, monkeypatch=monkeypatch, native=True - ) - differences.extend(mismatches(inputs=[index], expected=[expected], actual=[actual])) - outcomes[outcome_kind(actual)] += 1 - - assert (differences, dict(native_assemblies)) == ( - [], - test_case.expected_native_assemblies, - ), outcomes diff --git a/tests/unit/scripts/compiler_differential/_helpers/goldens/test_compiler_goldens.py b/tests/unit/scripts/compiler_differential/_helpers/goldens/test_compiler_goldens.py index 44e1fc9f37..b0d576094e 100644 --- a/tests/unit/scripts/compiler_differential/_helpers/goldens/test_compiler_goldens.py +++ b/tests/unit/scripts/compiler_differential/_helpers/goldens/test_compiler_goldens.py @@ -60,7 +60,7 @@ def test_given_corpus_project_when_locating_its_golden_then_only_golden_corpora_ [ GoldenPayloadTestCase( description="paths_ids_timings_and_repeated_sql_masked", - run=engine_run(engine="python", message=_MESSAGE, compiled_sql=_SQL), + run=engine_run(engine="native", message=_MESSAGE, compiled_sql=_SQL), masked_paths=((PROJECT_PATH, ""),), expected_payload={ "commands": [ @@ -118,63 +118,63 @@ def test_given_engine_run_when_building_golden_then_run_specific_noise_is_masked GoldenCheckTestCase( description="identical_engines_match", project="failure/unknown-ref", - recorded=(engine_run(engine="python", message=_MESSAGE, compiled_sql=_SQL),), + recorded=(engine_run(engine="native", message=_MESSAGE, compiled_sql=_SQL),), checked=( - engine_run(engine="python", message=_MESSAGE, compiled_sql=_SQL), engine_run(engine="native", message=_MESSAGE, compiled_sql=_SQL), + engine_run(engine="native-preview", message=_MESSAGE, compiled_sql=_SQL), ), expected_differences=(), ), GoldenCheckTestCase( description="changed_sql_names_the_engine", project="failure/unknown-ref", - recorded=(engine_run(engine="python", message=_MESSAGE, compiled_sql=_SQL),), + recorded=(engine_run(engine="native", message=_MESSAGE, compiled_sql=_SQL),), checked=( - engine_run(engine="python", message=_MESSAGE, compiled_sql=_SQL), - engine_run(engine="native", message=_MESSAGE, compiled_sql="SELECT 2\n"), + engine_run(engine="native", message=_MESSAGE, compiled_sql=_SQL), + engine_run(engine="native-preview", message=_MESSAGE, compiled_sql="SELECT 2\n"), ), - expected_differences=(("golden (native)", ("golden", "native")),), + expected_differences=(("golden (native-preview)", ("golden", "native-preview")),), ), GoldenCheckTestCase( description="missing_failure_golden_fails", project="failure/unknown-ref", recorded=(), - checked=(engine_run(engine="python", message=_MESSAGE, compiled_sql=_SQL),), + checked=(engine_run(engine="native", message=_MESSAGE, compiled_sql=_SQL),), expected_differences=(("golden unknown-ref.json", ("golden", "hint")),), ), GoldenCheckTestCase( description="missing_seed_golden_outside_the_recorded_range_is_skipped", project="seed/40", recorded=(), - checked=(engine_run(engine="python", message=_MESSAGE, compiled_sql=_SQL),), + checked=(engine_run(engine="native", message=_MESSAGE, compiled_sql=_SQL),), expected_differences=(), ), GoldenCheckTestCase( description="missing_seed_golden_inside_the_recorded_range_fails", project="seed/3", recorded=(), - checked=(engine_run(engine="python", message=_MESSAGE, compiled_sql=_SQL),), + checked=(engine_run(engine="native", message=_MESSAGE, compiled_sql=_SQL),), expected_differences=(("golden 3.json", ("golden", "hint")),), ), GoldenCheckTestCase( description="missing_dialect_variant_of_the_recorded_first_seed_fails", project="seed/0-postgres", recorded=(), - checked=(engine_run(engine="python", message=_MESSAGE, compiled_sql=_SQL),), + checked=(engine_run(engine="native", message=_MESSAGE, compiled_sql=_SQL),), expected_differences=(("golden 0-postgres.json", ("golden", "hint")),), ), GoldenCheckTestCase( description="dialect_variant_of_an_ad_hoc_first_seed_is_skipped", project="seed/3-postgres", recorded=(), - checked=(engine_run(engine="python", message=_MESSAGE, compiled_sql=_SQL),), + checked=(engine_run(engine="native", message=_MESSAGE, compiled_sql=_SQL),), expected_differences=(), ), GoldenCheckTestCase( description="missing_seed_range_fails_closed_even_with_the_seed_golden", project="seed/3", - recorded=(engine_run(engine="python", message=_MESSAGE, compiled_sql=_SQL),), - checked=(engine_run(engine="python", message=_MESSAGE, compiled_sql=_SQL),), + recorded=(engine_run(engine="native", message=_MESSAGE, compiled_sql=_SQL),), + checked=(engine_run(engine="native", message=_MESSAGE, compiled_sql=_SQL),), expected_differences=(("golden seed_range.toml", ("golden", "hint")),), seed_range_dir="elsewhere", ), diff --git a/tests/unit/scripts/compiler_differential/_helpers/running/test_evidence.py b/tests/unit/scripts/compiler_differential/_helpers/running/test_evidence.py index d97afea5f4..f9c20b5e25 100644 --- a/tests/unit/scripts/compiler_differential/_helpers/running/test_evidence.py +++ b/tests/unit/scripts/compiler_differential/_helpers/running/test_evidence.py @@ -30,7 +30,7 @@ FailureEvidenceTestCase( description="differing warm stderr keeps both engines' evidence", stderr_by_engine={ - "python": "Semantic checks were partial for 1 models:\n", + "native": "Semantic checks were partial for 1 models:\n", "native-preview": "SQL test planning START\n", }, expected_files=( @@ -38,16 +38,16 @@ "example__orders/native-preview/compiled-tests-stat.tsv", "example__orders/native-preview/target/compiled/tests/orders/test_orders.sql", "example__orders/native-preview/target/sql-test-artifacts.json", - "example__orders/python/0-compile-warm.stderr", - "example__orders/python/compiled-tests-stat.tsv", - "example__orders/python/target/compiled/tests/orders/test_orders.sql", - "example__orders/python/target/sql-test-artifacts.json", + "example__orders/native/0-compile-warm.stderr", + "example__orders/native/compiled-tests-stat.tsv", + "example__orders/native/target/compiled/tests/orders/test_orders.sql", + "example__orders/native/target/sql-test-artifacts.json", ), - expected_evidence_engines=("native-preview", "python"), + expected_evidence_engines=("native", "native-preview"), ), FailureEvidenceTestCase( description="identical runs keep nothing", - stderr_by_engine={"python": "done\n", "native-preview": "done\n"}, + stderr_by_engine={"native": "done\n", "native-preview": "done\n"}, expected_files=(), expected_evidence_engines=(), ), @@ -74,7 +74,7 @@ def test_given_engine_runs_when_comparing_then_only_differing_projects_keep_evid source_dir=tmp_path, ), options=DifferentialOptions( - engines=("python", "native-preview"), + engines=("native", "native-preview"), work_dir=tmp_path / "work", jobs=1, stage_captures=False, diff --git a/tests/unit/scripts/compiler_differential/_helpers/running/test_native_fallbacks.py b/tests/unit/scripts/compiler_differential/_helpers/running/test_native_fallbacks.py index 11ac5a0584..60bf52a9f9 100644 --- a/tests/unit/scripts/compiler_differential/_helpers/running/test_native_fallbacks.py +++ b/tests/unit/scripts/compiler_differential/_helpers/running/test_native_fallbacks.py @@ -2,10 +2,12 @@ from __future__ import annotations +from enum import StrEnum from pathlib import Path import pytest +from scripts.compiler_differential._helpers.running import native_fallbacks from scripts.compiler_differential._helpers.running.native_fallbacks import ( fallback_problems, observed_fallbacks, @@ -49,9 +51,27 @@ ) _SESSION: FallbackKey = ("native-preview", "model_analysis", "analysis_session", "session") _SHIPPED_RUN: RecordedRun = RecordedRun( - engines=("python", "native"), corpora=("seeds", "failures"), seed_start=0, seeds=12 + engines=("native",), corpora=("seeds", "failures"), seed_start=0, seeds=12 ) _LIST_HEAD: str = "seed_start = 0\nseeds = 12\n" +_REFERENCES: FallbackKey = ( + "native", + "reference_extraction", + "reference_extraction.sql_scan", + "deferred", +) +_REFERENCES_ENTRY: str = ( + '\n[[entry]]\nengine = "native"\nstage = "reference_extraction"\n' + 'site = "reference_extraction.sql_scan"\nkind = "deferred"\n' +) + + +class _SwitchableStage(StrEnum): + """Stand-in preview stages: `model_loop` can be switched off, `reference_extraction` cannot.""" + + MODEL_LOOP = "model_loop" + + _VARIABLES_ENTRY: str = ( '\n[[entry]]\nengine = "native"\nstage = "model_loop"\n' 'site = "model_loop.sql_variables"\nkind = "deferred"\n' @@ -89,7 +109,7 @@ def test_given_engine_records_when_observing_then_entries_are_summed_per_corpus( ) observed: dict[FallbackKey, dict[str, int]] = observed_fallbacks( - comparisons=[comparison], engines=("python", "native-preview") + comparisons=[comparison], engines=("native", "native-preview") ) assert observed == test_case.expected_observed @@ -146,6 +166,16 @@ def test_given_engine_records_when_observing_then_entries_are_summed_per_corpus( "removes a fallback must report native answers for the work it now does" ], ), + FallbackGateTestCase( + description="vanished_entry_of_a_shipped_stage_only_asks_for_removal", + allow_list=_LIST_HEAD + _REFERENCES_ENTRY + "counts = { seed = 3 }\n", + observed={}, + run=_SHIPPED_RUN, + expected_problems=[ + "native reference_extraction reference_extraction.sql_scan deferred (seed): " + "listed but no longer occurs; remove it from the allow-list" + ], + ), FallbackGateTestCase( description="changed_count_fails", allow_list=_LIST_HEAD + _VARIABLES_ENTRY + "counts = { seed = 195 }\n", @@ -202,9 +232,7 @@ def test_given_engine_records_when_observing_then_entries_are_summed_per_corpus( description="other_seed_range_is_refused", allow_list=_LIST_HEAD, observed={}, - run=RecordedRun( - engines=("python", "native"), corpora=("seeds",), seed_start=0, seeds=60 - ), + run=RecordedRun(engines=("native",), corpora=("seeds",), seed_start=0, seeds=60), expected_problems=[ "the allow-list holds counts for --seed-start 0 --seeds 12; this run used " "--seed-start 0 --seeds 60" @@ -214,8 +242,9 @@ def test_given_engine_records_when_observing_then_entries_are_summed_per_corpus( ids=lambda case: case.description, ) def test_given_allow_list_when_checking_a_run_then_every_difference_is_a_problem( - test_case: FallbackGateTestCase, tmp_path: Path + test_case: FallbackGateTestCase, tmp_path: Path, monkeypatch: pytest.MonkeyPatch ) -> None: + monkeypatch.setattr(native_fallbacks, "NativeStage", _SwitchableStage) path: Path = tmp_path / "native_fallbacks.toml" _ = path.write_text(test_case.allow_list, encoding="utf-8") diff --git a/tests/unit/scripts/compiler_differential/_helpers/running/test_options.py b/tests/unit/scripts/compiler_differential/_helpers/running/test_options.py index 8c7e4d3423..a5ff267939 100644 --- a/tests/unit/scripts/compiler_differential/_helpers/running/test_options.py +++ b/tests/unit/scripts/compiler_differential/_helpers/running/test_options.py @@ -25,10 +25,14 @@ [ EngineEnvironmentTestCase( description="grouped_by_engine", - values=("native:PYTHONPATH=/tmp/hook", "native:ORDERS_REGION=a=b", "python:EMPTY="), + values=( + "native:PYTHONPATH=/tmp/hook", + "native:ORDERS_REGION=a=b", + "native-preview:EMPTY=", + ), expected_environment={ "native": {"PYTHONPATH": "/tmp/hook", "ORDERS_REGION": "a=b"}, - "python": {"EMPTY": ""}, + "native-preview": {"EMPTY": ""}, }, ) ], diff --git a/tests/unit/scripts/compiler_differential/_helpers/running/test_records.py b/tests/unit/scripts/compiler_differential/_helpers/running/test_records.py index ffac8427af..4e76f0ada9 100644 --- a/tests/unit/scripts/compiler_differential/_helpers/running/test_records.py +++ b/tests/unit/scripts/compiler_differential/_helpers/running/test_records.py @@ -44,11 +44,11 @@ expected_deferrals={("legacy_fallback", "compact.py"): 1}, expected_fallbacks={("model_loop.sql_variables", "deferred"): 3}, expected_lines=( - "Polyglot wheel calls (python):", + "Polyglot wheel calls (native):", f" 5 {_SITE} parse_one (seed 5)", - "Analysis deferrals (python):", + "Analysis deferrals (native):", " 1 legacy_fallback compact.py (seed 1)", - "Native-to-Python fallbacks (python):", + "Native-to-Python fallbacks (native):", " 3 model_loop.sql_variables deferred (seed 3)", "Polyglot wheel calls (native-preview): none recorded", "Analysis deferrals (native-preview): none recorded", @@ -77,7 +77,7 @@ def test_given_record_files_when_reporting_then_counts_are_summed_per_engine_and records=(records, read_analysis_records(tmp_path / "missing")), ) ], - engines=("python", "native-preview"), + engines=("native", "native-preview"), ) ) diff --git a/tests/unit/scripts/compiler_differential/_helpers/running/test_report.py b/tests/unit/scripts/compiler_differential/_helpers/running/test_report.py index cd1c3f8ee6..ff29b155c4 100644 --- a/tests/unit/scripts/compiler_differential/_helpers/running/test_report.py +++ b/tests/unit/scripts/compiler_differential/_helpers/running/test_report.py @@ -130,7 +130,7 @@ def test_given_results_and_coverage_when_summarizing_then_failures_never_read_as ) -> None: summary: str = format_summary( comparisons=test_case.comparisons, - engines=("python", "native"), + engines=("native", "native-preview"), seconds=2.0, missing_coverage=test_case.missing_coverage, gate_failures=test_case.gate_failures, diff --git a/tests/unit/src/sqlbuild/adapter/type_system/test_type_normalization.py b/tests/unit/src/sqlbuild/adapter/type_system/test_type_normalization.py index 3603293450..f81fcf9e0c 100644 --- a/tests/unit/src/sqlbuild/adapter/type_system/test_type_normalization.py +++ b/tests/unit/src/sqlbuild/adapter/type_system/test_type_normalization.py @@ -1,9 +1,7 @@ from __future__ import annotations import pytest -from polyglot_sql import PolyglotError -import sqlbuild.adapter.type_system._helpers.type_normalization as type_normalization from sqlbuild.adapter.contract.models import NormalizedType from sqlbuild.adapter.contract.types import TypeFamily from sqlbuild.adapter.type_system.main.normalize_numeric_family import normalize_numeric_family @@ -16,15 +14,6 @@ ) -class _UnsupportedTypePolyglot: - PolyglotError: type[PolyglotError] = PolyglotError - - @staticmethod - def parse_data_type(*args: object, **kwargs: object) -> object: - del args, kwargs - raise PolyglotError("unsupported test type") - - @pytest.mark.parametrize( "test_case", [ @@ -62,40 +51,6 @@ def test_given_type_string_when_normalizing_then_it_returns_expected_shape( assert result == test_case.expected_type -@pytest.mark.parametrize( - "test_case", - [ - TypeNormalizationTestCase( - description="fallback normalizes bigquery integer alias", - dialect="bigquery", - raw_type="INTEGER", - expected_type=NormalizedType(normalized_name="INT64", family=TypeFamily.INTEGER), - ), - TypeNormalizationTestCase( - description="fallback preserves decimal precision and scale", - dialect="snowflake", - raw_type="NUMBER(10,2)", - expected_type=NormalizedType( - normalized_name="DECIMAL(10,2)", - family=TypeFamily.DECIMAL, - precision=10, - scale=2, - ), - ), - ], - ids=lambda case: case.description, -) -def test_given_type_string_when_normalizing_without_polyglot_then_it_returns_expected_shape( - test_case: TypeNormalizationTestCase, - monkeypatch: pytest.MonkeyPatch, -) -> None: - monkeypatch.setattr(type_normalization, "import_polyglot", _UnsupportedTypePolyglot) - - result: NormalizedType = normalize_type(type_sql=test_case.raw_type, dialect=test_case.dialect) - - assert result == test_case.expected_type - - @pytest.mark.parametrize( "test_case", [ @@ -170,69 +125,6 @@ def test_given_type_strings_when_comparing_then_it_returns_expected_equality( assert result is test_case.expected_equal -@pytest.mark.parametrize( - "test_case", - [ - TypeEqualityTestCase( - description="fallback treats bigquery string aliases as equal", - dialect="bigquery", - left_type="STRING", - right_type="TEXT", - expected_equal=True, - ), - TypeEqualityTestCase( - description="fallback keeps decimal scale differences distinct", - dialect="snowflake", - left_type="NUMBER(10,2)", - right_type="NUMBER(10,3)", - expected_equal=False, - ), - TypeEqualityTestCase( - description="fallback treats snowflake timestamp alias as timestamp_ntz", - dialect="snowflake", - left_type="TIMESTAMP", - right_type="TIMESTAMP_NTZ", - expected_equal=True, - ), - TypeEqualityTestCase( - description="fallback treats snowflake integer as number 38 scale 0", - dialect="snowflake", - left_type="INTEGER", - right_type="NUMBER(38,0)", - expected_equal=True, - ), - TypeEqualityTestCase( - description="fallback treats snowflake text as default varchar", - dialect="snowflake", - left_type="TEXT", - right_type="VARCHAR(16777216)", - expected_equal=True, - ), - TypeEqualityTestCase( - description="fallback treats bare snowflake number as number 38 scale 0", - dialect="snowflake", - left_type="NUMBER", - right_type="NUMBER(38,0)", - expected_equal=True, - ), - ], - ids=lambda case: case.description, -) -def test_given_type_strings_when_comparing_without_polyglot_then_it_returns_expected_equality( - test_case: TypeEqualityTestCase, - monkeypatch: pytest.MonkeyPatch, -) -> None: - monkeypatch.setattr(type_normalization, "import_polyglot", _UnsupportedTypePolyglot) - - result: bool = types_equal( - left=test_case.left_type, - right=test_case.right_type, - dialect=test_case.dialect, - ) - - assert result is test_case.expected_equal - - @pytest.mark.parametrize( "test_case", [ @@ -266,29 +158,3 @@ def test_given_type_string_when_resolving_numeric_family_then_it_returns_expecte ) assert result == test_case.expected_family - - -@pytest.mark.parametrize( - "test_case", - [ - NumericFamilyTestCase( - description="fallback classifies float64 as float family", - dialect="bigquery", - raw_type="FLOAT64", - expected_family="float", - ) - ], - ids=lambda case: case.description, -) -def test_given_type_string_without_polyglot_when_resolving_numeric_family_then_it_returns_expected( - test_case: NumericFamilyTestCase, - monkeypatch: pytest.MonkeyPatch, -) -> None: - monkeypatch.setattr(type_normalization, "import_polyglot", _UnsupportedTypePolyglot) - - result: str | None = normalize_numeric_family( - type_sql=test_case.raw_type, - dialect=test_case.dialect, - ) - - assert result == test_case.expected_family diff --git a/tests/unit/src/sqlbuild/cli/commands/_helpers/entry/test_compiler_engine_option.py b/tests/unit/src/sqlbuild/cli/commands/_helpers/entry/test_compiler_engine_option.py index fc4a0629f3..468456a3a7 100644 --- a/tests/unit/src/sqlbuild/cli/commands/_helpers/entry/test_compiler_engine_option.py +++ b/tests/unit/src/sqlbuild/cli/commands/_helpers/entry/test_compiler_engine_option.py @@ -38,15 +38,15 @@ ), CompilerEngineOptionTestCase( description="flag_after_subcommand", - argv=("plan", "--compiler-engine", "python"), + argv=("plan", "--compiler-engine", "native"), environment_value="", - expected_engine="python", + expected_engine="native", ), CompilerEngineOptionTestCase( description="flag_overrides_invalid_environment", - argv=("compile", "--compiler-engine", "python"), + argv=("compile", "--compiler-engine", "native-preview"), environment_value="rust", - expected_engine="python", + expected_engine="native-preview", ), ], ids=lambda case: case.description, @@ -72,7 +72,21 @@ def test_given_engine_selection_when_parsing_then_flag_value_is_recorded( argv=("compile", "--compiler-engine", "rust"), environment_value="", expected_exit_code=2, - expected_error="argument --compiler-engine: invalid choice: 'rust'", + expected_error="--compiler-engine must be one of native, native-preview (got 'rust')", + ), + RejectedCompilerEngineTestCase( + description="removed_python_flag_value", + argv=("compile", "--compiler-engine", "python"), + environment_value="", + expected_exit_code=2, + expected_error="--compiler-engine 'python' is no longer supported", + ), + RejectedCompilerEngineTestCase( + description="removed_python_environment_value", + argv=("compile",), + environment_value="python", + expected_exit_code=2, + expected_error="SQLBUILD_COMPILER_ENGINE 'python' is no longer supported", ), RejectedCompilerEngineTestCase( description="unknown_environment_value", @@ -80,8 +94,7 @@ def test_given_engine_selection_when_parsing_then_flag_value_is_recorded( environment_value="rust", expected_exit_code=2, expected_error=( - "SQLBUILD_COMPILER_ENGINE must be one of python, native, native-preview " - "(got 'rust')" + "SQLBUILD_COMPILER_ENGINE must be one of native, native-preview (got 'rust')" ), ), ], diff --git a/tests/unit/src/sqlbuild/cli/compile_reuse/_helpers/test_compiler_engine_reuse_key.py b/tests/unit/src/sqlbuild/cli/compile_reuse/_helpers/test_compiler_engine_reuse_key.py index e122193509..76965985e1 100644 --- a/tests/unit/src/sqlbuild/cli/compile_reuse/_helpers/test_compiler_engine_reuse_key.py +++ b/tests/unit/src/sqlbuild/cli/compile_reuse/_helpers/test_compiler_engine_reuse_key.py @@ -25,15 +25,15 @@ "test_case", [ EngineReuseDigestTestCase( - description="python_then_native", - first_environment={COMPILER_ENGINE_ENV_VAR: "python"}, + description="preview_then_native", + first_environment={COMPILER_ENGINE_ENV_VAR: "native-preview"}, second_environment={COMPILER_ENGINE_ENV_VAR: "native"}, expected_same_digest=False, ), EngineReuseDigestTestCase( - description="unset_then_python", + description="unset_then_preview", first_environment={}, - second_environment={COMPILER_ENGINE_ENV_VAR: "python"}, + second_environment={COMPILER_ENGINE_ENV_VAR: "native-preview"}, expected_same_digest=False, ), EngineReuseDigestTestCase( @@ -74,9 +74,9 @@ def test_given_same_invocation_when_engine_environment_changes_then_reuse_key_fo "test_case", [ EngineReuseStoreTestCase( - description="python", - engine="python", - expected_entry_directory="target/cache/compiler/project-reuse-v1", + description="native_preview", + engine="native-preview", + expected_entry_directory="target/cache/compiler-native-preview-v1/project-reuse-v1", ), EngineReuseStoreTestCase( description="native", diff --git a/tests/unit/src/sqlbuild/compiler/compile/_helpers/_test_types.py b/tests/unit/src/sqlbuild/compiler/compile/_helpers/_test_types.py index 39fb797bb2..2419372f0b 100644 --- a/tests/unit/src/sqlbuild/compiler/compile/_helpers/_test_types.py +++ b/tests/unit/src/sqlbuild/compiler/compile/_helpers/_test_types.py @@ -13,8 +13,6 @@ ) from sqlbuild.compiler.compile.types import AttachedAuditTargetKind, SqlTestMode from sqlbuild.compiler.lineage.types import ( - ColumnLineageConfidence, - ColumnTransformKind, InferredNullability, ) from sqlbuild.compiler.references.types import SqlReferenceKind @@ -84,12 +82,6 @@ class AuditFactoryAttachmentTestCase: expected_warning_code: str | None = None -@dataclass(frozen=True) -class AnalysisCacheTestCase: - description: str - expected_count: int - - @dataclass(frozen=True) class NativeSqlTestExtractionParityTestCase: description: str @@ -463,30 +455,6 @@ class ExtractSqlAnalysisExpectedBranchesErrorTestCase: expected_error_fragment: str -@dataclass(frozen=True) -class ModelBuildDepsTestCase: - description: str - references: tuple[CompileSqlReference, ...] - expected_deps: tuple[CompiledObjectKey, ...] - seed_names: frozenset[str] = field(default_factory=frozenset) - - -@dataclass(frozen=True) -class AuditScopeDepsTestCase: - description: str - references: tuple[CompileSqlReference, ...] - attached_target_kind: str | None - attached_target_name: str | None - expected_scope_deps: tuple[CompiledObjectKey, ...] - - -@dataclass(frozen=True) -class SqlTestScopeDepsTestCase: - description: str - expected_model_names: tuple[str, ...] - expected_scope_deps: tuple[CompiledObjectKey, ...] - - @dataclass(frozen=True) class AssembleCompiledProjectTestCase: description: str @@ -884,14 +852,6 @@ class ExpectedCountTestCase: expected_count: int -@dataclass(frozen=True) -class CachedLineageRoundTripTestCase: - description: str - transform_kind: ColumnTransformKind - confidence: ColumnLineageConfidence - expected_compact: bool - - @dataclass(frozen=True) class ClassifyDirectLogicSqlTestCtesErrorTestCase: description: str @@ -1102,14 +1062,6 @@ class QualifiedReferenceScanTestCase: expected_names: frozenset[str] -@dataclass(frozen=True) -class CompactLineageCacheEncodingTestCase: - description: str - output_column: str - resource_names: dict[int, str] - expected_lineage_columns: int = 2 - - @dataclass(frozen=True) class RequiredDescriptionUnitCase: """One resource kind checked by the required-description compile rule.""" diff --git a/tests/unit/src/sqlbuild/compiler/compile/_helpers/analysis/_test_types.py b/tests/unit/src/sqlbuild/compiler/compile/_helpers/analysis/_test_types.py index 0a910a212c..7f2d2cefb1 100644 --- a/tests/unit/src/sqlbuild/compiler/compile/_helpers/analysis/_test_types.py +++ b/tests/unit/src/sqlbuild/compiler/compile/_helpers/analysis/_test_types.py @@ -16,14 +16,6 @@ class DynamicPivotAnalysisTestCase: aggregate: str = "MAX" -@dataclass(frozen=True) -class CompactAnalysisWorkersTestCase: - description: str - model_count: int - sql_bytes_per_model: int - expected_workers: int - - @dataclass(frozen=True) class SetOperationSearchTestCase: description: str diff --git a/tests/unit/src/sqlbuild/compiler/compile/_helpers/analysis/test_compact_workers.py b/tests/unit/src/sqlbuild/compiler/compile/_helpers/analysis/test_compact_workers.py deleted file mode 100644 index 2c70492d97..0000000000 --- a/tests/unit/src/sqlbuild/compiler/compile/_helpers/analysis/test_compact_workers.py +++ /dev/null @@ -1,58 +0,0 @@ -from __future__ import annotations - -import orjson -import pytest - -from sqlbuild.compiler.compile._helpers.analysis import compact -from sqlbuild.compiler.compile.models import CompactBatchPreparation -from tests.unit.src.sqlbuild.compiler.compile._helpers.analysis._test_types import ( - CompactAnalysisWorkersTestCase, -) - -_MIB: int = 1024 * 1024 - - -@pytest.mark.parametrize( - "test_case", - ( - CompactAnalysisWorkersTestCase( - description="small project", - model_count=3, - sql_bytes_per_model=64, - expected_workers=4, - ), - CompactAnalysisWorkersTestCase( - description="dense ten thousand model project", - model_count=10_000, - sql_bytes_per_model=(64 * _MIB) // 10_000, - expected_workers=4, - ), - ), - ids=lambda case: case.description, -) -def test_given_project_size_when_running_compact_analysis_then_native_uses_all_workers( - test_case: CompactAnalysisWorkersTestCase, - monkeypatch: pytest.MonkeyPatch, -) -> None: - captured: list[dict[str, object]] = [] - - def analyze(request_json: str) -> str: - captured.append(orjson.loads(request_json)) - return "{}" - - monkeypatch.setattr(compact._native, "analyze_project_queries_compact_json", analyze) - sql: str = "SELECT 1 AS order_id" + " " * (test_case.sql_bytes_per_model - 20) - preparation: CompactBatchPreparation = CompactBatchPreparation( - cleaned_sql=(sql,) * test_case.model_count, - queries=({"sql": "SELECT 1 AS order_id", "dialect": "duckdb"},), - templates=({"queryIndex": 0},), - projections=({"templateIndex": 0},) * test_case.model_count, - ) - - _ = compact._run_compact_analysis_batch(preparation=preparation) - - assert [request["workers"] for request in captured] == [test_case.expected_workers] - - -if __name__ == "__main__": - raise SystemExit(pytest.main([__file__, "-n", "auto", "--dist", "loadfile"])) diff --git a/tests/unit/src/sqlbuild/compiler/compile/_helpers/analysis/test_dynamic_pivot.py b/tests/unit/src/sqlbuild/compiler/compile/_helpers/analysis/test_dynamic_pivot.py index 812f5c5c4a..b662a814da 100644 --- a/tests/unit/src/sqlbuild/compiler/compile/_helpers/analysis/test_dynamic_pivot.py +++ b/tests/unit/src/sqlbuild/compiler/compile/_helpers/analysis/test_dynamic_pivot.py @@ -2,10 +2,10 @@ import pytest -from sqlbuild.compiler.compile._helpers.analysis.dynamic_pivot import ( - analyze_dynamic_column_contract, +from sqlbuild.compiler.analysis_session._helpers.dynamic_contracts import ( + native_dynamic_contracts, ) -from sqlbuild.compiler.compile.models import DynamicColumnContractProof +from sqlbuild.compiler.analysis_session.models import NativePivotTables from sqlbuild.spec.contracts.models import SchemaDynamicColumnFamily from tests.unit.src.sqlbuild.compiler.compile._helpers.analysis._test_types import ( DynamicPivotAnalysisTestCase, @@ -147,41 +147,48 @@ def test_given_dynamic_family_when_analyzing_output_then_requires_supported_closed_shape( test_case: DynamicPivotAnalysisTestCase, ) -> None: - proof: DynamicColumnContractProof | None = analyze_dynamic_column_contract( - query_sql=test_case.query_sql, - dialect=test_case.dialect, - families=( - SchemaDynamicColumnFamily( - name="category_amounts", - pivot_column="category", - value_column="amount", - aggregate=test_case.aggregate, - type="DECIMAL(12,2)", - ), - ), - column_types_by_table={ - "order_amounts": { - "customer_id": "INTEGER", - "category": "VARCHAR", - "amount": "DECIMAL(12,2)", - "country": "VARCHAR", + (proof,) = native_dynamic_contracts( + session=None, + tables=NativePivotTables( + dialect=test_case.dialect, + column_types_by_table={ + "order_amounts": { + "customer_id": "INTEGER", + "category": "VARCHAR", + "amount": "DECIMAL(12,2)", + "country": "VARCHAR", + }, + "partial_order_amounts": { + "customer_id": "INTEGER", + "category": "VARCHAR", + "amount": "DECIMAL(12,2)", + }, }, - "partial_order_amounts": { - "customer_id": "INTEGER", - "category": "VARCHAR", - "amount": "DECIMAL(12,2)", + authoritative_column_types_by_table={ + "order_amounts": { + "customer_id": "INTEGER", + "category": "VARCHAR", + "amount": "DECIMAL(12,2)", + "country": "VARCHAR", + } }, - }, - authoritative_column_types_by_table={ - "order_amounts": { - "customer_id": "INTEGER", - "category": "VARCHAR", - "amount": "DECIMAL(12,2)", - "country": "VARCHAR", - } - }, - column_nullability_by_table={}, - dynamic_families_by_table={}, + column_nullability_by_table={}, + dynamic_families_by_table={}, + ), + models=( + ( + test_case.query_sql, + ( + SchemaDynamicColumnFamily( + name="category_amounts", + pivot_column="category", + value_column="amount", + aggregate=test_case.aggregate, + type="DECIMAL(12,2)", + ), + ), + ), + ), ) assert proof is not None diff --git a/tests/unit/src/sqlbuild/compiler/compile/_helpers/config/helpers.py b/tests/unit/src/sqlbuild/compiler/compile/_helpers/config/helpers.py index 7e4ceef286..d6cec06921 100644 --- a/tests/unit/src/sqlbuild/compiler/compile/_helpers/config/helpers.py +++ b/tests/unit/src/sqlbuild/compiler/compile/_helpers/config/helpers.py @@ -25,8 +25,6 @@ ) from sqlbuild.compiler.discovery.main.discover import discover_project_inputs from sqlbuild.compiler.discovery.models import DiscoveredProjectInputs, DiscoveredSqlModelFile -from sqlbuild.compiler.frontier.constants import COMPILER_ENGINE_ENV_VAR -from sqlbuild.compiler.frontier.types import CompilerEngine from sqlbuild.spec.contracts.models import ( DefaultsConfig, MaterializationDefaultsConfig, @@ -46,9 +44,8 @@ def compile_with_config_build_count( project_dir: Path, monkeypatch: pytest.MonkeyPatch, ) -> tuple[CompileProjectInputs, int]: - """Compile a project on the Python engine while counting its native model config builds.""" + """Compile a project while counting its native model config builds.""" - monkeypatch.setenv(COMPILER_ENGINE_ENV_VAR, CompilerEngine.PYTHON.value) build_counts: list[int] = [0] original_build_model_config: Callable[..., CompileModelConfig] = ( attachment_core.build_native_model_config diff --git a/tests/unit/src/sqlbuild/compiler/compile/_helpers/helpers.py b/tests/unit/src/sqlbuild/compiler/compile/_helpers/helpers.py index 98531f3687..d87ed36445 100644 --- a/tests/unit/src/sqlbuild/compiler/compile/_helpers/helpers.py +++ b/tests/unit/src/sqlbuild/compiler/compile/_helpers/helpers.py @@ -1,4 +1,4 @@ -import sqlite3 +import itertools from collections.abc import Callable from dataclasses import dataclass, replace from pathlib import Path @@ -6,11 +6,16 @@ from typing import cast from sqlbuild.adapter.contract.classes.base_adapter import BaseAdapter +from sqlbuild.adapter.contract.models import ExpressionInferenceProfile from sqlbuild.adapters.bigquery.classes.bigquery_adapter import BigQueryAdapter from sqlbuild.adapters.duckdb.classes.duckdb_adapter import DuckDbAdapter from sqlbuild.adapters.postgres.classes.postgres_adapter import PostgresAdapter from sqlbuild.adapters.snowflake.classes.snowflake_adapter import SnowflakeAdapter from sqlbuild.adapters.sqlserver.classes.sqlserver_adapter import SqlServerAdapter +from sqlbuild.compiler.analysis_session.main._infer_native_query_columns import ( + infer_native_query_columns, +) +from sqlbuild.compiler.analysis_session.models import NativeColumnQuery, NativeQueryColumns from sqlbuild.compiler.compile._helpers.attachment import core as attachment_core from sqlbuild.compiler.compile._helpers.diagnostics.collector import ( collect_compile_diagnostics, @@ -26,9 +31,7 @@ from sqlbuild.compiler.compile.main._assemble_project import assemble_project from sqlbuild.compiler.compile.main._build_compile_inputs import build_compile_inputs from sqlbuild.compiler.compile.models import ( - AnalysisCacheContext, CompileAdapterContext, - CompileAnalysisSelection, CompiledDirectLogicSqlTestPayload, CompiledLineageColumnFact, CompiledLineageSourceFact, @@ -71,11 +74,14 @@ DiscoveredTaskFunction, ) from sqlbuild.compiler.graph.main._build_lineage_upstream_deps import build_lineage_upstream_deps -from sqlbuild.compiler.lineage.types import ColumnLineageConfidence, ColumnTransformKind +from sqlbuild.compiler.lineage.types import ( + ColumnLineageConfidence, + ColumnTransformKind, + InferredNullability, +) from sqlbuild.compiler.model_loop.main._build_native_declaration_contexts import ( build_native_declaration_contexts, ) -from sqlbuild.compiler.pipeline.main.compiled_project import build_compiled_project from sqlbuild.compiler.planner._helpers.graph.core import build_execution_upstream_deps from sqlbuild.compiler.planner._helpers.resolve.refs import resolve_ref_references from sqlbuild.compiler.scopes.main.build_scope_lookup import build_scope_lookup @@ -252,25 +258,6 @@ def compile_project_inputs(*, project_dir: Path) -> CompileProjectInputs: ) -def compile_project_with_cache( - *, - project_dir: Path, - analysis_selection: CompileAnalysisSelection | None = None, - no_cache: bool = False, -) -> CompiledProject: - """Compile a discovered DuckDB fixture through the cache-enabled project boundary.""" - - effective_selection: CompileAnalysisSelection = replace( - analysis_selection or CompileAnalysisSelection(), - no_cache=no_cache, - ) - return build_compiled_project( - discovered_inputs=discover_project_inputs(project_dir=project_dir), - adapter=DuckDbAdapter(), - analysis_selection=effective_selection, - ) - - def compiled_sql_test_expected_model_names(test: CompiledSqlTest) -> tuple[str, ...]: getters: MappingProxyType[type[object], Callable[[object], tuple[str, ...]]] = MappingProxyType( { @@ -516,17 +503,6 @@ def write_scoped_macro_orders_project(project_dir: Path) -> None: ) -def stored_analysis_contents(*, context: AnalysisCacheContext, cache_key: str) -> str: - """Return the raw stored payload of one analysis cache entry.""" - - database_path: Path = next(context.root.rglob("model-analysis.sqlite3")) - with sqlite3.connect(database_path) as connection: - row: tuple[str] = connection.execute( - "SELECT payload FROM model_analysis WHERE cache_key = ?", (cache_key,) - ).fetchone() - return row[0] - - REQUIRED_DESCRIPTION_BASE_INPUTS: DiscoveredProjectInputs = DiscoveredProjectInputs( project_config=ProjectConfig(name="orders", adapter="duckdb"), local_config=LocalConfig(), @@ -846,3 +822,29 @@ def extract_test_sql( return extract_unexpanded_sql_test( sql=sql, file_label=file_label, mode=mode, syntax=SqlLexicalSyntax() )[0] + + +def reanalysed_columns( + *, + query_sql: str, + references: tuple[CompileSqlReference, ...] = (), + column_nullability_by_table: dict[str, dict[str, InferredNullability]] | None = None, + column_types_by_table: dict[str, dict[str, str]] | None = None, + inference_profile: ExpressionInferenceProfile | None = None, + allow_compact_analysis: bool = True, + recover_cte_facts: bool = True, +) -> NativeQueryColumns: + """Native compact re-analysis over known input types, as source bindings run it.""" + + assert allow_compact_analysis and recover_cte_facts + values: list[InferredNullability] = list( + itertools.chain.from_iterable( + map(dict.values, (column_nullability_by_table or {}).values()) + ) + ) + assert all(value == InferredNullability.UNKNOWN for value in values) + return infer_native_query_columns( + queries=(NativeColumnQuery(sql=query_sql, mode="reanalysis", references=references),), + profile=inference_profile or ExpressionInferenceProfile(), + column_types_by_table=column_types_by_table, + )[0] diff --git a/tests/unit/src/sqlbuild/compiler/compile/_helpers/native_stages/_test_types.py b/tests/unit/src/sqlbuild/compiler/compile/_helpers/native_stages/_test_types.py deleted file mode 100644 index 6fd230b52e..0000000000 --- a/tests/unit/src/sqlbuild/compiler/compile/_helpers/native_stages/_test_types.py +++ /dev/null @@ -1,16 +0,0 @@ -from __future__ import annotations - -from dataclasses import dataclass - -from sqlbuild.compiler.compile.models import DynamicColumnContractProof, ModelSqlAnalysis -from sqlbuild.spec.contracts.models import SchemaDynamicColumnFamily - - -@dataclass(frozen=True) -class DynamicColumnContractDispatchTestCase: - description: str - sql_analysis: ModelSqlAnalysis | None - native_proof: DynamicColumnContractProof | None - dialect: str - families: tuple[SchemaDynamicColumnFamily, ...] - expected_proof: DynamicColumnContractProof | None diff --git a/tests/unit/src/sqlbuild/compiler/compile/_helpers/native_stages/test_dynamic_column_contract_by_engine.py b/tests/unit/src/sqlbuild/compiler/compile/_helpers/native_stages/test_dynamic_column_contract_by_engine.py deleted file mode 100644 index 8addc9e694..0000000000 --- a/tests/unit/src/sqlbuild/compiler/compile/_helpers/native_stages/test_dynamic_column_contract_by_engine.py +++ /dev/null @@ -1,114 +0,0 @@ -"""A model's native analysis may carry its dynamic pivot proof; otherwise Python proves it.""" - -from __future__ import annotations - -from functools import partial - -import pytest - -from sqlbuild.compiler.compile._helpers.analysis.dynamic_pivot import ( - analyze_dynamic_column_contract, -) -from sqlbuild.compiler.compile._helpers.native_stages.assembly import ( - dynamic_column_contract_by_engine, -) -from sqlbuild.compiler.compile.models import ( - DynamicColumnContractProof, - ModelSqlAnalysis, - PolyglotAnalysisResult, -) -from sqlbuild.spec.contracts.models import SchemaDynamicColumnFamily -from tests.unit.src.sqlbuild.compiler.compile._helpers.native_stages._test_types import ( - DynamicColumnContractDispatchTestCase, -) - -_NATIVE_PROOF: DynamicColumnContractProof = DynamicColumnContractProof( - output_proven=False, failure_reason="native session proof" -) -_PYTHON_UNSUPPORTED_PROOF: DynamicColumnContractProof = DynamicColumnContractProof( - output_proven=False, - failure_reason=("adapter dialect 'bigquery' does not support compiler-proven dynamic pivots"), -) -_FAMILY: SchemaDynamicColumnFamily = SchemaDynamicColumnFamily( - name="category_amounts", - pivot_column="category", - value_column="amount", - aggregate="MAX", - type="DECIMAL(12,2)", -) -_ANALYSIS: PolyglotAnalysisResult = PolyglotAnalysisResult(analysis_succeeded=True) - - -@pytest.mark.parametrize( - "test_case", - ( - DynamicColumnContractDispatchTestCase( - description="native analysis proof replaces the python proof", - native_proof=None, - sql_analysis=ModelSqlAnalysis( - polyglot_analysis=_ANALYSIS, - placeholders=None, - dynamic_column_contract=_NATIVE_PROOF, - ), - dialect="bigquery", - families=(_FAMILY,), - expected_proof=_NATIVE_PROOF, - ), - DynamicColumnContractDispatchTestCase( - description="analysis without a proof falls back to the python proof", - native_proof=None, - sql_analysis=ModelSqlAnalysis(polyglot_analysis=_ANALYSIS, placeholders=None), - dialect="bigquery", - families=(_FAMILY,), - expected_proof=_PYTHON_UNSUPPORTED_PROOF, - ), - DynamicColumnContractDispatchTestCase( - description="unanalyzed model falls back to the python proof", - native_proof=None, - sql_analysis=None, - dialect="bigquery", - families=(_FAMILY,), - expected_proof=_PYTHON_UNSUPPORTED_PROOF, - ), - DynamicColumnContractDispatchTestCase( - description="a batched native proof answers an unanalyzed model", - native_proof=_NATIVE_PROOF, - sql_analysis=None, - dialect="bigquery", - families=(_FAMILY,), - expected_proof=_NATIVE_PROOF, - ), - DynamicColumnContractDispatchTestCase( - description="model without dynamic families has no proof", - native_proof=None, - sql_analysis=ModelSqlAnalysis(polyglot_analysis=_ANALYSIS, placeholders=None), - dialect="snowflake", - families=(), - expected_proof=None, - ), - ), - ids=lambda case: case.description, -) -def test_given_model_analysis_when_proving_dynamic_contract_then_native_proof_takes_precedence( - test_case: DynamicColumnContractDispatchTestCase, -) -> None: - proof: DynamicColumnContractProof | None = dynamic_column_contract_by_engine( - sql_analysis=test_case.sql_analysis, - native_proof=test_case.native_proof, - python_proof=partial( - analyze_dynamic_column_contract, - query_sql="SELECT * FROM order_amounts", - dialect=test_case.dialect, - families=test_case.families, - column_types_by_table={}, - authoritative_column_types_by_table={}, - column_nullability_by_table={}, - dynamic_families_by_table={}, - ), - ) - - assert proof == test_case.expected_proof - - -if __name__ == "__main__": - pytest.main([__file__, "-vv"]) diff --git a/tests/unit/src/sqlbuild/compiler/compile/_helpers/render/test_cursor_intrinsics.py b/tests/unit/src/sqlbuild/compiler/compile/_helpers/render/test_cursor_intrinsics.py index f053717e22..e8956a2043 100644 --- a/tests/unit/src/sqlbuild/compiler/compile/_helpers/render/test_cursor_intrinsics.py +++ b/tests/unit/src/sqlbuild/compiler/compile/_helpers/render/test_cursor_intrinsics.py @@ -2,7 +2,11 @@ import pytest -from sqlbuild.compiler.compile._helpers.analysis.compact import infer_columns_with_sql_analysis +from sqlbuild.adapter.contract.models import ExpressionInferenceProfile +from sqlbuild.compiler.analysis_session.main._infer_native_query_columns import ( + infer_native_query_columns, +) +from sqlbuild.compiler.analysis_session.models import NativeColumnQuery from sqlbuild.compiler.compile._helpers.render.cursor_intrinsics import ( cursor_intrinsics_analysis_sql, get_validated_model_cursor_intrinsics, @@ -154,7 +158,10 @@ def test_given_typed_intrinsic_when_analyzing_then_infers_non_null_column( cursor_type=test_case.cursor_type, ) - assert infer_columns_with_sql_analysis(query_sql=analysis_sql) == ( + assert infer_native_query_columns( + queries=(NativeColumnQuery(sql=analysis_sql, mode="parse"),), + profile=ExpressionInferenceProfile(), + )[0].columns == ( InferredColumn( name="batch_start", type=test_case.expected_type, diff --git a/tests/unit/src/sqlbuild/compiler/compile/_helpers/test_analysis_cache.py b/tests/unit/src/sqlbuild/compiler/compile/_helpers/test_analysis_cache.py deleted file mode 100644 index 1033e715b4..0000000000 --- a/tests/unit/src/sqlbuild/compiler/compile/_helpers/test_analysis_cache.py +++ /dev/null @@ -1,1174 +0,0 @@ -from __future__ import annotations - -import json -import sqlite3 -from collections.abc import Callable -from pathlib import Path -from unittest.mock import Mock - -import pytest - -from sqlbuild.adapter.contract.models import ExpressionInferenceProfile -from sqlbuild.compiler.compile._helpers.analysis import cache as analysis_cache -from sqlbuild.compiler.compile._helpers.analysis.cache import ( - build_analysis_cache_context, - model_analysis_cache_key, - read_model_analyses, - write_model_analyses, -) -from sqlbuild.compiler.compile._helpers.assembly import project as assembly_project -from sqlbuild.compiler.compile._helpers.refs import cache as reference_cache -from sqlbuild.compiler.compile.constants import COMPILE_CACHE_DISABLE_ENV_VAR -from sqlbuild.compiler.compile.exceptions import CompileInputError -from sqlbuild.compiler.compile.models import ( - AnalysisCacheContext, - CompactLineageFacts, - CompileAnalysisSelection, - CompiledLineageColumnFact, - CompiledLineageSourceFact, - CompiledModel, - CompiledProject, - CompileSqlReference, - PolyglotAnalysisResult, -) -from sqlbuild.compiler.frontier.main.compiler_cache_directory import compiler_cache_directory -from sqlbuild.compiler.lineage.types import ( - ColumnLineageConfidence, - ColumnTransformKind, - InferredNullability, -) -from sqlbuild.compiler.profiling.main.collect import collect_compile_timings -from sqlbuild.compiler.references.types import SqlReferenceKind -from tests.unit.src.sqlbuild.compiler.compile._helpers._test_types import ( - AnalysisCacheTestCase, - CachedLineageRoundTripTestCase, - CompactLineageCacheEncodingTestCase, -) -from tests.unit.src.sqlbuild.compiler.compile._helpers.helpers import ( - compile_project_with_cache, - stored_analysis_contents, -) - -pytestmark: pytest.MarkDecorator = pytest.mark.usefixtures("python_compiler_engine") - -_CACHE_REPO_FILES: dict[str, str] = { - "sqlbuild_project.toml": 'name = "cache_demo"\nadapter = "duckdb"\n', - "sources/raw.yml": """ -sources: - - name: raw_orders - description: Test source raw_orders. - contract: enforced - expression: "(SELECT 1 AS order_id)" - columns: - - name: order_id - type: INTEGER - nullable: false -""".strip() - + "\n", - "models/orders.sql": """ -MODEL (description "Test model orders."); - -SELECT order_id FROM __source("raw_orders") -""".strip() - + "\n", -} -_SELECTION_REPO_FILES: dict[str, str] = { - "sqlbuild_project.toml": 'name = "selection_demo"\nadapter = "duckdb"\n', - "models/root.sql": "MODEL (description 'Test model root.');\n\nSELECT 1 AS id\n", - "models/middle.sql": 'MODEL (description "Test model middle.");\n\nSELECT id FROM __ref("root")\n', - "models/leaf.sql": 'MODEL (description "Test model leaf.");\n\nSELECT id FROM __ref("middle")\n', - "models/unrelated.sql": "MODEL (description 'Test model unrelated.');\n\nSELECT 2 AS id\n", -} - - -@pytest.mark.parametrize( - "test_case", - ( - AnalysisCacheTestCase( - description="changed compiler semantics invalidate prior analysis", - expected_count=1, - ), - ), - ids=lambda case: case.description, -) -def test_given_changed_analysis_algorithm_when_compiling_then_refreshes_cached_facts( - test_case: AnalysisCacheTestCase, - tmp_path: Path, - monkeypatch: pytest.MonkeyPatch, - write_repo_files: Callable[[Path, dict[str, str]], None], -) -> None: - write_repo_files(tmp_path, _CACHE_REPO_FILES) - cold_project: CompiledProject = compile_project_with_cache(project_dir=tmp_path) - monkeypatch.setattr( - analysis_cache, "_ANALYSIS_ALGORITHM_FINGERPRINT", "synthetic-next-algorithm" - ) - with collect_compile_timings() as changed_metrics: - changed_project: CompiledProject = compile_project_with_cache(project_dir=tmp_path) - with collect_compile_timings() as normal_metrics: - normal_project: CompiledProject = compile_project_with_cache(project_dir=tmp_path) - - assert changed_metrics.as_milliseconds()["analysis_cache_misses"] == test_case.expected_count - assert changed_metrics.as_milliseconds()["analysis_entry_cache_hits"] == 0 - assert changed_metrics.as_milliseconds()["analysis_batch_cache_hits"] == 0 - assert normal_metrics.as_milliseconds()["analysis_entry_cache_hits"] == test_case.expected_count - assert normal_project.models == changed_project.models == cold_project.models - assert normal_project.diagnostics == cold_project.diagnostics - - -@pytest.mark.parametrize( - "test_case", - (AnalysisCacheTestCase(description="successful cache hit", expected_count=1),), - ids=lambda case: case.description, -) -def test_given_successful_analysis_when_compiling_again_then_reuses_identical_cached_facts( - test_case: AnalysisCacheTestCase, - tmp_path: Path, - monkeypatch: pytest.MonkeyPatch, - write_repo_files: Callable[[Path, dict[str, str]], None], -) -> None: - write_repo_files(tmp_path, _CACHE_REPO_FILES) - cold_project: CompiledProject = compile_project_with_cache(project_dir=tmp_path) - analyzer: Mock = Mock( - side_effect=AssertionError("Polyglot analysis must not run on a cache hit") - ) - monkeypatch.setattr(assembly_project, "analyze_columns_and_lineage_with_polyglot", analyzer) - signature_builder: Mock = Mock( - side_effect=AssertionError("output signatures must not be rebuilt on a cache hit") - ) - monkeypatch.setattr(assembly_project, "model_analysis_output_signature", signature_builder) - reference_scanner: Mock = Mock( - side_effect=AssertionError("SQL references must not be scanned on a cache hit") - ) - monkeypatch.setattr(reference_cache, "scan_sql_reference_calls", reference_scanner) - - warm_project: CompiledProject = compile_project_with_cache(project_dir=tmp_path) - - assert warm_project.models == cold_project.models - assert warm_project.diagnostics == cold_project.diagnostics - analyzer.assert_not_called() - signature_builder.assert_not_called() - reference_scanner.assert_not_called() - assert len(tuple((compiler_cache_directory(tmp_path)).rglob("*.sqlite3"))) == ( - test_case.expected_count + 1 - ) - - -@pytest.mark.parametrize( - "test_case", - (AnalysisCacheTestCase(description="completed compact cache reuse", expected_count=1),), - ids=lambda case: case.description, -) -def test_given_completed_compact_cache_when_compiling_again_then_skips_analysis_and_binding( - test_case: AnalysisCacheTestCase, - tmp_path: Path, - monkeypatch: pytest.MonkeyPatch, - write_repo_files: Callable[[Path, dict[str, str]], None], -) -> None: - write_repo_files(tmp_path, _CACHE_REPO_FILES) - monkeypatch.setattr( - assembly_project, "_COMPACT_BATCH_CACHE_MIN_MODEL_COUNT", test_case.expected_count - ) - cold_project: CompiledProject = compile_project_with_cache(project_dir=tmp_path) - analyzer: Mock = Mock(side_effect=AssertionError("completed facts must not be reanalyzed")) - validator: Mock = Mock(side_effect=AssertionError("completed bindings must not be revalidated")) - monkeypatch.setattr(assembly_project, "_analyze_model_sql_requests", analyzer) - monkeypatch.setattr(assembly_project, "get_schema_validations", validator) - - warm_project: CompiledProject = compile_project_with_cache(project_dir=tmp_path) - - assert warm_project.models == cold_project.models - assert warm_project.diagnostics == cold_project.diagnostics - analyzer.assert_not_called() - validator.assert_not_called() - - -@pytest.mark.parametrize( - "test_case", - (AnalysisCacheTestCase(description="exact compact batch reuse", expected_count=1),), - ids=lambda case: case.description, -) -def test_given_exact_compact_batch_when_entry_rows_are_absent_then_warm_compile_reuses_batch( - test_case: AnalysisCacheTestCase, - tmp_path: Path, - monkeypatch: pytest.MonkeyPatch, - write_repo_files: Callable[[Path, dict[str, str]], None], -) -> None: - write_repo_files(tmp_path, _CACHE_REPO_FILES) - monkeypatch.setattr(assembly_project, "_COMPACT_BATCH_CACHE_MIN_MODEL_COUNT", 1) - cold_project: CompiledProject = compile_project_with_cache(project_dir=tmp_path) - cache_path: Path = compiler_cache_directory(tmp_path) / "v13" / "model-analysis.sqlite3" - with sqlite3.connect(cache_path) as connection: - batch_count: int = connection.execute( - "SELECT COUNT(*) FROM model_analysis_compact_batch" - ).fetchone()[0] - _ = connection.execute("DELETE FROM model_analysis") - - with collect_compile_timings() as metrics: - warm_project: CompiledProject = compile_project_with_cache(project_dir=tmp_path) - - assert batch_count == 1 - assert warm_project.models == cold_project.models - assert warm_project.diagnostics == cold_project.diagnostics - assert metrics.as_milliseconds()["analysis_batch_cache_hits"] == test_case.expected_count - assert metrics.as_milliseconds()["analysis_entry_cache_hits"] == 0 - assert metrics.as_milliseconds()["analysis_cache_misses"] == 0 - assert metrics.as_milliseconds()["analysis_cache_bypasses"] == 0 - - -@pytest.mark.parametrize( - "test_case", - (AnalysisCacheTestCase(description="one changed compact model", expected_count=4),), - ids=lambda case: case.description, -) -def test_given_one_changed_model_when_entry_rows_are_absent_then_compact_batch_reuses_unchanged( - test_case: AnalysisCacheTestCase, - tmp_path: Path, - monkeypatch: pytest.MonkeyPatch, - write_repo_files: Callable[[Path, dict[str, str]], None], -) -> None: - write_repo_files(tmp_path, _SELECTION_REPO_FILES) - monkeypatch.setattr(assembly_project, "_COMPACT_BATCH_CACHE_MIN_MODEL_COUNT", 1) - cold_project: CompiledProject = compile_project_with_cache(project_dir=tmp_path) - cache_path: Path = compiler_cache_directory(tmp_path) / "v13" / "model-analysis.sqlite3" - with sqlite3.connect(cache_path) as connection: - _ = connection.execute("DELETE FROM model_analysis") - (tmp_path / "models" / "unrelated.sql").write_text( - "MODEL (description 'Test model unrelated.');\n\nSELECT 3 AS id\n", - encoding="utf-8", - ) - - changed_project: CompiledProject = compile_project_with_cache(project_dir=tmp_path) - - models_by_name: dict[str, CompiledModel] = { - model.name: model for model in changed_project.models - } - cold_models_by_name: dict[str, CompiledModel] = { - model.name: model for model in cold_project.models - } - assert models_by_name["root"] == cold_models_by_name["root"] - assert models_by_name["middle"] == cold_models_by_name["middle"] - assert models_by_name["leaf"] == cold_models_by_name["leaf"] - assert models_by_name["unrelated"].query_sql == "SELECT 3 AS id" - assert len(models_by_name) == test_case.expected_count - assert changed_project.diagnostics == () - - -@pytest.mark.parametrize( - "test_case", - (AnalysisCacheTestCase(description="corrupt compact batch fallback", expected_count=1),), - ids=lambda case: case.description, -) -def test_given_corrupt_compact_batch_when_entry_rows_are_valid_then_warm_compile_falls_back( - test_case: AnalysisCacheTestCase, - tmp_path: Path, - monkeypatch: pytest.MonkeyPatch, - write_repo_files: Callable[[Path, dict[str, str]], None], -) -> None: - write_repo_files(tmp_path, _CACHE_REPO_FILES) - monkeypatch.setattr(assembly_project, "_COMPACT_BATCH_CACHE_MIN_MODEL_COUNT", 1) - cold_project: CompiledProject = compile_project_with_cache(project_dir=tmp_path) - cache_path: Path = compiler_cache_directory(tmp_path) / "v13" / "model-analysis.sqlite3" - with sqlite3.connect(cache_path) as connection: - _ = connection.execute( - "UPDATE model_analysis_compact_batch SET payload = ?", - (b'{"version":1,"response":"tampered"}',), - ) - - warm_project: CompiledProject = compile_project_with_cache(project_dir=tmp_path) - - assert warm_project.models == cold_project.models - assert len(warm_project.models) == test_case.expected_count - assert warm_project.diagnostics == cold_project.diagnostics - - -@pytest.mark.parametrize( - "test_case", - (AnalysisCacheTestCase(description="changed SQL cache miss", expected_count=2),), - ids=lambda case: case.description, -) -def test_given_changed_expanded_sql_when_compiling_then_writes_a_new_analysis_object( - test_case: AnalysisCacheTestCase, - tmp_path: Path, - monkeypatch: pytest.MonkeyPatch, - write_repo_files: Callable[[Path, dict[str, str]], None], -) -> None: - write_repo_files(tmp_path, _CACHE_REPO_FILES) - cold_project: CompiledProject = compile_project_with_cache(project_dir=tmp_path) - changed_sql = 'MODEL (description "Test model.");\n\nSELECT order_id + 1 AS order_id FROM __source("raw_orders")\n' - (tmp_path / "models" / "orders.sql").write_text(changed_sql, encoding="utf-8") - analyzer: Mock = Mock(wraps=assembly_project.analyze_columns_and_lineage_with_polyglot) - monkeypatch.setattr(assembly_project, "analyze_columns_and_lineage_with_polyglot", analyzer) - - changed_project: CompiledProject = compile_project_with_cache(project_dir=tmp_path) - - assert changed_project.models[0].query_sql != cold_project.models[0].query_sql - assert analyzer.call_count == test_case.expected_count - - -@pytest.mark.parametrize( - "test_case", - (AnalysisCacheTestCase(description="corrupt cache fallback", expected_count=2),), - ids=lambda case: case.description, -) -def test_given_corrupt_analysis_when_compiling_then_reanalyzes_and_repairs_the_entry( - test_case: AnalysisCacheTestCase, - tmp_path: Path, - monkeypatch: pytest.MonkeyPatch, - write_repo_files: Callable[[Path, dict[str, str]], None], -) -> None: - write_repo_files(tmp_path, _CACHE_REPO_FILES) - cold_project: CompiledProject = compile_project_with_cache(project_dir=tmp_path) - cache_path: Path = compiler_cache_directory(tmp_path) / "v13" / "model-analysis.sqlite3" - with sqlite3.connect(cache_path) as connection: - persisted_contents: str = connection.execute( - "SELECT payload FROM model_analysis" - ).fetchone()[0] - corrupt_contents: str = persisted_contents.replace("order_id", "tampered", 1) - assert corrupt_contents != persisted_contents - _ = connection.execute( - "UPDATE model_analysis SET payload = ?", - (corrupt_contents,), - ) - analyzer: Mock = Mock(wraps=assembly_project.analyze_columns_and_lineage_with_polyglot) - monkeypatch.setattr(assembly_project, "analyze_columns_and_lineage_with_polyglot", analyzer) - - repaired_project: CompiledProject = compile_project_with_cache(project_dir=tmp_path) - - with sqlite3.connect(cache_path) as connection: - repaired_contents: str = connection.execute( - "SELECT payload FROM model_analysis" - ).fetchone()[0] - _digest, _separator, serialized_payload = repaired_contents.partition("\n") - repaired_payload: dict[str, object] = json.loads(serialized_payload) - assert repaired_project.models == cold_project.models - assert repaired_payload["v"] == 13 - assert isinstance(repaired_payload["s"], str) - assert analyzer.call_count == test_case.expected_count - - -@pytest.mark.parametrize( - "test_case", - (AnalysisCacheTestCase(description="non-text analysis cache fallback", expected_count=2),), - ids=lambda case: case.description, -) -def test_given_non_text_analysis_cache_when_compiling_then_reanalyzes_safely( - test_case: AnalysisCacheTestCase, - tmp_path: Path, - monkeypatch: pytest.MonkeyPatch, - write_repo_files: Callable[[Path, dict[str, str]], None], -) -> None: - write_repo_files(tmp_path, _CACHE_REPO_FILES) - _ = compile_project_with_cache(project_dir=tmp_path) - cache_path: Path = compiler_cache_directory(tmp_path) / "v13" / "model-analysis.sqlite3" - with sqlite3.connect(cache_path) as connection: - _ = connection.execute( - "UPDATE model_analysis SET payload = ?", - (sqlite3.Binary(b"broken"),), - ) - analyzer: Mock = Mock(wraps=assembly_project.analyze_columns_and_lineage_with_polyglot) - monkeypatch.setattr(assembly_project, "analyze_columns_and_lineage_with_polyglot", analyzer) - - _ = compile_project_with_cache(project_dir=tmp_path) - - assert analyzer.call_count == test_case.expected_count - - -@pytest.mark.parametrize( - "test_case", - (AnalysisCacheTestCase(description="corrupt reference cache fallback", expected_count=1),), - ids=lambda case: case.description, -) -def test_given_corrupt_reference_cache_when_compiling_then_rescans_and_repairs_the_entry( - test_case: AnalysisCacheTestCase, - tmp_path: Path, - monkeypatch: pytest.MonkeyPatch, - write_repo_files: Callable[[Path, dict[str, str]], None], -) -> None: - write_repo_files(tmp_path, _CACHE_REPO_FILES) - cold_project: CompiledProject = compile_project_with_cache(project_dir=tmp_path) - cache_path: Path = next( - (compiler_cache_directory(tmp_path) / "references-v3").glob("*.sqlite3") - ) - with sqlite3.connect(cache_path) as connection: - persisted_contents: str = connection.execute( - "SELECT payload FROM sql_reference" - ).fetchone()[0] - corrupt_contents: str = persisted_contents.replace("raw_orders", "tampered", 1) - assert corrupt_contents != persisted_contents - _ = connection.execute( - "UPDATE sql_reference SET payload = ?", - (corrupt_contents,), - ) - scanner: Mock = Mock(wraps=reference_cache.scan_sql_reference_calls) - monkeypatch.setattr(reference_cache, "scan_sql_reference_calls", scanner) - - repaired_project: CompiledProject = compile_project_with_cache(project_dir=tmp_path) - - with sqlite3.connect(cache_path) as connection: - repaired_contents: str = connection.execute("SELECT payload FROM sql_reference").fetchone()[ - 0 - ] - assert repaired_project.models == cold_project.models - assert "raw_orders" in repaired_contents - assert scanner.call_count == test_case.expected_count - - -@pytest.mark.parametrize( - "test_case", - (AnalysisCacheTestCase(description="non-text reference cache fallback", expected_count=1),), - ids=lambda case: case.description, -) -def test_given_non_text_reference_cache_when_compiling_then_rescans_safely( - test_case: AnalysisCacheTestCase, - tmp_path: Path, - monkeypatch: pytest.MonkeyPatch, - write_repo_files: Callable[[Path, dict[str, str]], None], -) -> None: - write_repo_files(tmp_path, _CACHE_REPO_FILES) - _ = compile_project_with_cache(project_dir=tmp_path) - cache_path: Path = next( - (compiler_cache_directory(tmp_path) / "references-v3").glob("*.sqlite3") - ) - with sqlite3.connect(cache_path) as connection: - _ = connection.execute( - "UPDATE sql_reference SET payload = ?", - (sqlite3.Binary(b"broken"),), - ) - scanner: Mock = Mock(wraps=reference_cache.scan_sql_reference_calls) - monkeypatch.setattr(reference_cache, "scan_sql_reference_calls", scanner) - - _ = compile_project_with_cache(project_dir=tmp_path) - - assert scanner.call_count == test_case.expected_count - - -@pytest.mark.parametrize( - "test_case", - (AnalysisCacheTestCase(description="deterministic unsuccessful result", expected_count=1),), - ids=lambda case: case.description, -) -def test_given_unsuccessful_analysis_when_writing_then_reuses_deterministic_result( - test_case: AnalysisCacheTestCase, - tmp_path: Path, -) -> None: - cache_key: str = "a" * 64 - context: AnalysisCacheContext = AnalysisCacheContext( - root=tmp_path, - shared_fingerprint="shared", - ) - write_model_analyses( - context=context, - analyses_by_key={ - cache_key: PolyglotAnalysisResult(analysis_succeeded=False), - }, - latest_analyses_by_model={ - "orders": PolyglotAnalysisResult(analysis_succeeded=False), - }, - ) - analyses, _, _ = read_model_analyses( - context=context, - cache_keys=(cache_key,), - model_names=("orders",), - upstream_model_names_by_key={cache_key: ()}, - ) - - assert len(analyses) == test_case.expected_count - assert analyses[cache_key].analysis_succeeded is False - - -@pytest.mark.parametrize( - "test_case", - ( - CachedLineageRoundTripTestCase( - description="indexed lineage decodes lazily", - transform_kind=ColumnTransformKind.CAST, - confidence=ColumnLineageConfidence.HIGH, - expected_compact=True, - ), - CachedLineageRoundTripTestCase( - description="unindexed lineage values decode eagerly", - transform_kind=ColumnTransformKind.UNKNOWN, - confidence=ColumnLineageConfidence.LOW, - expected_compact=False, - ), - ), - ids=lambda case: case.description, -) -def test_given_cached_lineage_when_reading_then_facts_round_trip_exactly( - test_case: CachedLineageRoundTripTestCase, - tmp_path: Path, -) -> None: - cache_key: str = "b" * 64 - context: AnalysisCacheContext = AnalysisCacheContext(root=tmp_path, shared_fingerprint="shared") - shared_source: CompiledLineageSourceFact = CompiledLineageSourceFact( - resource_type="source", resource_name="raw_orders", column_name="order_id" - ) - analysis: PolyglotAnalysisResult = PolyglotAnalysisResult( - analysis_succeeded=True, - lineage_columns=( - CompiledLineageColumnFact( - output_column="order_id", - upstream_columns=(shared_source,), - transform_kind=test_case.transform_kind, - confidence=test_case.confidence, - ), - CompiledLineageColumnFact( - output_column="order_key", - upstream_columns=( - shared_source, - CompiledLineageSourceFact( - resource_type="model", resource_name="orders", column_name="order_key" - ), - ), - transform_kind=ColumnTransformKind.EXPRESSION, - confidence=ColumnLineageConfidence.MEDIUM, - ), - ), - ) - write_model_analyses( - context=context, - analyses_by_key={cache_key: analysis}, - latest_analyses_by_model={"orders": analysis}, - ) - - analyses, _, _ = read_model_analyses( - context=context, - cache_keys=(cache_key,), - model_names=("orders",), - upstream_model_names_by_key={cache_key: ()}, - ) - - assert analyses[cache_key] == analysis - assert tuple(analyses[cache_key].lineage_columns) == analysis.lineage_columns - assert ( - isinstance(analyses[cache_key].lineage_columns, CompactLineageFacts) - is test_case.expected_compact - ) - - -@pytest.mark.parametrize( - "test_case", - ( - CompactLineageCacheEncodingTestCase( - description="canonical relation names", - output_column="order_id", - resource_names={}, - ), - CompactLineageCacheEncodingTestCase( - description="shared result projected onto member relation names", - output_column='caf\u00e9 "note"\n\t\x01\u2028', - resource_names={4: "orders_archive"}, - ), - ), - ids=lambda case: case.description, -) -def test_given_compact_lineage_when_writing_then_entry_matches_projected_fact_encoding( - test_case: CompactLineageCacheEncodingTestCase, - tmp_path: Path, -) -> None: - compact: CompactLineageFacts = CompactLineageFacts( - string_pool=("source", "raw_orders", test_case.output_column, "model", "orders"), - rows=( - (2, 1, 1, ((0, 1, 2),)), - (2, 2, 2, ((0, 1, 2), (3, 4, 2))), - ), - resource_names=test_case.resource_names, - ) - compact_analysis: PolyglotAnalysisResult = PolyglotAnalysisResult( - analysis_succeeded=True, lineage_columns=compact - ) - projected_analysis: PolyglotAnalysisResult = PolyglotAnalysisResult( - analysis_succeeded=True, lineage_columns=tuple(compact) - ) - compact_context: AnalysisCacheContext = AnalysisCacheContext( - root=tmp_path / "compact", shared_fingerprint="shared" - ) - projected_context: AnalysisCacheContext = AnalysisCacheContext( - root=tmp_path / "projected", shared_fingerprint="shared" - ) - cache_key: str = "c" * 64 - - write_model_analyses(context=compact_context, analyses_by_key={cache_key: compact_analysis}) - write_model_analyses(context=projected_context, analyses_by_key={cache_key: projected_analysis}) - - compact_contents: str = stored_analysis_contents(context=compact_context, cache_key=cache_key) - serialized_payload: str = compact_contents.partition("\n")[2] - assert compact_contents == stored_analysis_contents( - context=projected_context, cache_key=cache_key - ) - assert serialized_payload == json.dumps( - json.loads(serialized_payload), ensure_ascii=False, separators=(",", ":"), sort_keys=True - ) - analyses, _, _ = read_model_analyses( - context=compact_context, - cache_keys=(cache_key,), - model_names=(), - upstream_model_names_by_key={cache_key: ()}, - ) - assert tuple(analyses[cache_key].lineage_columns) == tuple(compact) - assert len(analyses[cache_key].lineage_columns) == test_case.expected_lineage_columns - - -@pytest.mark.parametrize( - "test_case", - (AnalysisCacheTestCase(description="stable per-model digests", expected_count=1),), - ids=lambda case: case.description, -) -def test_given_model_payload_when_digesting_then_fast_digest_matches_stable_encoding( - test_case: AnalysisCacheTestCase, -) -> None: - payload: dict[str, object] = { - "query_sql": "SELECT \"caf\u00e9\" AS name, '\\n\t\x01\u2028' AS note", - "references": [{"kind": "ref", "name": "orders", "package": None, "count": 2}], - "placeholders": {"b": "2", "a": "1"}, - "upstream": (("orders", "a" * 64),), - "binding_schema": None, - "has_star": False, - } - - digests: set[str] = { - analysis_cache._json_value_digest(payload), - analysis_cache._payload_digest(payload), - } - - assert len(digests) == test_case.expected_count - - -@pytest.mark.parametrize( - "test_case", - (AnalysisCacheTestCase(description="semantic cache identities", expected_count=7),), - ids=lambda case: case.description, -) -def test_given_analysis_inputs_when_building_keys_then_all_semantic_inputs_affect_identity( - test_case: AnalysisCacheTestCase, - tmp_path: Path, -) -> None: - base_context: AnalysisCacheContext | None = build_analysis_cache_context( - root=tmp_path, - inference_profile=ExpressionInferenceProfile(sql_analysis_dialect="duckdb"), - allow_compact_analysis=False, - ) - profile_context: AnalysisCacheContext | None = build_analysis_cache_context( - root=tmp_path, - inference_profile=ExpressionInferenceProfile(sql_analysis_dialect="snowflake"), - allow_compact_analysis=True, - ) - return_type_context: AnalysisCacheContext | None = build_analysis_cache_context( - root=tmp_path, - inference_profile=ExpressionInferenceProfile( - sql_analysis_dialect="duckdb", function_return_types={"TO_VARIANT": "VARIANT"} - ), - allow_compact_analysis=False, - ) - assert base_context is not None - assert profile_context is not None - assert return_type_context is not None - reference: CompileSqlReference = CompileSqlReference( - ref_kind=SqlReferenceKind.SOURCE, - ref_name="raw_orders", - call_argument_count=1, - ) - changed_reference: CompileSqlReference = CompileSqlReference( - ref_kind=SqlReferenceKind.SOURCE, - ref_name="raw_customers", - call_argument_count=1, - ) - base_key: str = model_analysis_cache_key( - context=base_context, - query_sql="SELECT 1", - references=(reference,), - placeholders=None, - column_nullability_by_table={}, - column_types_by_table={}, - ) - - changed_keys: tuple[str, ...] = ( - model_analysis_cache_key( - context=base_context, - query_sql="SELECT 2", - references=(reference,), - placeholders=None, - column_nullability_by_table={}, - column_types_by_table={}, - ), - model_analysis_cache_key( - context=base_context, - query_sql="SELECT 1", - references=(changed_reference,), - placeholders=None, - column_nullability_by_table={}, - column_types_by_table={}, - ), - model_analysis_cache_key( - context=base_context, - query_sql="SELECT 1", - references=(reference,), - placeholders={"value": "1"}, - column_nullability_by_table={}, - column_types_by_table={}, - ), - model_analysis_cache_key( - context=base_context, - query_sql="SELECT 1", - references=(reference,), - placeholders=None, - column_nullability_by_table={"raw_orders": {"order_id": InferredNullability.NON_NULL}}, - column_types_by_table={}, - ), - model_analysis_cache_key( - context=profile_context, - query_sql="SELECT 1", - references=(reference,), - placeholders=None, - column_nullability_by_table={}, - column_types_by_table={}, - ), - model_analysis_cache_key( - context=return_type_context, - query_sql="SELECT 1", - references=(reference,), - placeholders=None, - column_nullability_by_table={}, - column_types_by_table={}, - ), - model_analysis_cache_key( - context=base_context, - query_sql="SELECT 1", - references=(reference,), - placeholders=None, - column_nullability_by_table={}, - column_types_by_table={}, - recover_cte_facts=True, - ), - ) - unrelated_schema_key: str = model_analysis_cache_key( - context=base_context, - query_sql="SELECT 1", - references=(reference,), - placeholders=None, - column_nullability_by_table={"unrelated": {"order_id": InferredNullability.NON_NULL}}, - column_types_by_table={}, - ) - - assert len(changed_keys) == test_case.expected_count - assert all(changed_key != base_key for changed_key in changed_keys) - assert unrelated_schema_key == base_key - - -@pytest.mark.parametrize( - "test_case", - (AnalysisCacheTestCase(description="propagated schema invalidation", expected_count=4),), - ids=lambda case: case.description, -) -def test_given_schema_change_when_compiling_then_affected_consumers_miss_cache( - test_case: AnalysisCacheTestCase, - tmp_path: Path, - monkeypatch: pytest.MonkeyPatch, - write_repo_files: Callable[[Path, dict[str, str]], None], -) -> None: - write_repo_files( - tmp_path, - { - **_SELECTION_REPO_FILES, - "models/root.sql": "MODEL (description 'Test model root.');\n\nSELECT CAST(NULL AS INTEGER) AS id\n", - }, - ) - _ = compile_project_with_cache(project_dir=tmp_path) - analyzer: Mock = Mock(wraps=assembly_project.analyze_columns_and_lineage_with_polyglot) - monkeypatch.setattr(assembly_project, "analyze_columns_and_lineage_with_polyglot", analyzer) - unrelated_path: Path = tmp_path / "models" / "unrelated.sql" - unrelated_path.write_text( - unrelated_path.read_text(encoding="utf-8").replace( - "MODEL (description 'Test model unrelated.');", - "MODEL (description 'Test model unrelated.', columns (id (nullable false)));", - 1, - ), - encoding="utf-8", - ) - - _ = compile_project_with_cache(project_dir=tmp_path) - - analyzer.assert_not_called() - root_path: Path = tmp_path / "models" / "root.sql" - root_path.write_text( - root_path.read_text(encoding="utf-8").replace( - "MODEL (description 'Test model root.');", - "MODEL (description 'Test model root.', columns (id (nullable false)));", - 1, - ), - encoding="utf-8", - ) - - _ = compile_project_with_cache(project_dir=tmp_path) - - assert analyzer.call_count == test_case.expected_count - _ = compile_project_with_cache(project_dir=tmp_path) - assert analyzer.call_count == test_case.expected_count - - -@pytest.mark.parametrize( - "test_case", - (AnalysisCacheTestCase(description="stable exported signature", expected_count=1),), - ids=lambda case: case.description, -) -def test_given_model_sql_change_with_stable_signature_when_compiling_then_downstream_hits_cache( - test_case: AnalysisCacheTestCase, - tmp_path: Path, - monkeypatch: pytest.MonkeyPatch, - write_repo_files: Callable[[Path, dict[str, str]], None], -) -> None: - write_repo_files(tmp_path, _SELECTION_REPO_FILES) - _ = compile_project_with_cache(project_dir=tmp_path) - analyzer: Mock = Mock(wraps=assembly_project.analyze_columns_and_lineage_with_polyglot) - monkeypatch.setattr(assembly_project, "analyze_columns_and_lineage_with_polyglot", analyzer) - (tmp_path / "models" / "root.sql").write_text( - "MODEL (description 'Test model root.');\n\nSELECT 3 AS id\n", - encoding="utf-8", - ) - - _ = compile_project_with_cache(project_dir=tmp_path) - - assert analyzer.call_count == test_case.expected_count - - -@pytest.mark.parametrize( - "test_case", - (AnalysisCacheTestCase(description="changed exported signature", expected_count=5),), - ids=lambda case: case.description, -) -def test_given_model_output_change_when_compiling_then_downstream_closure_misses_cache( - test_case: AnalysisCacheTestCase, - tmp_path: Path, - monkeypatch: pytest.MonkeyPatch, - write_repo_files: Callable[[Path, dict[str, str]], None], -) -> None: - write_repo_files(tmp_path, _SELECTION_REPO_FILES) - _ = compile_project_with_cache(project_dir=tmp_path) - analyzer: Mock = Mock(wraps=assembly_project.analyze_columns_and_lineage_with_polyglot) - monkeypatch.setattr(assembly_project, "analyze_columns_and_lineage_with_polyglot", analyzer) - (tmp_path / "models" / "root.sql").write_text( - "MODEL (description 'Test model root.');\n\nSELECT 1 AS id, 2 AS extra\n", - encoding="utf-8", - ) - - _ = compile_project_with_cache(project_dir=tmp_path) - - assert analyzer.call_count == test_case.expected_count - _ = compile_project_with_cache(project_dir=tmp_path) - assert analyzer.call_count == test_case.expected_count - - -@pytest.mark.parametrize( - "test_case", - (AnalysisCacheTestCase(description="parallel downstream invalidation", expected_count=2),), - ids=lambda case: case.description, -) -def test_given_changed_output_signature_when_reanalyzing_downstream_then_uses_dependency_ready_batches( - test_case: AnalysisCacheTestCase, - tmp_path: Path, - monkeypatch: pytest.MonkeyPatch, - write_repo_files: Callable[[Path, dict[str, str]], None], -) -> None: - write_repo_files(tmp_path, _SELECTION_REPO_FILES) - _ = compile_project_with_cache(project_dir=tmp_path) - root_path: Path = tmp_path / "models" / "root.sql" - original_sql: str = root_path.read_text(encoding="utf-8") - root_path.write_text( - "MODEL (description 'Test model root.');\n\nSELECT 1 AS id, 2 AS extra\n", encoding="utf-8" - ) - _ = compile_project_with_cache(project_dir=tmp_path) - batcher: Mock = Mock(wraps=assembly_project.analyze_queries_with_compact_polyglot_batch) - monkeypatch.setattr(assembly_project, "analyze_queries_with_compact_polyglot_batch", batcher) - root_path.write_text(original_sql, encoding="utf-8") - - _ = compile_project_with_cache(project_dir=tmp_path) - - assert batcher.call_count == test_case.expected_count - assert all(len(call.kwargs["query_sqls"]) == 1 for call in batcher.call_args_list) - - -@pytest.mark.parametrize( - "test_case", - (AnalysisCacheTestCase(description="restored exported signature", expected_count=4),), - ids=lambda case: case.description, -) -def test_given_cached_model_signature_is_restored_when_compiling_then_downstream_reanalyzes( - test_case: AnalysisCacheTestCase, - tmp_path: Path, - monkeypatch: pytest.MonkeyPatch, - write_repo_files: Callable[[Path, dict[str, str]], None], -) -> None: - write_repo_files(tmp_path, _SELECTION_REPO_FILES) - _ = compile_project_with_cache(project_dir=tmp_path) - root_path: Path = tmp_path / "models" / "root.sql" - original_sql: str = root_path.read_text(encoding="utf-8") - root_path.write_text( - "MODEL (description 'Test model root.');\n\nSELECT 1 AS id, 2 AS extra\n", encoding="utf-8" - ) - _ = compile_project_with_cache(project_dir=tmp_path) - analyzer: Mock = Mock(wraps=assembly_project.analyze_columns_and_lineage_with_polyglot) - monkeypatch.setattr(assembly_project, "analyze_columns_and_lineage_with_polyglot", analyzer) - root_path.write_text(original_sql, encoding="utf-8") - - _ = compile_project_with_cache(project_dir=tmp_path) - - assert analyzer.call_count == test_case.expected_count - - -@pytest.mark.parametrize( - "test_case", - (AnalysisCacheTestCase(description="selected upstream change", expected_count=4),), - ids=lambda case: case.description, -) -def test_given_selected_upstream_change_when_compiling_full_project_then_stale_consumer_misses( - test_case: AnalysisCacheTestCase, - tmp_path: Path, - monkeypatch: pytest.MonkeyPatch, - write_repo_files: Callable[[Path, dict[str, str]], None], -) -> None: - write_repo_files( - tmp_path, - { - **_SELECTION_REPO_FILES, - "models/middle.sql": 'MODEL (description "Test model middle.");\n\nSELECT * FROM __ref("root")\n', - "models/leaf.sql": 'MODEL (description "Test model leaf.");\n\nSELECT * FROM __ref("middle")\n', - }, - ) - _ = compile_project_with_cache(project_dir=tmp_path) - (tmp_path / "models" / "root.sql").write_text( - "MODEL (description 'Test model root.');\n\nSELECT 1 AS id, 2 AS extra\n", - encoding="utf-8", - ) - _ = compile_project_with_cache( - project_dir=tmp_path, - analysis_selection=CompileAnalysisSelection(select=("root",)), - ) - analyzer: Mock = Mock(wraps=assembly_project.analyze_columns_and_lineage_with_polyglot) - monkeypatch.setattr(assembly_project, "analyze_columns_and_lineage_with_polyglot", analyzer) - - _ = compile_project_with_cache(project_dir=tmp_path) - - assert analyzer.call_count == test_case.expected_count - - -@pytest.mark.parametrize( - "test_case", - (AnalysisCacheTestCase(description="compact upstream interface change", expected_count=4),), - ids=lambda case: case.description, -) -def test_given_upstream_interface_change_when_compact_batch_exists_then_dependents_reanalyze( - test_case: AnalysisCacheTestCase, - tmp_path: Path, - monkeypatch: pytest.MonkeyPatch, - write_repo_files: Callable[[Path, dict[str, str]], None], -) -> None: - write_repo_files( - tmp_path, - { - **_SELECTION_REPO_FILES, - "models/middle.sql": 'MODEL (description "Test model middle.");\n\nSELECT * FROM __ref("root")\n', - "models/leaf.sql": 'MODEL (description "Test model leaf.");\n\nSELECT * FROM __ref("middle")\n', - }, - ) - monkeypatch.setattr(assembly_project, "_COMPACT_BATCH_CACHE_MIN_MODEL_COUNT", 1) - _ = compile_project_with_cache(project_dir=tmp_path) - (tmp_path / "models" / "root.sql").write_text( - "MODEL (description 'Test model root.');\n\nSELECT 1 AS id, 2 AS extra\n", - encoding="utf-8", - ) - - with collect_compile_timings() as metrics: - changed_project: CompiledProject = compile_project_with_cache(project_dir=tmp_path) - expected_project: CompiledProject = compile_project_with_cache( - project_dir=tmp_path, - no_cache=True, - ) - - models_by_name: dict[str, CompiledModel] = { - model.name: model for model in changed_project.models - } - expected_models_by_name: dict[str, CompiledModel] = { - model.name: model for model in expected_project.models - } - assert ( - models_by_name["root"].inferred_columns == expected_models_by_name["root"].inferred_columns - ) - assert models_by_name["middle"].inferred_columns == ( - expected_models_by_name["middle"].inferred_columns - ) - assert ( - models_by_name["leaf"].inferred_columns == expected_models_by_name["leaf"].inferred_columns - ) - recorded: dict[str, int] = metrics.as_milliseconds() - assert ( - sum( - recorded[name] - for name in ( - "analysis_batch_cache_hits", - "analysis_entry_cache_hits", - "analysis_cache_misses", - ) - ) - == test_case.expected_count - ) - assert recorded["analysis_batch_cache_hits"] == 1 - assert recorded["analysis_entry_cache_hits"] == 2 - assert recorded["analysis_cache_misses"] == 1 - - -@pytest.mark.parametrize( - "test_case", - (AnalysisCacheTestCase(description="selected upstream analysis", expected_count=3),), - ids=lambda case: case.description, -) -def test_given_partial_selection_when_compiling_then_analyzes_only_upstream_closure( - test_case: AnalysisCacheTestCase, - tmp_path: Path, - monkeypatch: pytest.MonkeyPatch, - write_repo_files: Callable[[Path, dict[str, str]], None], -) -> None: - write_repo_files(tmp_path, _SELECTION_REPO_FILES) - analyzer: Mock = Mock(wraps=assembly_project.analyze_columns_and_lineage_with_polyglot) - monkeypatch.setattr(assembly_project, "analyze_columns_and_lineage_with_polyglot", analyzer) - - project: CompiledProject = compile_project_with_cache( - project_dir=tmp_path, - analysis_selection=CompileAnalysisSelection(select=("middle",)), - ) - - inferred_by_name: dict[str, bool] = { - model.name: model.inferred_columns is not None for model in project.models - } - assert analyzer.call_count == test_case.expected_count - assert inferred_by_name == { - "leaf": False, - "middle": True, - "root": True, - "unrelated": False, - } - full_project: CompiledProject = compile_project_with_cache(project_dir=tmp_path) - full_models_by_name: dict[str, CompiledModel] = { - model.name: model for model in full_project.models - } - selected_models_by_name: dict[str, CompiledModel] = { - model.name: model for model in project.models - } - assert selected_models_by_name["root"] == full_models_by_name["root"] - assert selected_models_by_name["middle"] == full_models_by_name["middle"] - - -@pytest.mark.parametrize( - "test_case", - (AnalysisCacheTestCase(description="unselected invalid reference", expected_count=0),), - ids=lambda case: case.description, -) -def test_given_unselected_invalid_reference_when_compiling_then_live_validation_still_fails( - test_case: AnalysisCacheTestCase, - tmp_path: Path, - write_repo_files: Callable[[Path, dict[str, str]], None], -) -> None: - repo_files: dict[str, str] = _SELECTION_REPO_FILES | { - "models/unrelated.sql": 'MODEL (description "Test model unrelated.");\n\nSELECT id FROM __ref("missing")\n' - } - write_repo_files(tmp_path, repo_files) - - with pytest.raises(CompileInputError, match="references unknown model"): - _ = compile_project_with_cache( - project_dir=tmp_path, - analysis_selection=CompileAnalysisSelection(select=("middle",)), - ) - - assert len(tuple((tmp_path / "target").rglob("*.sqlite3"))) == test_case.expected_count - - -@pytest.mark.parametrize( - "test_case", - (AnalysisCacheTestCase(description="explicit cache bypass", expected_count=4),), - ids=lambda case: case.description, -) -def test_given_compile_cache_bypass_when_compiling_twice_then_both_runs_analyze_cold( - test_case: AnalysisCacheTestCase, - tmp_path: Path, - monkeypatch: pytest.MonkeyPatch, - write_repo_files: Callable[[Path, dict[str, str]], None], -) -> None: - write_repo_files(tmp_path, _CACHE_REPO_FILES) - monkeypatch.setenv(COMPILE_CACHE_DISABLE_ENV_VAR, "1") - analyzer: Mock = Mock(wraps=assembly_project.analyze_columns_and_lineage_with_polyglot) - monkeypatch.setattr(assembly_project, "analyze_columns_and_lineage_with_polyglot", analyzer) - batch_plan_spy: Mock = Mock(wraps=assembly_project.build_compact_analysis_cache_plan) - monkeypatch.setattr( - assembly_project, - "build_compact_analysis_cache_plan", - batch_plan_spy, - ) - - _ = compile_project_with_cache(project_dir=tmp_path) - with collect_compile_timings() as metrics: - _ = compile_project_with_cache(project_dir=tmp_path) - - assert analyzer.call_count == test_case.expected_count - assert batch_plan_spy.call_count == 0 - assert not tuple((tmp_path / "target").rglob("*.sqlite3")) - recorded: dict[str, int] = metrics.as_milliseconds() - assert recorded["analysis_batch_cache_hits"] == 0 - assert recorded["analysis_entry_cache_hits"] == 0 - assert recorded["analysis_cache_misses"] == 0 - assert recorded["analysis_cache_bypasses"] == 1 - - -@pytest.mark.parametrize( - "test_case", - (AnalysisCacheTestCase(description="command cache bypass", expected_count=4),), - ids=lambda case: case.description, -) -def test_given_command_cache_bypass_when_compiling_twice_then_both_runs_analyze_cold( - test_case: AnalysisCacheTestCase, - tmp_path: Path, - monkeypatch: pytest.MonkeyPatch, - write_repo_files: Callable[[Path, dict[str, str]], None], -) -> None: - write_repo_files(tmp_path, _CACHE_REPO_FILES) - analyzer: Mock = Mock(wraps=assembly_project.analyze_columns_and_lineage_with_polyglot) - monkeypatch.setattr(assembly_project, "analyze_columns_and_lineage_with_polyglot", analyzer) - _ = compile_project_with_cache(project_dir=tmp_path, no_cache=True) - _ = compile_project_with_cache(project_dir=tmp_path, no_cache=True) - - assert analyzer.call_count == test_case.expected_count - assert not tuple((tmp_path / "target").rglob("*.sqlite3")) - - -@pytest.mark.parametrize( - "test_case", - (AnalysisCacheTestCase(description="target cache bypass", expected_count=4),), - ids=lambda case: case.description, -) -def test_given_target_cache_disabled_when_compiling_twice_then_both_runs_analyze_cold( - test_case: AnalysisCacheTestCase, - tmp_path: Path, - monkeypatch: pytest.MonkeyPatch, - write_repo_files: Callable[[Path, dict[str, str]], None], -) -> None: - write_repo_files( - tmp_path, - { - **_CACHE_REPO_FILES, - "sqlbuild_project.toml": """ -name = "cache_demo" -adapter = "duckdb" -default_target = "prod" - -[targets.prod] -compile_cache = false -""".strip() - + "\n", - }, - ) - analyzer: Mock = Mock(wraps=assembly_project.analyze_columns_and_lineage_with_polyglot) - monkeypatch.setattr(assembly_project, "analyze_columns_and_lineage_with_polyglot", analyzer) - - _ = compile_project_with_cache(project_dir=tmp_path) - _ = compile_project_with_cache(project_dir=tmp_path) - - assert analyzer.call_count == test_case.expected_count - assert not tuple((tmp_path / "target").rglob("*.sqlite3")) diff --git a/tests/unit/src/sqlbuild/compiler/compile/_helpers/test_deps.py b/tests/unit/src/sqlbuild/compiler/compile/_helpers/test_deps.py deleted file mode 100644 index 749109ef72..0000000000 --- a/tests/unit/src/sqlbuild/compiler/compile/_helpers/test_deps.py +++ /dev/null @@ -1,152 +0,0 @@ -from __future__ import annotations - -import pytest - -from sqlbuild.compiler.compile._helpers.deps.dependencies import ( - audit_scope_deps, - model_build_deps, - sql_test_scope_deps, -) -from sqlbuild.compiler.compile.models import ( - CompiledObjectKey, - CompileSqlReference, -) -from sqlbuild.compiler.compile.types import CompiledResourceType -from sqlbuild.compiler.references.types import SqlReferenceKind -from tests.unit.src.sqlbuild.compiler.compile._helpers._test_types import ( - AuditScopeDepsTestCase, - ModelBuildDepsTestCase, - SqlTestScopeDepsTestCase, -) - - -@pytest.mark.parametrize( - "test_case", - [ - ModelBuildDepsTestCase( - description="maps model source and dbt references to typed build deps", - references=( - CompileSqlReference(ref_kind=SqlReferenceKind.REF, ref_name="stg_orders"), - CompileSqlReference(ref_kind=SqlReferenceKind.SOURCE, ref_name="raw_orders"), - CompileSqlReference(ref_kind=SqlReferenceKind.DBT_REF, ref_name="dbt_customers"), - CompileSqlReference( - ref_kind=SqlReferenceKind.TABLE_FUNCTION, - ref_name="customer_orders", - ), - ), - expected_deps=( - CompiledObjectKey(resource_type=CompiledResourceType.MODEL, name="stg_orders"), - CompiledObjectKey(resource_type=CompiledResourceType.SOURCE, name="raw_orders"), - CompiledObjectKey(resource_type=CompiledResourceType.DBT_REF, name="dbt_customers"), - CompiledObjectKey( - resource_type=CompiledResourceType.TABLE_FN, - name="customer_orders", - ), - ), - ), - ModelBuildDepsTestCase( - description="dedupes repeated model deps while preserving first seen order", - references=( - CompileSqlReference(ref_kind=SqlReferenceKind.REF, ref_name="stg_orders"), - CompileSqlReference(ref_kind=SqlReferenceKind.SOURCE, ref_name="raw_orders"), - CompileSqlReference(ref_kind=SqlReferenceKind.REF, ref_name="stg_orders"), - ), - expected_deps=( - CompiledObjectKey(resource_type=CompiledResourceType.MODEL, name="stg_orders"), - CompiledObjectKey(resource_type=CompiledResourceType.SOURCE, name="raw_orders"), - ), - ), - ModelBuildDepsTestCase( - description="seed reference produces a SEED typed dep key", - references=( - CompileSqlReference(ref_kind=SqlReferenceKind.REF, ref_name="stg_orders"), - CompileSqlReference(ref_kind=SqlReferenceKind.SEED, ref_name="waffle_types"), - ), - expected_deps=( - CompiledObjectKey(resource_type=CompiledResourceType.MODEL, name="stg_orders"), - CompiledObjectKey(resource_type=CompiledResourceType.SEED, name="waffle_types"), - ), - ), - ], - ids=lambda case: case.description, -) -def test_given_sql_references_when_deriving_model_build_deps_then_returns_typed_object_keys( - test_case: ModelBuildDepsTestCase, -) -> None: - deps: tuple[CompiledObjectKey, ...] = model_build_deps( - references=test_case.references, seed_names=test_case.seed_names - ) - - assert deps == test_case.expected_deps - - -@pytest.mark.parametrize( - "test_case", - [ - AuditScopeDepsTestCase( - description="combines audit references with attached model target", - references=( - CompileSqlReference(ref_kind=SqlReferenceKind.SOURCE, ref_name="raw_orders"), - ), - attached_target_kind="model", - attached_target_name="orders", - expected_scope_deps=( - CompiledObjectKey(resource_type=CompiledResourceType.SOURCE, name="raw_orders"), - CompiledObjectKey(resource_type=CompiledResourceType.MODEL, name="orders"), - ), - ), - AuditScopeDepsTestCase( - description="dedupes attached source target already present in refs", - references=( - CompileSqlReference(ref_kind=SqlReferenceKind.SOURCE, ref_name="raw_orders"), - ), - attached_target_kind="source", - attached_target_name="raw_orders", - expected_scope_deps=( - CompiledObjectKey(resource_type=CompiledResourceType.SOURCE, name="raw_orders"), - ), - ), - ], - ids=lambda case: case.description, -) -def test_given_audit_refs_and_target_when_deriving_scope_deps_then_returns_scope_keys( - test_case: AuditScopeDepsTestCase, -) -> None: - deps: tuple[CompiledObjectKey, ...] = audit_scope_deps( - references=test_case.references, - attached_target_kind=test_case.attached_target_kind, - attached_target_name=test_case.attached_target_name, - ) - - assert deps == test_case.expected_scope_deps - - -@pytest.mark.parametrize( - "test_case", - [ - SqlTestScopeDepsTestCase( - description="uses expected models as sql test scope deps", - expected_model_names=("orders", "daily_revenue"), - expected_scope_deps=( - CompiledObjectKey(resource_type=CompiledResourceType.MODEL, name="orders"), - CompiledObjectKey(resource_type=CompiledResourceType.MODEL, name="daily_revenue"), - ), - ), - SqlTestScopeDepsTestCase( - description="dedupes repeated expected model names", - expected_model_names=("orders", "orders"), - expected_scope_deps=( - CompiledObjectKey(resource_type=CompiledResourceType.MODEL, name="orders"), - ), - ), - ], - ids=lambda case: case.description, -) -def test_given_expected_models_when_deriving_sql_test_scope_deps_then_returns_model_keys( - test_case: SqlTestScopeDepsTestCase, -) -> None: - deps: tuple[CompiledObjectKey, ...] = sql_test_scope_deps( - expected_model_names=test_case.expected_model_names - ) - - assert deps == test_case.expected_scope_deps diff --git a/tests/unit/src/sqlbuild/compiler/compile/_helpers/test_sql_analysis_columns.py b/tests/unit/src/sqlbuild/compiler/compile/_helpers/test_sql_analysis_columns.py index 93fa1ead40..9b54407c9e 100644 --- a/tests/unit/src/sqlbuild/compiler/compile/_helpers/test_sql_analysis_columns.py +++ b/tests/unit/src/sqlbuild/compiler/compile/_helpers/test_sql_analysis_columns.py @@ -1,30 +1,20 @@ from __future__ import annotations -import json -from typing import cast -from unittest.mock import Mock - import pytest -from polyglot_sql import ParseError from sqlbuild.adapter.contract.models import ExpressionInferenceProfile -from sqlbuild.compiler.compile._helpers.analysis import columns as analysis_columns -from sqlbuild.compiler.compile._helpers.analysis.columns import ( - import_polyglot_sql, - substitute_placeholder_defaults, +from sqlbuild.compiler.analysis_session.main._infer_native_query_columns import ( + infer_native_query_columns, ) -from sqlbuild.compiler.compile._helpers.analysis.compact import ( - analyze_columns_and_lineage_with_polyglot, - analyze_queries_with_compact_polyglot_batch, - infer_columns_with_sql_analysis, +from sqlbuild.compiler.analysis_session.models import NativeColumnQuery, NativeQueryColumns +from sqlbuild.compiler.compile._helpers.analysis.reference_names import ( + substitute_placeholder_defaults, ) from sqlbuild.compiler.compile.models import ( CompiledLineageColumnFact, CompiledLineageSourceFact, CompileSqlReference, InferredColumn, - NativeCompactAnalysis, - PolyglotAnalysisResult, ) from sqlbuild.compiler.compile.types import CompiledResourceType from sqlbuild.compiler.lineage.types import ( @@ -34,500 +24,14 @@ ) from sqlbuild.compiler.references.types import SqlReferenceKind from tests.unit.src.sqlbuild.compiler.compile._helpers._test_types import ( - ExpectedCountTestCase, InferColumnsTestCase, - NativeTypeInferenceModeTestCase, PolyglotAnalysisTestCase, - QualifiedReferenceAnalysisTestCase, - QualifiedReferenceScanTestCase, SubstitutePlaceholderDefaultsTestCase, - UnexpectedAnalysisFailureTestCase, -) -from tests.unit.src.sqlbuild.compiler.compile._helpers.helpers import direct_orders_lineage - - -@pytest.mark.parametrize( - "test_case", - [ExpectedCountTestCase(description="native request remains batched", expected_count=1)], - ids=lambda case: case.description, -) -def test_given_queries_when_batch_analyzing_then_uses_one_ordered_native_request( - monkeypatch: pytest.MonkeyPatch, - test_case: ExpectedCountTestCase, -) -> None: - captured: list[dict[str, object]] = [] - - def analyze_project_queries_compact_json(request_json: str) -> str: - request: dict[str, object] = json.loads(request_json) - captured.append(request) - return json.dumps( - { - "strings": [ - "order_id", - "BIGINT", - "model", - "__sqlbuild_project_input_0", - "orders", - ], - "facts": [[0, 1, 1, 0, 1, [[2, 3, 0]]]], - "templates": [ - [[0], False], - "invalid query", - ], - "analyses": [ - [0, [[3, 4]]], - [1, []], - ], - } - ) - - monkeypatch.setattr( - "sqlbuild.compiler.compile._helpers.analysis.compact._native.analyze_project_queries_compact_json", - analyze_project_queries_compact_json, - raising=False, - ) - - results: tuple[NativeCompactAnalysis, ...] = analyze_queries_with_compact_polyglot_batch( - query_sqls=( - 'SELECT order_id FROM __ref("orders")', - "SELECT @@@status AS status", - ), - references=( - (CompileSqlReference(ref_kind=SqlReferenceKind.REF, ref_name="orders"),), - (), - ), - placeholders=(None, {"status": "'ready'"}), - column_nullability_by_table={"orders": {"order_id": InferredNullability.NON_NULL}}, - column_types_by_table={"orders": {"order_id": "BIGINT"}}, - inference_profile=ExpressionInferenceProfile(sql_analysis_dialect="duckdb"), - recover_cte_facts=(False, False), - ) - - assert len(captured) == test_case.expected_count - native_queries: list[dict[str, object]] = cast(list[dict[str, object]], captured[0]["queries"]) - native_templates: list[dict[str, object]] = cast( - list[dict[str, object]], captured[0]["templates"] - ) - native_projections: list[dict[str, object]] = cast( - list[dict[str, object]], captured[0]["projections"] - ) - assert len(native_queries) == 2 - assert "__ref" not in str(native_queries[0]["sql"]) - assert "__sqlbuild_project_input_0" in str(native_queries[0]["sql"]) - assert native_queries[1]["sql"] == "SELECT 'ready' AS status" - assert native_templates[0]["references"] == { - "__sqlbuild_project_input_0": { - "resourceType": "model", - "resourceName": "__sqlbuild_project_input_0", - } - } - assert native_projections[0]["resourceNames"] == {"__sqlbuild_project_input_0": "orders"} - assert native_queries[0]["schema"] == { - "tables": [ - { - "name": "__sqlbuild_project_input_0", - "columns": [{"name": "order_id", "type": "BIGINT", "nullable": False}], - } - ] - } - - assert "orders" in results[0].cleaned_sql - assert results[0].analysis == {"hasStar": False, "starResolved": False} - assert results[0].compact_rows == [0] - assert results[1].analysis is None - assert results[1].projected is True - projected_analysis: PolyglotAnalysisResult = analyze_columns_and_lineage_with_polyglot( - query_sql='SELECT order_id FROM __ref("orders")', - allow_compact_analysis=True, - precomputed=results[0], - ) - assert projected_analysis.columns == ( - InferredColumn( - name="order_id", - type="BIGINT", - nullability=InferredNullability.NON_NULL, - ), - ) - assert tuple(projected_analysis.lineage_columns) == ( - CompiledLineageColumnFact( - output_column="order_id", - upstream_columns=( - CompiledLineageSourceFact( - resource_type=CompiledResourceType.MODEL, - resource_name="orders", - column_name="order_id", - ), - ), - transform_kind=ColumnTransformKind.DIRECT, - confidence=ColumnLineageConfidence.HIGH, - ), - ) - monkeypatch.setattr( - "sqlbuild.compiler.compile._helpers.analysis.compact.import_polyglot_sql", - Mock(side_effect=AssertionError("native failures must not trigger Python reparsing")), - ) - - failed_analysis: PolyglotAnalysisResult = analyze_columns_and_lineage_with_polyglot( - query_sql="SELECT FROM", - allow_compact_analysis=True, - precomputed=results[1], - ) - - assert failed_analysis.analysis_succeeded is False - - -@pytest.mark.parametrize( - "test_case", - ( - InferColumnsTestCase( - description="cast expression overrides input type through CTE", - query_sql='WITH typed AS (SELECT COALESCE(CAST(amount AS FLOAT), CAST(0 AS FLOAT)) AS amount FROM __ref("orders")) SELECT amount FROM typed', - expected_columns=( - InferredColumn( - name="amount", type="FLOAT", nullability=InferredNullability.NON_NULL - ), - ), - ), - ), - ids=lambda case: case.description, -) -def test_given_cte_cast_when_batch_analyzing_then_cast_type_overrides_input_type( - test_case: InferColumnsTestCase, -) -> None: - query_sql: str = test_case.query_sql - references: tuple[CompileSqlReference, ...] = ( - CompileSqlReference(ref_kind=SqlReferenceKind.REF, ref_name="orders"), - ) - nullability: dict[str, dict[str, InferredNullability]] = { - "orders": {"amount": InferredNullability.NULLABLE} - } - types: dict[str, dict[str, str]] = {"orders": {"amount": "VARCHAR"}} - profile: ExpressionInferenceProfile = ExpressionInferenceProfile( - sql_analysis_dialect="snowflake" - ) - - prepared: NativeCompactAnalysis = analyze_queries_with_compact_polyglot_batch( - query_sqls=(query_sql,), - references=(references,), - placeholders=(None,), - column_nullability_by_table=nullability, - column_types_by_table=types, - inference_profile=profile, - recover_cte_facts=(True,), - rich_type_inference=False, - )[0] - result: PolyglotAnalysisResult = analyze_columns_and_lineage_with_polyglot( - query_sql=query_sql, - references=references, - column_nullability_by_table=nullability, - column_types_by_table=types, - inference_profile=profile, - allow_compact_analysis=True, - recover_cte_facts=True, - precomputed=prepared, - ) - - assert result.analysis_succeeded - assert result.columns == test_case.expected_columns - - -@pytest.mark.parametrize( - "test_case", - ( - InferColumnsTestCase( - description="lowercase authored stub-named CTE", - query_sql=( - "WITH __sqlbuild_project_input_0 AS (SELECT 'pending' AS order_id) " - 'SELECT order_id FROM __ref("orders")' - ), - expected_columns=( - InferredColumn( - name="order_id", type="BIGINT", nullability=InferredNullability.NON_NULL - ), - ), - ), - InferColumnsTestCase( - description="uppercase authored stub-named CTE", - query_sql=( - "WITH __SQLBUILD_PROJECT_INPUT_0 AS (SELECT 'pending' AS order_id) " - 'SELECT order_id FROM __ref("orders")' - ), - expected_columns=( - InferredColumn( - name="order_id", type="BIGINT", nullability=InferredNullability.NON_NULL - ), - ), - ), - ), - ids=lambda case: case.description, -) -def test_given_authored_stub_named_cte_when_batch_analyzing_without_binding_then_uses_input( - test_case: InferColumnsTestCase, -) -> None: - references: tuple[CompileSqlReference, ...] = ( - CompileSqlReference(ref_kind=SqlReferenceKind.REF, ref_name="orders"), - ) - nullability: dict[str, dict[str, InferredNullability]] = { - "orders": {"order_id": InferredNullability.NON_NULL} - } - types: dict[str, dict[str, str]] = {"orders": {"order_id": "BIGINT"}} - profile: ExpressionInferenceProfile = ExpressionInferenceProfile(sql_analysis_dialect="duckdb") - - prepared: NativeCompactAnalysis = analyze_queries_with_compact_polyglot_batch( - query_sqls=(test_case.query_sql,), - references=(references,), - placeholders=(None,), - column_nullability_by_table=nullability, - column_types_by_table=types, - inference_profile=profile, - recover_cte_facts=(False,), - )[0] - result: PolyglotAnalysisResult = analyze_columns_and_lineage_with_polyglot( - query_sql=test_case.query_sql, - references=references, - column_nullability_by_table=nullability, - column_types_by_table=types, - inference_profile=profile, - allow_compact_analysis=True, - precomputed=prepared, - ) - - assert result.analysis_succeeded - assert result.columns == test_case.expected_columns - lineage_column: CompiledLineageColumnFact = tuple(result.lineage_columns)[0] - assert [source.resource_name for source in lineage_column.upstream_columns] == ["orders"] - - -@pytest.mark.parametrize( - "test_case", - [ - QualifiedReferenceAnalysisTestCase( - description="plain qualified reference", - query_sql='SELECT orders.order_id FROM __ref("orders")', - ), - QualifiedReferenceAnalysisTestCase( - description="commented qualified reference", - query_sql='SELECT orders /* column qualifier */ .order_id FROM __ref("orders")', - ), - ], - ids=lambda case: case.description, -) -def test_given_qualified_reference_when_batch_analyzing_then_preserves_analysis_facts( - test_case: QualifiedReferenceAnalysisTestCase, -) -> None: - references: tuple[CompileSqlReference, ...] = ( - CompileSqlReference(ref_kind=SqlReferenceKind.REF, ref_name="orders"), - ) - nullability: dict[str, dict[str, InferredNullability]] = { - "orders": {"order_id": InferredNullability.NON_NULL} - } - types: dict[str, dict[str, str]] = {"orders": {"order_id": "BIGINT"}} - profile: ExpressionInferenceProfile = ExpressionInferenceProfile(sql_analysis_dialect="duckdb") - expected: PolyglotAnalysisResult = analyze_columns_and_lineage_with_polyglot( - query_sql=test_case.query_sql, - references=references, - placeholders=None, - column_nullability_by_table=nullability, - column_types_by_table=types, - inference_profile=profile, - allow_compact_analysis=True, - ) - prepared: NativeCompactAnalysis = analyze_queries_with_compact_polyglot_batch( - query_sqls=(test_case.query_sql,), - references=(references,), - placeholders=(None,), - column_nullability_by_table=nullability, - column_types_by_table=types, - inference_profile=profile, - recover_cte_facts=(False,), - )[0] - - actual: PolyglotAnalysisResult = analyze_columns_and_lineage_with_polyglot( - query_sql=test_case.query_sql, - references=references, - placeholders=None, - column_nullability_by_table=nullability, - column_types_by_table=types, - inference_profile=profile, - allow_compact_analysis=True, - precomputed=prepared, - ) - - assert (actual.columns == expected.columns) is test_case.expected_matches - assert tuple(actual.lineage_columns) == expected.lineage_columns - - -@pytest.mark.parametrize( - "test_case", - (ExpectedCountTestCase(description="unqualified SQL skips scanner", expected_count=0),), - ids=lambda case: case.description, -) -def test_given_sql_without_dots_when_finding_qualified_references_then_skips_scanner( - monkeypatch: pytest.MonkeyPatch, - test_case: ExpectedCountTestCase, -) -> None: - scanner: Mock = Mock() - monkeypatch.setattr(analysis_columns, "_QUALIFIED_IDENTIFIER_PATTERN", scanner) - - result: frozenset[str] = analysis_columns._qualified_reference_names( - query_sql='SELECT order_id FROM __ref("orders")', - reference_names=("orders",), - ) - - assert result == frozenset() - assert scanner.finditer.call_count == test_case.expected_count - - -@pytest.mark.parametrize( - "test_case", - ( - QualifiedReferenceScanTestCase( - description="alias qualifier does not qualify the relation", - query_sql="SELECT input.id FROM orders AS input", - reference_names=("orders",), - expected_names=frozenset(), - ), - QualifiedReferenceScanTestCase( - description="relation qualifier matches case-insensitively", - query_sql="SELECT ORDERS . id FROM orders", - reference_names=("orders", "Orders"), - expected_names=frozenset({"orders", "Orders"}), - ), - QualifiedReferenceScanTestCase( - description="longer identifier sharing a prefix is not a qualifier", - query_sql="SELECT orders_archive.id, x.orders FROM orders_archive, orders AS x", - reference_names=("orders", "archive"), - expected_names=frozenset(), - ), - QualifiedReferenceScanTestCase( - description="dollar and digit identifier characters bound the name", - query_sql="SELECT $orders.id, orders$1.id, orders.id FROM t", - reference_names=("orders",), - expected_names=frozenset({"orders"}), - ), - QualifiedReferenceScanTestCase( - description="string literal text still counts like the regex scan", - query_sql="SELECT 'customers.id' AS note FROM orders", - reference_names=("orders", "customers"), - expected_names=frozenset({"customers"}), - ), - QualifiedReferenceScanTestCase( - description="comment between qualifier and separator", - query_sql="SELECT orders /* note */ .id -- customers.id\nFROM orders", - reference_names=("orders", "customers"), - expected_names=frozenset({"orders", "customers"}), - ), - QualifiedReferenceScanTestCase( - description="comment consumed by an earlier qualifier hides its contents", - query_sql="SELECT x /* customers. */ .id FROM orders AS x", - reference_names=("orders", "customers"), - expected_names=frozenset(), - ), - QualifiedReferenceScanTestCase( - description="quoted identifiers qualify by their unquoted name", - query_sql='SELECT "orders".id, `customers`.id, [products].id FROM t', - reference_names=("orders", "customers", "products"), - expected_names=frozenset({"orders", "customers", "products"}), - ), - QualifiedReferenceScanTestCase( - description="quoted identifier containing a dot is one name", - query_sql='SELECT "orders.v2".id FROM t', - reference_names=("orders",), - expected_names=frozenset(), - ), - QualifiedReferenceScanTestCase( - description="non-identifier reference names never qualify", - query_sql="SELECT order-lines.id FROM t", - reference_names=("order-lines", "lines"), - expected_names=frozenset({"lines"}), - ), - QualifiedReferenceScanTestCase( - description="non-ascii SQL uses the full scan", - query_sql="SELECT caf\u00e9.id, orders.id FROM t", - reference_names=("orders", "caf\u00e9"), - expected_names=frozenset({"orders"}), - ), - ), - ids=lambda case: case.description, ) -def test_given_reference_names_when_finding_qualified_references_then_matches_full_scan( - test_case: QualifiedReferenceScanTestCase, -) -> None: - names_by_normalized: dict[str, list[str]] = {} - for name in test_case.reference_names: - names_by_normalized.setdefault(name.casefold(), []).append(name) - - result: frozenset[str] = analysis_columns._qualified_reference_names( - query_sql=test_case.query_sql, reference_names=test_case.reference_names - ) - - assert result == test_case.expected_names - assert ( - analysis_columns._scanned_qualified_reference_names( - query_sql=test_case.query_sql, names_by_normalized=names_by_normalized - ) - == test_case.expected_names - ) - - -@pytest.mark.parametrize( - "test_case", - [ - NativeTypeInferenceModeTestCase( - description="direct input type remains unknown in fast mode", - query_sql='SELECT status FROM __ref("orders")', - column_types={"status": "VARCHAR"}, - expected_fast_types=(None,), - expected_rich_types=("TEXT",), - ), - NativeTypeInferenceModeTestCase( - description="aggregate hint remains unknown in fast mode", - query_sql='SELECT SUM(amount) AS total FROM __ref("orders")', - column_types={"amount": "INT"}, - expected_fast_types=(None,), - expected_rich_types=("INT128",), - ), - ], - ids=lambda case: case.description, +from tests.unit.src.sqlbuild.compiler.compile._helpers.helpers import ( + direct_orders_lineage, + reanalysed_columns, ) -def test_given_native_batch_when_selecting_type_mode_then_preserves_mode_contract( - test_case: NativeTypeInferenceModeTestCase, -) -> None: - references: tuple[CompileSqlReference, ...] = ( - CompileSqlReference(ref_kind=SqlReferenceKind.REF, ref_name="orders"), - ) - nullability: dict[str, dict[str, InferredNullability]] = { - "orders": {name: InferredNullability.NON_NULL for name in test_case.column_types} - } - profile: ExpressionInferenceProfile = ExpressionInferenceProfile(sql_analysis_dialect="duckdb") - - projected_types: list[tuple[str | None, ...]] = [] - for rich_type_inference in (False, True): - prepared: NativeCompactAnalysis = analyze_queries_with_compact_polyglot_batch( - query_sqls=(test_case.query_sql,), - references=(references,), - placeholders=(None,), - column_nullability_by_table=nullability, - column_types_by_table={"orders": test_case.column_types}, - inference_profile=profile, - recover_cte_facts=(False,), - rich_type_inference=rich_type_inference, - )[0] - result: PolyglotAnalysisResult = analyze_columns_and_lineage_with_polyglot( - query_sql=test_case.query_sql, - references=references, - column_nullability_by_table=nullability, - column_types_by_table={"orders": test_case.column_types}, - inference_profile=profile, - allow_compact_analysis=True, - precomputed=prepared, - ) - projected_types.append(tuple(column.type for column in result.columns or ())) - - assert tuple(projected_types) == ( - test_case.expected_fast_types, - test_case.expected_rich_types, - ) @pytest.mark.parametrize( @@ -999,11 +503,11 @@ def test_given_native_batch_when_selecting_type_mode_then_preserves_mode_contrac def test_given_query_sql_when_inferring_columns_then_returns_expected( test_case: InferColumnsTestCase, ) -> None: - result: tuple[InferredColumn, ...] | None = infer_columns_with_sql_analysis( - query_sql=test_case.query_sql, + result: tuple[InferredColumn, ...] | None = infer_native_query_columns( + queries=(NativeColumnQuery(sql=test_case.query_sql, mode="parse"),), + profile=test_case.inference_profile or ExpressionInferenceProfile(), column_nullability_by_table=test_case.column_nullability_by_table, - inference_profile=test_case.inference_profile, - ) + )[0].columns assert result == test_case.expected_columns @@ -1032,65 +536,6 @@ def test_given_query_sql_when_inferring_columns_then_returns_expected( ), expected_has_star=False, ), - PolyglotAnalysisTestCase( - description="refines a compact filtered column across whitespace", - query_sql=('SELECT order_id FROM __ref("orders") WHERE order_id IS\nNOT NULL'), - references=(CompileSqlReference(SqlReferenceKind.REF, "orders"),), - column_nullability_by_table={"orders": {"order_id": InferredNullability.NULLABLE}}, - column_types_by_table={"orders": {"order_id": "INTEGER"}}, - expected_columns=( - InferredColumn( - name="order_id", - type="INT", - nullability=InferredNullability.NON_NULL, - ), - ), - expected_lineage_columns=direct_orders_lineage("order_id"), - expected_has_star=False, - ), - PolyglotAnalysisTestCase( - description="refines a compact filtered outer join across a comment", - query_sql=( - 'SELECT c.customer_id FROM __ref("orders") AS o ' - 'LEFT JOIN __ref("customers") AS c ' - "ON o.order_id = c.customer_id " - "WHERE c.customer_id IS /* required customer */ NOT NULL" - ), - references=( - CompileSqlReference(SqlReferenceKind.REF, "orders"), - CompileSqlReference(SqlReferenceKind.REF, "customers"), - ), - column_nullability_by_table={ - "orders": {"order_id": InferredNullability.NON_NULL}, - "customers": {"customer_id": InferredNullability.NON_NULL}, - }, - column_types_by_table={ - "orders": {"order_id": "INTEGER"}, - "customers": {"customer_id": "INTEGER"}, - }, - expected_columns=( - InferredColumn( - name="customer_id", - type="INT", - nullability=InferredNullability.NON_NULL, - ), - ), - expected_lineage_columns=( - CompiledLineageColumnFact( - output_column="customer_id", - upstream_columns=( - CompiledLineageSourceFact( - resource_type=CompiledResourceType.MODEL, - resource_name="customers", - column_name="customer_id", - ), - ), - transform_kind=ColumnTransformKind.DIRECT, - confidence=ColumnLineageConfidence.HIGH, - ), - ), - expected_has_star=False, - ), PolyglotAnalysisTestCase( description="terminates direct lineage at a managed table function output", query_sql='SELECT order_id FROM __table_fn("customer_orders")(42)', @@ -1144,7 +589,7 @@ def test_given_query_sql_when_inferring_columns_then_returns_expected( def test_given_ref_query_when_analyzing_columns_and_lineage_then_returns_compact_facts( test_case: PolyglotAnalysisTestCase, ) -> None: - result: PolyglotAnalysisResult = analyze_columns_and_lineage_with_polyglot( + result: NativeQueryColumns = reanalysed_columns( query_sql=test_case.query_sql, references=test_case.references, column_nullability_by_table=test_case.column_nullability_by_table, @@ -1154,9 +599,8 @@ def test_given_ref_query_when_analyzing_columns_and_lineage_then_returns_compact recover_cte_facts=True, ) - assert result.analysis_succeeded + assert result.succeeded assert result.columns == test_case.expected_columns - assert result.lineage_columns == test_case.expected_lineage_columns assert result.has_star is test_case.expected_has_star @@ -1164,373 +608,23 @@ def test_given_ref_query_when_analyzing_columns_and_lineage_then_returns_compact "test_case", [ PolyglotAnalysisTestCase( - description="preserves fallback lineage for a commented qualified column", + description="does not reuse a source type through a transformed cte", query_sql=( - "SELECT orders.order_id,\n" - "-- Current order status.\n" - 'orders.status FROM __ref("orders") AS orders' + "WITH transformed AS (" + "SELECT amount || '0' AS amount FROM __ref(\"orders\")" + "), final AS (" + "SELECT amount FROM transformed" + ") SELECT amount FROM final" ), references=(CompileSqlReference(SqlReferenceKind.REF, "orders"),), - expected_columns=(InferredColumn(name="order_id"), InferredColumn(name="status")), - expected_lineage_columns=( - CompiledLineageColumnFact( - output_column="order_id", - upstream_columns=( - CompiledLineageSourceFact( - resource_type=CompiledResourceType.MODEL, - resource_name="orders", - column_name="order_id", - ), - ), - transform_kind=ColumnTransformKind.DIRECT, - confidence=ColumnLineageConfidence.HIGH, - ), - CompiledLineageColumnFact( - output_column="status", - upstream_columns=( - CompiledLineageSourceFact( - resource_type=CompiledResourceType.MODEL, - resource_name="orders", - column_name="status", - ), - ), - transform_kind=ColumnTransformKind.DIRECT, - confidence=ColumnLineageConfidence.HIGH, - ), - ), + column_nullability_by_table={"orders": {"amount": InferredNullability.UNKNOWN}}, + column_types_by_table={"orders": {"amount": "INTEGER"}}, + expected_columns=(InferredColumn(name="amount"),), + expected_lineage_columns=direct_orders_lineage("amount"), expected_has_star=False, ), PolyglotAnalysisTestCase( - description="preserves a final CTE cast after a values CTE on the AST fallback", - query_sql=( - "WITH labels(label) AS (VALUES ('web')), transformed AS (" - 'SELECT CAST(amount AS INTEGER) AS amount FROM __ref("orders")' - "), final AS (SELECT amount FROM transformed) SELECT amount FROM final" - ), - references=(CompileSqlReference(SqlReferenceKind.REF, "orders"),), - column_nullability_by_table={"orders": {"amount": InferredNullability.UNKNOWN}}, - column_types_by_table={"orders": {"amount": "VARCHAR"}}, - expected_columns=(InferredColumn(name="amount", type="INT"),), - expected_lineage_columns=( - CompiledLineageColumnFact( - output_column="amount", - upstream_columns=( - CompiledLineageSourceFact( - resource_type=CompiledResourceType.MODEL, - resource_name="orders", - column_name="amount", - ), - ), - transform_kind=ColumnTransformKind.DIRECT, - confidence=ColumnLineageConfidence.MEDIUM, - ), - ), - expected_has_star=False, - ), - ], - ids=lambda case: case.description, -) -def test_given_annotated_projection_when_using_ast_fallback_then_lineage_is_preserved( - test_case: PolyglotAnalysisTestCase, -) -> None: - result: PolyglotAnalysisResult = analyze_columns_and_lineage_with_polyglot( - query_sql=test_case.query_sql, - references=test_case.references, - column_nullability_by_table=test_case.column_nullability_by_table, - column_types_by_table=test_case.column_types_by_table, - allow_compact_analysis=False, - recover_cte_facts=True, - ) - - assert result.analysis_succeeded - assert result.columns == test_case.expected_columns - assert result.lineage_columns == test_case.expected_lineage_columns - assert result.has_star is test_case.expected_has_star - - -@pytest.mark.parametrize( - "test_case", - [ - PolyglotAnalysisTestCase( - description="uses compact query analysis before AST fallback", - query_sql='SELECT order_id FROM __ref("orders")', - references=(CompileSqlReference(SqlReferenceKind.REF, "orders"),), - expected_columns=(InferredColumn(name="order_id"),), - expected_lineage_columns=( - CompiledLineageColumnFact( - output_column="order_id", - upstream_columns=( - CompiledLineageSourceFact( - resource_type=CompiledResourceType.MODEL, - resource_name="orders", - column_name="order_id", - ), - ), - transform_kind=ColumnTransformKind.DIRECT, - confidence=ColumnLineageConfidence.HIGH, - ), - ), - expected_has_star=False, - ) - ], - ids=lambda case: case.description, -) -def test_given_compact_query_analysis_when_ast_parse_would_fail_then_returns_compact_facts( - test_case: PolyglotAnalysisTestCase, - monkeypatch: pytest.MonkeyPatch, -) -> None: - polyglot_module: object | None = import_polyglot_sql() - assert polyglot_module is not None - - def raise_parse_error(*args: object, **kwargs: object) -> object: - del args, kwargs - raise AssertionError("AST parse should not be called") - - monkeypatch.setattr(polyglot_module, "parse_one", raise_parse_error) - - result: PolyglotAnalysisResult = analyze_columns_and_lineage_with_polyglot( - query_sql=test_case.query_sql, - references=test_case.references, - allow_compact_analysis=True, - ) - - assert result.analysis_succeeded - assert result.columns == test_case.expected_columns - assert result.lineage_columns == test_case.expected_lineage_columns - assert result.has_star is test_case.expected_has_star - - -@pytest.mark.parametrize( - "test_case", - [ - PolyglotAnalysisTestCase( - description="uses compact analysis for aggregate transforms", - query_sql='SELECT COUNT(*) AS n, SUM(amount) AS total FROM __ref("orders")', - references=(CompileSqlReference(SqlReferenceKind.REF, "orders"),), - expected_columns=( - InferredColumn(name="n", type="BIGINT", nullability=InferredNullability.NON_NULL), - InferredColumn(name="total", type="DECIMAL"), - ), - expected_lineage_columns=( - CompiledLineageColumnFact( - output_column="n", - upstream_columns=(), - transform_kind=ColumnTransformKind.AGGREGATION, - confidence=ColumnLineageConfidence.UNKNOWN, - ), - CompiledLineageColumnFact( - output_column="total", - upstream_columns=( - CompiledLineageSourceFact( - resource_type=CompiledResourceType.MODEL, - resource_name="orders", - column_name="amount", - ), - ), - transform_kind=ColumnTransformKind.AGGREGATION, - confidence=ColumnLineageConfidence.HIGH, - ), - ), - expected_has_star=False, - ), - PolyglotAnalysisTestCase( - description="uses compact analysis for expression transforms", - query_sql='SELECT amount + tax AS total FROM __ref("orders")', - references=(CompileSqlReference(SqlReferenceKind.REF, "orders"),), - expected_columns=(InferredColumn(name="total"),), - expected_lineage_columns=( - CompiledLineageColumnFact( - output_column="total", - upstream_columns=( - CompiledLineageSourceFact( - resource_type=CompiledResourceType.MODEL, - resource_name="orders", - column_name="amount", - ), - CompiledLineageSourceFact( - resource_type=CompiledResourceType.MODEL, - resource_name="orders", - column_name="tax", - ), - ), - transform_kind=ColumnTransformKind.EXPRESSION, - confidence=ColumnLineageConfidence.HIGH, - ), - ), - expected_has_star=False, - ), - PolyglotAnalysisTestCase( - description="uses compact analysis for cte lineage", - query_sql=( - 'WITH base AS (SELECT order_id FROM __ref("orders")) SELECT order_id FROM base' - ), - references=(CompileSqlReference(SqlReferenceKind.REF, "orders"),), - expected_columns=(InferredColumn(name="order_id"),), - expected_lineage_columns=( - CompiledLineageColumnFact( - output_column="order_id", - upstream_columns=( - CompiledLineageSourceFact( - resource_type=CompiledResourceType.MODEL, - resource_name="orders", - column_name="order_id", - ), - ), - transform_kind=ColumnTransformKind.DIRECT, - confidence=ColumnLineageConfidence.HIGH, - ), - ), - expected_has_star=False, - ), - PolyglotAnalysisTestCase( - description="uses compact analysis for set operation branch lineage", - query_sql=( - 'SELECT order_id FROM __ref("orders") UNION ALL SELECT return_id FROM __ref("returns")' - ), - references=( - CompileSqlReference(SqlReferenceKind.REF, "orders"), - CompileSqlReference(SqlReferenceKind.REF, "returns"), - ), - expected_columns=(InferredColumn(name="order_id"),), - expected_lineage_columns=( - CompiledLineageColumnFact( - output_column="order_id", - upstream_columns=( - CompiledLineageSourceFact( - resource_type=CompiledResourceType.MODEL, - resource_name="orders", - column_name="order_id", - ), - CompiledLineageSourceFact( - resource_type=CompiledResourceType.MODEL, - resource_name="returns", - column_name="return_id", - ), - ), - transform_kind=ColumnTransformKind.DIRECT, - confidence=ColumnLineageConfidence.HIGH, - ), - ), - expected_has_star=False, - ), - PolyglotAnalysisTestCase( - description="uses compact analysis for qualified stars", - query_sql=( - 'SELECT o.* FROM __ref("orders") o JOIN __ref("customers") c ON o.customer_id = c.id' - ), - references=( - CompileSqlReference(SqlReferenceKind.REF, "orders"), - CompileSqlReference(SqlReferenceKind.REF, "customers"), - ), - expected_columns=(), - expected_lineage_columns=(), - expected_has_star=True, - ), - PolyglotAnalysisTestCase( - description="uses compact schema metadata for unqualified column resolution", - query_sql=( - 'SELECT amount FROM __ref("orders") o JOIN __ref("customers") c ON o.customer_id = c.id' - ), - references=( - CompileSqlReference(SqlReferenceKind.REF, "orders"), - CompileSqlReference(SqlReferenceKind.REF, "customers"), - ), - column_nullability_by_table={ - "orders": { - "amount": InferredNullability.UNKNOWN, - "customer_id": InferredNullability.UNKNOWN, - }, - "customers": {"id": InferredNullability.UNKNOWN}, - }, - expected_columns=(InferredColumn(name="amount"),), - expected_lineage_columns=( - CompiledLineageColumnFact( - output_column="amount", - upstream_columns=( - CompiledLineageSourceFact( - resource_type=CompiledResourceType.MODEL, - resource_name="orders", - column_name="amount", - ), - ), - transform_kind=ColumnTransformKind.DIRECT, - confidence=ColumnLineageConfidence.HIGH, - ), - ), - expected_has_star=False, - ), - ], - ids=lambda case: case.description, -) -def test_given_supported_compact_query_when_ast_parse_would_fail_then_returns_analysis_facts( - test_case: PolyglotAnalysisTestCase, - monkeypatch: pytest.MonkeyPatch, -) -> None: - polyglot_module: object | None = import_polyglot_sql() - assert polyglot_module is not None - - def raise_parse_error(*args: object, **kwargs: object) -> object: - del args, kwargs - raise AssertionError("AST parse should not be called") - - monkeypatch.setattr(polyglot_module, "parse_one", raise_parse_error) - - result: PolyglotAnalysisResult = analyze_columns_and_lineage_with_polyglot( - query_sql=test_case.query_sql, - references=test_case.references, - column_nullability_by_table=test_case.column_nullability_by_table, - allow_compact_analysis=True, - ) - - assert result.analysis_succeeded - assert result.columns == test_case.expected_columns - assert result.lineage_columns == test_case.expected_lineage_columns - assert result.has_star is test_case.expected_has_star - - -@pytest.mark.parametrize( - "test_case", - [ - PolyglotAnalysisTestCase( - description="preserves a cast type through direct cte passthroughs", - query_sql=( - "WITH transformed AS (" - 'SELECT CAST(amount AS INTEGER) AS amount FROM __ref("orders")' - "), final AS (" - "SELECT amount FROM transformed" - ") SELECT amount FROM final" - ), - references=(CompileSqlReference(SqlReferenceKind.REF, "orders"),), - column_nullability_by_table={"orders": {"amount": InferredNullability.NON_NULL}}, - column_types_by_table={"orders": {"amount": "VARCHAR"}}, - expected_columns=( - InferredColumn( - name="amount", - type="INT", - nullability=InferredNullability.NON_NULL, - ), - ), - expected_lineage_columns=direct_orders_lineage("amount"), - expected_has_star=False, - ), - PolyglotAnalysisTestCase( - description="does not reuse a source type through a transformed cte", - query_sql=( - "WITH transformed AS (" - "SELECT amount || '0' AS amount FROM __ref(\"orders\")" - "), final AS (" - "SELECT amount FROM transformed" - ") SELECT amount FROM final" - ), - references=(CompileSqlReference(SqlReferenceKind.REF, "orders"),), - column_nullability_by_table={"orders": {"amount": InferredNullability.UNKNOWN}}, - column_types_by_table={"orders": {"amount": "INTEGER"}}, - expected_columns=(InferredColumn(name="amount"),), - expected_lineage_columns=direct_orders_lineage("amount"), - expected_has_star=False, - ), - PolyglotAnalysisTestCase( - description="preserves only matching recursive by-name cte union types", + description="preserves only matching recursive by-name cte union types", query_sql=( "WITH current_orders AS (" "SELECT CAST(amount AS INTEGER) AS amount, " @@ -1709,111 +803,7 @@ def raise_parse_error(*args: object, **kwargs: object) -> object: def test_given_cte_chain_when_analyzing_direct_passthrough_then_type_is_conservative( test_case: PolyglotAnalysisTestCase, ) -> None: - result: PolyglotAnalysisResult = analyze_columns_and_lineage_with_polyglot( - query_sql=test_case.query_sql, - references=test_case.references, - column_nullability_by_table=test_case.column_nullability_by_table, - column_types_by_table=test_case.column_types_by_table, - inference_profile=test_case.inference_profile, - allow_compact_analysis=True, - recover_cte_facts=True, - ) - - assert result.analysis_succeeded - assert result.columns == test_case.expected_columns - assert result.lineage_columns == test_case.expected_lineage_columns - assert result.has_star is test_case.expected_has_star - - -@pytest.mark.parametrize( - "test_case", - [ - PolyglotAnalysisTestCase( - description="preserves safe expression types without over-inferring overloads", - query_sql=( - "WITH transformed AS (" - "SELECT " - "'web' AS source_name, " - "TRUE AS active, " - "order_id IN (1, 2) AS selected, " - "first_name || last_name AS full_name, " - "COALESCE(status, CAST(NULL AS VARCHAR)) AS status, " - "IFF(active, status, NULL) AS maybe_status, " - "CASE WHEN active THEN status ELSE NULL END AS case_status, " - "NULLIF(status, '') AS clean_status, " - "MIN(created_at) OVER (PARTITION BY order_id) AS first_created_at, " - "to_date, " - "payload || payload AS merged_payload, " - "SUBSTRING(payload, 1, 2) AS sliced_payload " - 'FROM __ref("orders")' - "), final AS (" - "SELECT source_name, active, selected, full_name, status, maybe_status, " - "case_status, clean_status, first_created_at, to_date, merged_payload, " - "sliced_payload FROM transformed" - ") SELECT source_name, active, selected, full_name, status, maybe_status, " - "case_status, clean_status, first_created_at, to_date, merged_payload, " - "sliced_payload FROM final" - ), - references=(CompileSqlReference(SqlReferenceKind.REF, "orders"),), - column_nullability_by_table={ - "orders": { - "order_id": InferredNullability.NON_NULL, - "first_name": InferredNullability.UNKNOWN, - "last_name": InferredNullability.UNKNOWN, - "status": InferredNullability.UNKNOWN, - "active": InferredNullability.UNKNOWN, - "created_at": InferredNullability.UNKNOWN, - "to_date": InferredNullability.UNKNOWN, - "payload": InferredNullability.UNKNOWN, - } - }, - column_types_by_table={ - "orders": { - "order_id": "NUMBER(38,0)", - "first_name": "VARCHAR(16777216)", - "last_name": "VARCHAR(16777216)", - "status": "VARCHAR(16777216)", - "active": "BOOLEAN", - "created_at": "TIMESTAMP_NTZ", - "to_date": "INTEGER", - "payload": "BINARY", - } - }, - inference_profile=ExpressionInferenceProfile( - sql_analysis_dialect="snowflake", - function_return_types={"TO_DATE": "DATE"}, - ), - expected_columns=( - InferredColumn( - name="source_name", - nullability=InferredNullability.NON_NULL, - ), - InferredColumn( - name="active", - type="BOOLEAN", - nullability=InferredNullability.NON_NULL, - ), - InferredColumn(name="selected", type="BOOLEAN"), - InferredColumn(name="full_name", type="TEXT"), - InferredColumn(name="status", type="VARCHAR(16777216)"), - InferredColumn(name="maybe_status", type="VARCHAR(16777216)"), - InferredColumn(name="case_status", type="VARCHAR(16777216)"), - InferredColumn(name="clean_status", type="VARCHAR(16777216)"), - InferredColumn(name="first_created_at", type="TIMESTAMP_NTZ"), - InferredColumn(name="to_date", type="INTEGER"), - InferredColumn(name="merged_payload"), - InferredColumn(name="sliced_payload", type="BINARY"), - ), - expected_lineage_columns=(), - expected_has_star=False, - ) - ], - ids=lambda case: case.description, -) -def test_given_typed_cte_expressions_when_recovering_facts_then_safe_result_types_are_preserved( - test_case: PolyglotAnalysisTestCase, -) -> None: - result: PolyglotAnalysisResult = analyze_columns_and_lineage_with_polyglot( + result: NativeQueryColumns = reanalysed_columns( query_sql=test_case.query_sql, references=test_case.references, column_nullability_by_table=test_case.column_nullability_by_table, @@ -1823,89 +813,14 @@ def test_given_typed_cte_expressions_when_recovering_facts_then_safe_result_type recover_cte_facts=True, ) + assert result.succeeded assert result.columns == test_case.expected_columns - - -@pytest.mark.parametrize( - "test_case", - [ - PolyglotAnalysisTestCase( - description="keeps star lineage conservative on fast path", - query_sql='SELECT * FROM __ref("orders")', - references=(CompileSqlReference(SqlReferenceKind.REF, "orders"),), - column_nullability_by_table={ - "orders": { - "order_id": InferredNullability.NON_NULL, - "status": InferredNullability.NULLABLE, - } - }, - expected_columns=(), - expected_lineage_columns=(), - expected_has_star=True, - ) - ], - ids=lambda case: case.description, -) -def test_given_star_projection_when_compact_analysis_disabled_then_marks_star_without_expansion( - test_case: PolyglotAnalysisTestCase, -) -> None: - result: PolyglotAnalysisResult = analyze_columns_and_lineage_with_polyglot( - query_sql=test_case.query_sql, - references=test_case.references, - column_nullability_by_table=test_case.column_nullability_by_table, - ) - - assert result.analysis_succeeded - assert result.columns == test_case.expected_columns - assert result.lineage_columns == test_case.expected_lineage_columns assert result.has_star is test_case.expected_has_star @pytest.mark.parametrize( "test_case", [ - PolyglotAnalysisTestCase( - description="expands star lineage on rich compact path", - query_sql='SELECT * FROM __ref("orders")', - references=(CompileSqlReference(SqlReferenceKind.REF, "orders"),), - column_nullability_by_table={ - "orders": { - "order_id": InferredNullability.NON_NULL, - "status": InferredNullability.NULLABLE, - } - }, - expected_columns=( - InferredColumn(name="order_id", nullability=InferredNullability.NON_NULL), - InferredColumn(name="status", nullability=InferredNullability.NULLABLE), - ), - expected_lineage_columns=( - CompiledLineageColumnFact( - output_column="order_id", - upstream_columns=( - CompiledLineageSourceFact( - resource_type=CompiledResourceType.MODEL, - resource_name="orders", - column_name="order_id", - ), - ), - transform_kind=ColumnTransformKind.DIRECT, - confidence=ColumnLineageConfidence.HIGH, - ), - CompiledLineageColumnFact( - output_column="status", - upstream_columns=( - CompiledLineageSourceFact( - resource_type=CompiledResourceType.MODEL, - resource_name="orders", - column_name="status", - ), - ), - transform_kind=ColumnTransformKind.DIRECT, - confidence=ColumnLineageConfidence.HIGH, - ), - ), - expected_has_star=True, - ), PolyglotAnalysisTestCase( description="expands declared table function output columns on rich compact path", query_sql='SELECT * FROM __table_fn("customer_orders")(42)', @@ -1966,7 +881,7 @@ def test_given_star_projection_when_compact_analysis_disabled_then_marks_star_wi def test_given_star_projection_when_compact_analysis_enabled_then_expands_schema_lineage( test_case: PolyglotAnalysisTestCase, ) -> None: - result: PolyglotAnalysisResult = analyze_columns_and_lineage_with_polyglot( + result: NativeQueryColumns = reanalysed_columns( query_sql=test_case.query_sql, references=test_case.references, column_nullability_by_table=test_case.column_nullability_by_table, @@ -1974,148 +889,11 @@ def test_given_star_projection_when_compact_analysis_enabled_then_expands_schema allow_compact_analysis=True, ) - assert result.analysis_succeeded + assert result.succeeded assert result.columns == test_case.expected_columns - assert result.lineage_columns == test_case.expected_lineage_columns assert result.has_star is test_case.expected_has_star -@pytest.mark.parametrize( - "test_case", - [ - PolyglotAnalysisTestCase( - description="matches AST fallback for unqualified single ref", - query_sql='SELECT order_id FROM __ref("orders")', - references=(CompileSqlReference(SqlReferenceKind.REF, "orders"),), - expected_columns=(), - expected_lineage_columns=(), - expected_has_star=False, - ), - PolyglotAnalysisTestCase( - description="matches AST fallback for qualified join refs", - query_sql=( - 'SELECT o.order_id, c.name FROM __ref("orders") o ' - 'JOIN __ref("customers") c ON o.customer_id = c.customer_id' - ), - references=( - CompileSqlReference(SqlReferenceKind.REF, "orders"), - CompileSqlReference(SqlReferenceKind.REF, "customers"), - ), - expected_columns=(), - expected_lineage_columns=(), - expected_has_star=False, - ), - PolyglotAnalysisTestCase( - description="matches AST fallback for source refs", - query_sql='SELECT payment_id FROM __source("stripe__payments")', - references=(CompileSqlReference(SqlReferenceKind.SOURCE, "stripe__payments"),), - expected_columns=(), - expected_lineage_columns=(), - expected_has_star=False, - ), - PolyglotAnalysisTestCase( - description="matches AST fallback for seed refs", - query_sql='SELECT lookup_id FROM __seed("order_statuses")', - references=(CompileSqlReference(SqlReferenceKind.SEED, "order_statuses"),), - expected_columns=(), - expected_lineage_columns=(), - expected_has_star=False, - ), - PolyglotAnalysisTestCase( - description="matches AST fallback for casted ref column", - query_sql='SELECT CAST(order_id AS BIGINT) AS order_id FROM __ref("orders")', - references=(CompileSqlReference(SqlReferenceKind.REF, "orders"),), - expected_columns=(), - expected_lineage_columns=(), - expected_has_star=False, - ), - PolyglotAnalysisTestCase( - description="matches AST fallback for arithmetic expression fallback", - query_sql='SELECT amount + tax AS total FROM __ref("orders")', - references=(CompileSqlReference(SqlReferenceKind.REF, "orders"),), - expected_columns=(), - expected_lineage_columns=(), - expected_has_star=False, - ), - ], - ids=lambda case: case.description, -) -def test_given_compact_query_analysis_safe_shape_when_analyzing_then_matches_ast_facts( - test_case: PolyglotAnalysisTestCase, - monkeypatch: pytest.MonkeyPatch, -) -> None: - compact_result: PolyglotAnalysisResult = analyze_columns_and_lineage_with_polyglot( - query_sql=test_case.query_sql, - references=test_case.references, - allow_compact_analysis=True, - ) - assert compact_result.analysis_succeeded - assert compact_result.has_star is test_case.expected_has_star - - polyglot_module: object | None = import_polyglot_sql() - assert polyglot_module is not None - - def raise_compact_error(*args: object, **kwargs: object) -> object: - del args, kwargs - raise ParseError("compact analysis disabled") - - monkeypatch.setattr(polyglot_module, "analyze_query", raise_compact_error) - fallback_result: PolyglotAnalysisResult = analyze_columns_and_lineage_with_polyglot( - query_sql=test_case.query_sql, - references=test_case.references, - allow_compact_analysis=True, - ) - - assert fallback_result.analysis_succeeded - assert compact_result.columns == fallback_result.columns - assert compact_result.has_star == fallback_result.has_star - compact_lineage_columns: tuple[CompiledLineageColumnFact, ...] = tuple( - compact_result.lineage_columns - ) - fallback_lineage_columns: tuple[CompiledLineageColumnFact, ...] = tuple( - fallback_result.lineage_columns - ) - assert len(compact_lineage_columns) == len(fallback_lineage_columns) - for compact_fact, fallback_fact in zip( - compact_lineage_columns, - fallback_lineage_columns, - strict=True, - ): - assert compact_fact.output_column == fallback_fact.output_column - assert compact_fact.upstream_columns == fallback_fact.upstream_columns - assert compact_fact.transform_kind == fallback_fact.transform_kind - - -@pytest.mark.parametrize( - "test_case", - [ - UnexpectedAnalysisFailureTestCase( - description="unexpected native integration failure", - expected_error="unexpected native integration failure", - ) - ], - ids=lambda case: case.description, -) -def test_given_unexpected_polyglot_failure_when_analyzing_then_failure_is_not_silenced( - test_case: UnexpectedAnalysisFailureTestCase, - monkeypatch: pytest.MonkeyPatch, -) -> None: - polyglot_module: object = import_polyglot_sql() - - def raise_unexpected_failure(*args: object, **kwargs: object) -> object: - del args, kwargs - raise RuntimeError(test_case.expected_error) - - monkeypatch.setattr(polyglot_module, "analyze_query", raise_unexpected_failure) - - with pytest.raises(RuntimeError, match=test_case.expected_error): - analyze_columns_and_lineage_with_polyglot( - query_sql='SELECT id FROM __ref("orders")', - references=(CompileSqlReference(SqlReferenceKind.REF, "orders"),), - allow_compact_analysis=True, - ) - - @pytest.mark.parametrize( "test_case", [ @@ -2137,6 +915,24 @@ def raise_unexpected_failure(*args: object, **kwargs: object) -> object: placeholders={}, expected_sql="SELECT * FROM t WHERE d >= @@@start", ), + SubstitutePlaceholderDefaultsTestCase( + description="an extra at sign and unknown names stay as Python's regex leaves them", + query_sql="@@@@a + @@@a @@@unknown @@@ a", + placeholders={"a": "1", "é": "2", "x\u0661": "3", "a_b1x": "4"}, + expected_sql="@1 + 1 @@@unknown @@@ a", + ), + SubstitutePlaceholderDefaultsTestCase( + description="names follow Python's word characters beyond ASCII", + query_sql="@@@é·@@@x١ @@@a_b1x@@@", + placeholders={"a": "1", "é": "2", "x\u0661": "3", "a_b1x": "4"}, + expected_sql="2·3 4@@@", + ), + SubstitutePlaceholderDefaultsTestCase( + description="adjacent and quoted placeholders are replaced", + query_sql="@@@a@@@a '@@@a'", + placeholders={"a": "1", "é": "2", "x\u0661": "3", "a_b1x": "4"}, + expected_sql="11 '1'", + ), SubstitutePlaceholderDefaultsTestCase( description="returns sql unchanged when no placeholders in sql", query_sql="SELECT * FROM t", diff --git a/tests/unit/src/sqlbuild/compiler/frontier/_test_types.py b/tests/unit/src/sqlbuild/compiler/frontier/_test_types.py index 51aa39f3d7..5754853221 100644 --- a/tests/unit/src/sqlbuild/compiler/frontier/_test_types.py +++ b/tests/unit/src/sqlbuild/compiler/frontier/_test_types.py @@ -9,7 +9,6 @@ CompilerEngine, CompilerStage, NativeFallbackSite, - NativeStage, ) @@ -121,35 +120,6 @@ class SharedCaptureTestCase: expected_shared_nodes: int -@dataclass(frozen=True) -class NativeStageTierTestCase: - """One engine, one native stage, and whether that engine runs it.""" - - description: str - engine: CompilerEngine - stage: NativeStage - expected_enabled: bool - - -@dataclass(frozen=True) -class DefaultEngineStageTestCase: - """With no engine selected, the native stages the default compile runs and those it skips.""" - - description: str - expected_enabled: frozenset[NativeStage] - expected_disabled: frozenset[NativeStage] - - -@dataclass(frozen=True) -class NativeStageCouplingTestCase: - """A native stage that may only run where the stage it relies on also runs natively.""" - - description: str - dependent: NativeStage - dependency: NativeStage - expected_engines_without_dependency: frozenset[CompilerEngine] - - @dataclass(frozen=True) class NativeFallbackRecorderTestCase: """Fallbacks one process records and the record file it writes at exit.""" diff --git a/tests/unit/src/sqlbuild/compiler/frontier/test_cache_namespace.py b/tests/unit/src/sqlbuild/compiler/frontier/test_cache_namespace.py index 8f284670f9..eee5cacf38 100644 --- a/tests/unit/src/sqlbuild/compiler/frontier/test_cache_namespace.py +++ b/tests/unit/src/sqlbuild/compiler/frontier/test_cache_namespace.py @@ -1,4 +1,4 @@ -"""On-disk compiler stores are namespaced by engine; Python keeps its existing paths.""" +"""On-disk compiler stores are namespaced by engine.""" from __future__ import annotations @@ -19,12 +19,6 @@ @pytest.mark.parametrize( "test_case", [ - EngineCacheNameTestCase( - description="python_keeps_name", - engine=CompilerEngine.PYTHON, - base="compiler", - expected_name="compiler", - ), EngineCacheNameTestCase( description="native_gets_versioned_suffix", engine=CompilerEngine.NATIVE, @@ -57,16 +51,6 @@ def test_given_engine_when_naming_store_then_only_native_engines_are_suffixed( @pytest.mark.parametrize( "test_case", [ - EngineStorePathsTestCase( - description="python_paths_unchanged", - engine=CompilerEngine.PYTHON, - expected_paths=( - "target/cache/compiler", - "target/cache/compiler", - "target/cache/compiler/declaration-scopes-v2", - "target/rules-cache/bulk/sql.json", - ), - ), EngineStorePathsTestCase( description="native_paths_separate", engine=CompilerEngine.NATIVE, diff --git a/tests/unit/src/sqlbuild/compiler/frontier/test_native_fallback_recorder.py b/tests/unit/src/sqlbuild/compiler/frontier/test_native_fallback_recorder.py index 9ec4a839cb..2f1ce465f5 100644 --- a/tests/unit/src/sqlbuild/compiler/frontier/test_native_fallback_recorder.py +++ b/tests/unit/src/sqlbuild/compiler/frontier/test_native_fallback_recorder.py @@ -20,16 +20,16 @@ NativeFallbackRecorderTestCase( description="counts_per_site_and_kind_sorted", recorded=( - (NativeFallbackSite.PROJECT_ASSEMBLY, "deferred"), - (NativeFallbackSite.MACRO_CALL_RESOLUTION, "deferred"), - (NativeFallbackSite.PROJECT_ASSEMBLY, "deferred"), - (NativeFallbackSite.PROJECT_ASSEMBLY, "error"), + (NativeFallbackSite.SCOPE_REBIND_LOOKUP, "deferred"), + (NativeFallbackSite.MACRO_CALL_MOCKED, "deferred"), + (NativeFallbackSite.SCOPE_REBIND_LOOKUP, "deferred"), + (NativeFallbackSite.SCOPE_REBIND_LOOKUP, "error"), ), expected_files=[ [ - ["macro_calls.resolution", "deferred", 1], - ["project_assembly.assembly", "deferred", 2], - ["project_assembly.assembly", "error", 1], + ["declaration_scopes.rebind_lookup", "deferred", 2], + ["declaration_scopes.rebind_lookup", "error", 1], + ["macro_calls.mocked_evaluation", "deferred", 1], ] ], ), diff --git a/tests/unit/src/sqlbuild/compiler/frontier/test_native_stage_tiers.py b/tests/unit/src/sqlbuild/compiler/frontier/test_native_stage_tiers.py deleted file mode 100644 index e004764d10..0000000000 --- a/tests/unit/src/sqlbuild/compiler/frontier/test_native_stage_tiers.py +++ /dev/null @@ -1,408 +0,0 @@ -"""Each engine runs exactly the native stages whose registered tier it includes.""" - -from __future__ import annotations - -from itertools import compress - -import pytest - -from sqlbuild.compiler.frontier.constants import ( - COMPILER_ENGINE_ENV_VAR, - ENGINE_NATIVE_STAGE_TIERS, - NATIVE_STAGE_TIERS, -) -from sqlbuild.compiler.frontier.main.native_stage_enabled import native_stage_enabled -from sqlbuild.compiler.frontier.types import CompilerEngine, NativeStage -from tests.unit.src.sqlbuild.compiler.frontier._test_types import ( - DefaultEngineStageTestCase, - NativeStageCouplingTestCase, - NativeStageTierTestCase, -) - - -@pytest.mark.parametrize( - "test_case", - [ - NativeStageTierTestCase( - description="python_discovery", - engine=CompilerEngine.PYTHON, - stage=NativeStage.DISCOVERY, - expected_enabled=False, - ), - NativeStageTierTestCase( - description="python_declaration_scopes", - engine=CompilerEngine.PYTHON, - stage=NativeStage.DECLARATION_SCOPES, - expected_enabled=False, - ), - NativeStageTierTestCase( - description="native_discovery", - engine=CompilerEngine.NATIVE, - stage=NativeStage.DISCOVERY, - expected_enabled=True, - ), - NativeStageTierTestCase( - description="native_declaration_scopes", - engine=CompilerEngine.NATIVE, - stage=NativeStage.DECLARATION_SCOPES, - expected_enabled=True, - ), - NativeStageTierTestCase( - description="native_preview_discovery", - engine=CompilerEngine.NATIVE_PREVIEW, - stage=NativeStage.DISCOVERY, - expected_enabled=True, - ), - NativeStageTierTestCase( - description="native_preview_declaration_scopes", - engine=CompilerEngine.NATIVE_PREVIEW, - stage=NativeStage.DECLARATION_SCOPES, - expected_enabled=True, - ), - NativeStageTierTestCase( - description="python_model_config", - engine=CompilerEngine.PYTHON, - stage=NativeStage.MODEL_CONFIG, - expected_enabled=False, - ), - NativeStageTierTestCase( - description="native_model_config", - engine=CompilerEngine.NATIVE, - stage=NativeStage.MODEL_CONFIG, - expected_enabled=True, - ), - NativeStageTierTestCase( - description="native_preview_model_config", - engine=CompilerEngine.NATIVE_PREVIEW, - stage=NativeStage.MODEL_CONFIG, - expected_enabled=True, - ), - NativeStageTierTestCase( - description="python_reference_extraction", - engine=CompilerEngine.PYTHON, - stage=NativeStage.REFERENCE_EXTRACTION, - expected_enabled=False, - ), - NativeStageTierTestCase( - description="native_reference_extraction", - engine=CompilerEngine.NATIVE, - stage=NativeStage.REFERENCE_EXTRACTION, - expected_enabled=True, - ), - NativeStageTierTestCase( - description="native_preview_reference_extraction", - engine=CompilerEngine.NATIVE_PREVIEW, - stage=NativeStage.REFERENCE_EXTRACTION, - expected_enabled=True, - ), - NativeStageTierTestCase( - description="python_declaration_files", - engine=CompilerEngine.PYTHON, - stage=NativeStage.DECLARATION_FILES, - expected_enabled=False, - ), - NativeStageTierTestCase( - description="native_declaration_files", - engine=CompilerEngine.NATIVE, - stage=NativeStage.DECLARATION_FILES, - expected_enabled=True, - ), - NativeStageTierTestCase( - description="native_preview_declaration_files", - engine=CompilerEngine.NATIVE_PREVIEW, - stage=NativeStage.DECLARATION_FILES, - expected_enabled=True, - ), - NativeStageTierTestCase( - description="python_model_loop", - engine=CompilerEngine.PYTHON, - stage=NativeStage.MODEL_LOOP, - expected_enabled=False, - ), - NativeStageTierTestCase( - description="native_model_loop", - engine=CompilerEngine.NATIVE, - stage=NativeStage.MODEL_LOOP, - expected_enabled=True, - ), - NativeStageTierTestCase( - description="native_preview_model_loop", - engine=CompilerEngine.NATIVE_PREVIEW, - stage=NativeStage.MODEL_LOOP, - expected_enabled=True, - ), - NativeStageTierTestCase( - description="python_macro_calls", - engine=CompilerEngine.PYTHON, - stage=NativeStage.MACRO_CALLS, - expected_enabled=False, - ), - NativeStageTierTestCase( - description="python_macro_call_store", - engine=CompilerEngine.PYTHON, - stage=NativeStage.MACRO_CALL_STORE, - expected_enabled=False, - ), - NativeStageTierTestCase( - description="native_macro_calls", - engine=CompilerEngine.NATIVE, - stage=NativeStage.MACRO_CALLS, - expected_enabled=True, - ), - NativeStageTierTestCase( - description="native_macro_call_store", - engine=CompilerEngine.NATIVE, - stage=NativeStage.MACRO_CALL_STORE, - expected_enabled=True, - ), - NativeStageTierTestCase( - description="native_preview_macro_calls", - engine=CompilerEngine.NATIVE_PREVIEW, - stage=NativeStage.MACRO_CALLS, - expected_enabled=True, - ), - NativeStageTierTestCase( - description="native_preview_macro_call_store", - engine=CompilerEngine.NATIVE_PREVIEW, - stage=NativeStage.MACRO_CALL_STORE, - expected_enabled=True, - ), - NativeStageTierTestCase( - description="python_attachments", - engine=CompilerEngine.PYTHON, - stage=NativeStage.ATTACHMENTS, - expected_enabled=False, - ), - NativeStageTierTestCase( - description="native_attachments", - engine=CompilerEngine.NATIVE, - stage=NativeStage.ATTACHMENTS, - expected_enabled=True, - ), - NativeStageTierTestCase( - description="native_preview_attachments", - engine=CompilerEngine.NATIVE_PREVIEW, - stage=NativeStage.ATTACHMENTS, - expected_enabled=True, - ), - NativeStageTierTestCase( - description="python_type_system", - engine=CompilerEngine.PYTHON, - stage=NativeStage.TYPE_SYSTEM, - expected_enabled=False, - ), - NativeStageTierTestCase( - description="native_type_system", - engine=CompilerEngine.NATIVE, - stage=NativeStage.TYPE_SYSTEM, - expected_enabled=True, - ), - NativeStageTierTestCase( - description="native_preview_type_system", - engine=CompilerEngine.NATIVE_PREVIEW, - stage=NativeStage.TYPE_SYSTEM, - expected_enabled=True, - ), - NativeStageTierTestCase( - description="python_model_analysis", - engine=CompilerEngine.PYTHON, - stage=NativeStage.MODEL_ANALYSIS, - expected_enabled=False, - ), - NativeStageTierTestCase( - description="native_model_analysis", - engine=CompilerEngine.NATIVE, - stage=NativeStage.MODEL_ANALYSIS, - expected_enabled=True, - ), - NativeStageTierTestCase( - description="native_preview_model_analysis", - engine=CompilerEngine.NATIVE_PREVIEW, - stage=NativeStage.MODEL_ANALYSIS, - expected_enabled=True, - ), - NativeStageTierTestCase( - description="python_semantic_checks", - engine=CompilerEngine.PYTHON, - stage=NativeStage.SEMANTIC_CHECKS, - expected_enabled=False, - ), - NativeStageTierTestCase( - description="native_semantic_checks", - engine=CompilerEngine.NATIVE, - stage=NativeStage.SEMANTIC_CHECKS, - expected_enabled=True, - ), - NativeStageTierTestCase( - description="native_preview_semantic_checks", - engine=CompilerEngine.NATIVE_PREVIEW, - stage=NativeStage.SEMANTIC_CHECKS, - expected_enabled=True, - ), - NativeStageTierTestCase( - description="python_contracts", - engine=CompilerEngine.PYTHON, - stage=NativeStage.CONTRACTS, - expected_enabled=False, - ), - NativeStageTierTestCase( - description="native_contracts", - engine=CompilerEngine.NATIVE, - stage=NativeStage.CONTRACTS, - expected_enabled=True, - ), - NativeStageTierTestCase( - description="native_preview_contracts", - engine=CompilerEngine.NATIVE_PREVIEW, - stage=NativeStage.CONTRACTS, - expected_enabled=True, - ), - NativeStageTierTestCase( - description="python_lineage_facts", - engine=CompilerEngine.PYTHON, - stage=NativeStage.LINEAGE_FACTS, - expected_enabled=False, - ), - NativeStageTierTestCase( - description="native_lineage_facts", - engine=CompilerEngine.NATIVE, - stage=NativeStage.LINEAGE_FACTS, - expected_enabled=True, - ), - NativeStageTierTestCase( - description="native_preview_lineage_facts", - engine=CompilerEngine.NATIVE_PREVIEW, - stage=NativeStage.LINEAGE_FACTS, - expected_enabled=True, - ), - NativeStageTierTestCase( - description="python_sql_test_glue", - engine=CompilerEngine.PYTHON, - stage=NativeStage.SQL_TEST_GLUE, - expected_enabled=False, - ), - NativeStageTierTestCase( - description="native_sql_test_glue", - engine=CompilerEngine.NATIVE, - stage=NativeStage.SQL_TEST_GLUE, - expected_enabled=True, - ), - NativeStageTierTestCase( - description="native_preview_sql_test_glue", - engine=CompilerEngine.NATIVE_PREVIEW, - stage=NativeStage.SQL_TEST_GLUE, - expected_enabled=True, - ), - NativeStageTierTestCase( - description="python_project_assembly", - engine=CompilerEngine.PYTHON, - stage=NativeStage.PROJECT_ASSEMBLY, - expected_enabled=False, - ), - NativeStageTierTestCase( - description="native_project_assembly", - engine=CompilerEngine.NATIVE, - stage=NativeStage.PROJECT_ASSEMBLY, - expected_enabled=True, - ), - NativeStageTierTestCase( - description="native_preview_project_assembly", - engine=CompilerEngine.NATIVE_PREVIEW, - stage=NativeStage.PROJECT_ASSEMBLY, - expected_enabled=True, - ), - ], - ids=lambda case: case.description, -) -def test_given_engine_when_checking_native_stage_then_only_its_tiers_run( - test_case: NativeStageTierTestCase, monkeypatch: pytest.MonkeyPatch -) -> None: - monkeypatch.setenv(COMPILER_ENGINE_ENV_VAR, test_case.engine.value) - - assert native_stage_enabled(test_case.stage) is test_case.expected_enabled - - -@pytest.mark.parametrize( - "test_case", - [ - DefaultEngineStageTestCase( - description="discovery_rendering_and_analysis_native", - expected_enabled=frozenset( - { - NativeStage.DISCOVERY, - NativeStage.DECLARATION_SCOPES, - NativeStage.MODEL_CONFIG, - NativeStage.REFERENCE_EXTRACTION, - NativeStage.DECLARATION_FILES, - NativeStage.MODEL_LOOP, - NativeStage.MACRO_CALLS, - NativeStage.MACRO_CALL_STORE, - NativeStage.ATTACHMENTS, - NativeStage.TYPE_SYSTEM, - NativeStage.MODEL_ANALYSIS, - NativeStage.SEMANTIC_CHECKS, - NativeStage.CONTRACTS, - NativeStage.LINEAGE_FACTS, - NativeStage.SQL_TEST_GLUE, - NativeStage.PROJECT_ASSEMBLY, - } - ), - expected_disabled=frozenset(), - ) - ], - ids=lambda case: case.description, -) -def test_given_no_engine_selection_when_checking_native_stages_then_every_stage_runs_natively( - test_case: DefaultEngineStageTestCase, monkeypatch: pytest.MonkeyPatch -) -> None: - monkeypatch.delenv(COMPILER_ENGINE_ENV_VAR, raising=False) - - assert {stage: native_stage_enabled(stage) for stage in NativeStage} == { - **dict.fromkeys(test_case.expected_enabled, True), - **dict.fromkeys(test_case.expected_disabled, False), - } - - -@pytest.mark.parametrize( - "test_case", - [ - NativeStageCouplingTestCase( - description=( - "semantic checks normalize types with the native type system unconditionally, " - "while Python only does so where the type system stage runs natively" - ), - dependent=NativeStage.SEMANTIC_CHECKS, - dependency=NativeStage.TYPE_SYSTEM, - expected_engines_without_dependency=frozenset(), - ), - ], - ids=lambda case: case.description, -) -def test_given_coupled_native_stages_when_reading_tiers_then_dependent_never_runs_alone( - test_case: NativeStageCouplingTestCase, -) -> None: - engines: tuple[CompilerEngine, ...] = tuple(ENGINE_NATIVE_STAGE_TIERS) - dependent_engines: frozenset[CompilerEngine] = frozenset( - compress( - engines, - ( - NATIVE_STAGE_TIERS[test_case.dependent] in tiers - for tiers in ENGINE_NATIVE_STAGE_TIERS.values() - ), - ) - ) - dependency_engines: frozenset[CompilerEngine] = frozenset( - compress( - engines, - ( - NATIVE_STAGE_TIERS[test_case.dependency] in tiers - for tiers in ENGINE_NATIVE_STAGE_TIERS.values() - ), - ) - ) - - assert dependent_engines - dependency_engines == (test_case.expected_engines_without_dependency) - - -if __name__ == "__main__": - pytest.main([__file__, "-vv"]) diff --git a/tests/unit/src/sqlbuild/compiler/frontier/test_resolve_compiler_engine.py b/tests/unit/src/sqlbuild/compiler/frontier/test_resolve_compiler_engine.py index 3180d6d89e..1f4e46a8e8 100644 --- a/tests/unit/src/sqlbuild/compiler/frontier/test_resolve_compiler_engine.py +++ b/tests/unit/src/sqlbuild/compiler/frontier/test_resolve_compiler_engine.py @@ -24,9 +24,6 @@ EngineResolutionTestCase( description="empty", raw_value="", expected_engine=CompilerEngine.NATIVE ), - EngineResolutionTestCase( - description="python", raw_value="python", expected_engine=CompilerEngine.PYTHON - ), EngineResolutionTestCase( description="native", raw_value="native", expected_engine=CompilerEngine.NATIVE ), @@ -70,32 +67,39 @@ def test_given_no_engine_variable_when_resolving_then_native_is_the_default( description="unknown", raw_value="rust", expected_message=( - "SQLBUILD_COMPILER_ENGINE must be one of python, native, native-preview " - "(got 'rust')" + "SQLBUILD_COMPILER_ENGINE must be one of native, native-preview (got 'rust')" ), ), EngineErrorTestCase( description="wrong_case", raw_value="Native", expected_message=( - "SQLBUILD_COMPILER_ENGINE must be one of python, native, native-preview " - "(got 'Native')" + "SQLBUILD_COMPILER_ENGINE must be one of native, native-preview (got 'Native')" ), ), EngineErrorTestCase( description="underscored_preview", raw_value="native_preview", expected_message=( - "SQLBUILD_COMPILER_ENGINE must be one of python, native, native-preview " + "SQLBUILD_COMPILER_ENGINE must be one of native, native-preview " "(got 'native_preview')" ), ), + EngineErrorTestCase( + description="removed_python", + raw_value="python", + expected_message=( + "SQLBUILD_COMPILER_ENGINE 'python' is no longer supported: SQLBuild removed its " + "Python compiler, and the native compiler is the default. Unset " + "SQLBUILD_COMPILER_ENGINE and drop --compiler-engine to use it; to run the " + "Python compiler for comparison, pin an earlier SQLBuild release." + ), + ), EngineErrorTestCase( description="padded", raw_value=" python", expected_message=( - "SQLBUILD_COMPILER_ENGINE must be one of python, native, native-preview " - "(got ' python')" + "SQLBUILD_COMPILER_ENGINE must be one of native, native-preview (got ' python')" ), ), ], @@ -116,11 +120,11 @@ def test_given_unknown_engine_when_resolving_then_error_names_accepted_and_curre "test_case", [ EngineOverrideTestCase( - description="python_restored", - previous="python", + description="preview_restored", + previous="native-preview", override=CompilerEngine.NATIVE, expected_inside=CompilerEngine.NATIVE, - expected_after="python", + expected_after="native-preview", ), EngineOverrideTestCase( description="empty_restored", diff --git a/tests/unit/src/sqlbuild/compiler/macro_bridge/classes/test_macro_bridge.py b/tests/unit/src/sqlbuild/compiler/macro_bridge/classes/test_macro_bridge.py index 758149c91a..bcaccfe10c 100644 --- a/tests/unit/src/sqlbuild/compiler/macro_bridge/classes/test_macro_bridge.py +++ b/tests/unit/src/sqlbuild/compiler/macro_bridge/classes/test_macro_bridge.py @@ -7,7 +7,7 @@ import pytest from sqlbuild.compiler.macro_bridge.classes.macro_bridge import MacroBridge -from sqlbuild.compiler.macro_bridge.models import MacroCallSite +from sqlbuild.compiler.macro_bridge.models import MacroCallScan from tests.unit.src.sqlbuild.compiler.macro_bridge.classes._test_types import ( DeepNestingScanTestCase, ) @@ -47,7 +47,10 @@ def test_given_deeply_nested_calls_when_scanning_then_the_bridge_returns_promptl sql: str = "@m(" * test_case.depth + "x" + ")" * test_case.depth started: float = time.perf_counter() - sites: tuple[MacroCallSite, ...] | None = bridge.scan(sql) + scan: MacroCallScan = bridge.scan(sql) assert time.perf_counter() - started < test_case.expected_max_seconds - assert tuple(site.tree_names for site in sites or ()) == test_case.expected_tree_names + assert (tuple(site.tree_names for site in scan.sites), scan.failure) == ( + test_case.expected_tree_names, + None, + ) diff --git a/tests/unit/src/sqlbuild/compiler/planner/_helpers/helpers.py b/tests/unit/src/sqlbuild/compiler/planner/_helpers/helpers.py index bfc3e44d74..98b314f050 100644 --- a/tests/unit/src/sqlbuild/compiler/planner/_helpers/helpers.py +++ b/tests/unit/src/sqlbuild/compiler/planner/_helpers/helpers.py @@ -10,10 +10,10 @@ from types import MappingProxyType from typing import ClassVar +import sqlbuild._native as _native from sqlbuild.adapter.contract.classes.base_adapter import BaseAdapter from sqlbuild.adapter.contract.models import RelationInfo from sqlbuild.compiler.auditing.types import AuditSeverity -from sqlbuild.compiler.compile._helpers.deps.dependencies import audit_scope_deps from sqlbuild.compiler.compile._helpers.sql_tests.core import ( extract_assertion_target_model_names, ) @@ -1378,7 +1378,7 @@ def build_scheduling_audit( return CompiledAudit( key=CompiledObjectKey(resource_type=CompiledResourceType.AUDIT, name=name), definition_name="test_audit", - scope_deps=audit_scope_deps( + scope_deps=native_audit_scope_deps( references=references, attached_target_kind=attached_target_kind, attached_target_name=attached_target_name, @@ -1448,3 +1448,31 @@ def build_seed_identity_compiled_seed( qualified_name="main.orders", ), ) + + +def native_audit_scope_deps( + *, + references: tuple[CompileSqlReference, ...], + attached_target_kind: AttachedAuditTargetKind | None, + attached_target_name: str | None, +) -> tuple[CompiledObjectKey, ...]: + """The audit's scope dependencies as native project assembly derives them.""" + + attached: tuple[str, str] | None = { + True: None, + False: (str(attached_target_kind), str(attached_target_name)), + }[attached_target_kind is None or attached_target_name is None] + audit_row: tuple[list[tuple[str, str, str | None]], tuple[str, str] | None] = ( + [ + (str(reference.ref_kind), reference.ref_name, reference.ref_package) + for reference in references + ], + attached, + ) + audit_deps: list[list[tuple[str, str]]] = _native.assemble_project_resource_facts( + ("generic", None, (None, None, None, None), [], [], [], [], [], [], [audit_row]) + )[4] + return tuple( + CompiledObjectKey(resource_type=CompiledResourceType(kind), name=name) + for kind, name in audit_deps[0] + ) diff --git a/tests/unit/src/sqlbuild/compiler/planner/_helpers/sql_test_assembly/helpers.py b/tests/unit/src/sqlbuild/compiler/planner/_helpers/sql_test_assembly/helpers.py index 295fcc27ba..03f3af6119 100644 --- a/tests/unit/src/sqlbuild/compiler/planner/_helpers/sql_test_assembly/helpers.py +++ b/tests/unit/src/sqlbuild/compiler/planner/_helpers/sql_test_assembly/helpers.py @@ -42,7 +42,7 @@ from sqlbuild.compiler.planner._helpers.sql_tests.assembly import plan_sql_tests from sqlbuild.compiler.planner._helpers.sql_tests.comments import uncommented_pattern_matches from sqlbuild.compiler.planner._helpers.sql_tests.native_planning import ( - plan_and_render_sql_test_artifacts, + plan_compiled_sql_test_artifacts, plan_sql_tests_natively, sql_test_plan_error_messages, ) @@ -142,7 +142,7 @@ def assert_native_artifact_matches_runtime_plan( set_difference_operator=adapter.render_set_difference_operator(), sql_analysis_dialect=adapter.sql_analysis_dialect(), ) - (artifact,) = plan_and_render_sql_test_artifacts( + (artifact,) = plan_compiled_sql_test_artifacts( project=project, tests=(sql_test,), adapter=adapter, diff --git a/tests/unit/src/sqlbuild/compiler/planner/_helpers/sql_test_assembly/test_plan_test.py b/tests/unit/src/sqlbuild/compiler/planner/_helpers/sql_test_assembly/test_plan_test.py index be518b4b4f..789aedcede 100644 --- a/tests/unit/src/sqlbuild/compiler/planner/_helpers/sql_test_assembly/test_plan_test.py +++ b/tests/unit/src/sqlbuild/compiler/planner/_helpers/sql_test_assembly/test_plan_test.py @@ -22,7 +22,7 @@ from sqlbuild.compiler.compile.types import CompiledResourceType, SqlTestMode from sqlbuild.compiler.discovery.models import DiscoveredSqlTestBlock, DiscoveredSqlTestFile from sqlbuild.compiler.planner._helpers.sql_tests.native_planning import ( - plan_and_render_sql_test_artifacts, + plan_compiled_sql_test_artifacts, sql_test_plan_error_messages, ) from sqlbuild.compiler.planner.exceptions import PlannerInputError @@ -1339,7 +1339,7 @@ def test_given_sql_analysis_enabled_when_generated_cte_name_conflicts_then_it_ra sql_analysis_enabled=True, ) with pytest.raises(CompileInputError, match=test_case.expected_error_fragments[0]): - plan_and_render_sql_test_artifacts( + plan_compiled_sql_test_artifacts( project=project, tests=(compiled_test,), adapter=DuckDbAdapter(), @@ -1606,7 +1606,7 @@ def test_given_reference_the_compiler_missed_when_planning_then_it_fails_with_lo compiled_test, project = build_test_and_project(test_case) with pytest.raises(SqlTestReferenceError) as raised: - plan_and_render_sql_test_artifacts( + plan_compiled_sql_test_artifacts( project=project, tests=(compiled_test,), adapter=DuckDbAdapter(),