Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 40 additions & 3 deletions .github/workflows/website.yml
Original file line number Diff line number Diff line change
@@ -1,8 +1,19 @@
name: Website

# Builds the site and checks its links and branding. Manual only, and it never deploys: the site is
# not public yet. Add push and pull_request triggers, and a deploy job, once publishing is approved.
# Builds the playground engine and the site, and checks them. It runs on pull requests that touch
# them and on demand, never on push to main, and it never deploys: the site is not public yet.
# Add a deploy job only once publishing is approved.
on:
pull_request:
paths:
- website/**
- crates/sqlquack-core/**
- crates/sqlquack-duckdb/**
- crates/sqlquack-rules/**
- crates/sqlquack-semantics/**
- crates/sqlquack-snowflake/**
- crates/sqlquack-syntax/**
- .github/workflows/website.yml
workflow_dispatch:

permissions:
Expand All @@ -14,7 +25,7 @@ concurrency:

jobs:
build:
name: Build the website
name: Build the engine and the website
runs-on: ubuntu-24.04
defaults:
run:
Expand All @@ -28,12 +39,38 @@ jobs:
cache: npm
cache-dependency-path: website/package-lock.json

- name: Install the pinned Rust toolchain with the wasm32 target
working-directory: .
run: |
rustup toolchain install
rustup target add wasm32-unknown-unknown

- uses: Swatinem/rust-cache@v2
with:
workspaces: website/wasm

- uses: taiki-e/install-action@v2
with:
tool: wasm-bindgen-cli@0.2.130

- name: Check the diagnostics reference matches the registry
run: python3 scripts/generate_diagnostics.py --check

- name: Lint the engine
working-directory: website/wasm
run: |
cargo fmt --check
cargo clippy --locked --target wasm32-unknown-unknown --release -- -D warnings

- name: Install dependencies
run: npm ci

- name: Build the engine
run: ./scripts/build_engine.sh

- name: Test the engine and its spans
run: npm run -s test:engine

- name: Build
run: npm run build

Expand Down
2 changes: 2 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

13 changes: 13 additions & 0 deletions crates/sqlquack-policy/src/policy/models.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
//! The policy schema. Every struct rejects unknown keys.

use std::collections::BTreeMap;
use std::str::FromStr;

use serde::{Deserialize, Serialize};

use crate::policy::_helpers::parsing::parse_policy;
use crate::policy::errors::PolicyError;

/// The whole policy file.
#[derive(Clone, Debug, PartialEq, Deserialize)]
#[serde(deny_unknown_fields)]
Expand Down Expand Up @@ -216,3 +220,12 @@ pub enum PatternArgument {
/// A lower-case name bound by the first match.
Variable(String),
}

/// A policy file's text, validated as `load_policy` validates a file; for callers without files.
impl FromStr for Policy {
type Err = PolicyError;

fn from_str(text: &str) -> Result<Self, Self::Err> {
parse_policy(text)
}
}
1 change: 1 addition & 0 deletions crates/sqlquack-polyglot-check/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ sqlquack.workspace = true
sqlquack-core.workspace = true
sqlquack-evidence.workspace = true
sqlquack-policy.workspace = true
sqlquack-rules.workspace = true
sqlquack-syntax.workspace = true
toml.workspace = true
walkdir.workspace = true
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@

use std::path::Path;

use sqlquack::analysis::main::conversion_options::conversion_options;
use sqlquack::analysis::models::PipelineConverter;
use sqlquack_evidence::cases::main::load_cases::load_cases;
use sqlquack_evidence::verify::models::Conversion;
use sqlquack_evidence::verify::types::CaseConverter;
use sqlquack_policy::policy::main::load_policy::load_policy;
use sqlquack_rules::session::main::conversion_options::conversion_options;
use sqlquack_syntax::Dialect;

use crate::corpora::models::CorpusEntry;
Expand Down
1 change: 1 addition & 0 deletions crates/sqlquack-rules/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ serde.workspace = true
serde_json.workspace = true
sqlquack-core.workspace = true
sqlquack-duckdb.workspace = true
sqlquack-policy.workspace = true
sqlquack-semantics.workspace = true
sqlquack-snowflake.workspace = true
sqlquack-syntax.workspace = true
Expand Down
1 change: 1 addition & 0 deletions crates/sqlquack-rules/src/conversion/main/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@ pub mod convert_statement;
pub mod override_macro;
pub mod override_macro_name;
pub mod quoted_exclusions;
pub mod within_budget;
43 changes: 43 additions & 0 deletions crates/sqlquack-rules/src/conversion/main/within_budget.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
//! `within_budget`: a conversion, or a refusal when converting it outran its time or size budget.

use std::time::Duration;

use sqlquack_core::refusals::models::{Refusal, RefusalCategory};

use crate::conversion::models::{ConversionOptions, Converted};

/// `converted`, or a refusal when converting it outran the time or size budget.
pub fn within_budget(
converted: Converted,
(source, elapsed): (&str, Duration),
options: &ConversionOptions,
) -> Result<Converted, Refusal> {
let budget = options.budget;
let emitted = converted.sql.len() as u64;
let allowed = budget
.minimum_bytes
.max((source.len() as u64).saturating_mul(budget.size_ratio));
let reason = if elapsed > Duration::from_millis(budget.milliseconds) {
format!(
"converting the statement took {} ms, beyond the budget of {} ms",
elapsed.as_millis(),
budget.milliseconds
)
} else if emitted > allowed {
format!(
"the DuckDB SQL is {emitted} bytes for {} bytes of source, beyond the budget of \
{allowed} bytes ({} times the source, at least {})",
source.len(),
budget.size_ratio,
budget.minimum_bytes
)
} else {
return Ok(converted);
};
Err(Refusal {
construct: None,
location: None,
category: RefusalCategory::ConversionBudget,
reason,
})
}
1 change: 1 addition & 0 deletions crates/sqlquack-rules/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@

pub mod catalogue;
pub mod conversion;
pub mod session;
1 change: 1 addition & 0 deletions crates/sqlquack-rules/src/session/_helpers/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
pub(crate) mod session_profiles;
4 changes: 4 additions & 0 deletions crates/sqlquack-rules/src/session/constants.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
//! Session constants.

/// The profile name reported when the built-in default stands in for a policy.
pub const BUILTIN_PROFILE: &str = "the built-in default";
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
//! `confirm_utc_session`: conversion options trusting the caller's word that sessions run in UTC.

use crate::conversion::constants::SESSION_TIMEZONE_UTC;
use crate::conversion::models::{AllowedDivergence, ConversionOptions};
use sqlquack_policy::policy::models::Policy;
use sqlquack_rules::conversion::constants::SESSION_TIMEZONE_UTC;
use sqlquack_rules::conversion::models::{AllowedDivergence, ConversionOptions};

/// `options` relying on `session_timezone_utc` in any mode: the caller confirmed UTC sessions.
pub fn confirm_utc_session(mut options: ConversionOptions, policy: &Policy) -> ConversionOptions {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
//! `conversion_options`: the known divergences the policy allows in one mode, and its budget.

use crate::conversion::models::{AllowedDivergence, ConversionBudget, ConversionOptions};
use sqlquack_policy::policy::models::{DivergenceMode, Policy};
use sqlquack_rules::conversion::models::{AllowedDivergence, ConversionBudget, ConversionOptions};

/// The divergences `policy` converts with a warning, in strict mode or by default.
pub fn conversion_options(policy: &Policy, strict: bool) -> ConversionOptions {
Expand Down
4 changes: 4 additions & 0 deletions crates/sqlquack-rules/src/session/main/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
pub mod confirm_utc_session;
pub mod conversion_options;
pub mod parse_session;
pub mod session_conversion_options;
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
use std::collections::BTreeMap;

/// `NAME=VALUE` settings as upper-case names to values; empty or conflicting names are an error.
pub(crate) fn parse_session(settings: &[String]) -> Result<BTreeMap<String, String>, String> {
pub fn parse_session(settings: &[String]) -> Result<BTreeMap<String, String>, String> {
let mut parameters: BTreeMap<String, String> = BTreeMap::new();
for setting in settings {
let (name, value) = setting
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,17 @@

use std::collections::BTreeMap;

use crate::conversion::constants::SESSION_TIMEZONE_UTC;
use crate::conversion::models::ConversionOptions;
use sqlquack_policy::policy::constants::{
DEFAULT_SESSION_PROFILE, QUOTED_IDENTIFIERS_IGNORE_CASE, SESSION_TIME_ZONE, TIMEZONE_PARAMETER,
};
use sqlquack_policy::policy::models::{Policy, SessionValue};
use sqlquack_rules::conversion::constants::SESSION_TIMEZONE_UTC;
use sqlquack_rules::conversion::models::ConversionOptions;

use crate::analysis::_helpers::session_profiles::{matching_profile, value_text};
use crate::analysis::constants::BUILTIN_PROFILE;
use crate::analysis::main::confirm_utc_session::confirm_utc_session;
use crate::analysis::main::conversion_options::conversion_options;
use crate::session::_helpers::session_profiles::{matching_profile, value_text};
use crate::session::constants::BUILTIN_PROFILE;
use crate::session::main::confirm_utc_session::confirm_utc_session;
use crate::session::main::conversion_options::conversion_options;

/// Options for a session with `parameters`, under the recorded profile they match, and its name.
pub fn session_conversion_options(
Expand Down
5 changes: 5 additions & 0 deletions crates/sqlquack-rules/src/session/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
//! A caller's policy and Snowflake session parameters as conversion options.

pub(crate) mod _helpers;
pub mod constants;
pub mod main;
1 change: 1 addition & 0 deletions crates/sqlquack-semantics/src/types/_helpers/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
pub(crate) mod schema_file;
Loading
Loading