@sqlanvil/cli 1.25.1 → 1.26.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bundle.js +228 -15
- package/package.json +1 -1
package/bundle.js
CHANGED
|
@@ -50646,7 +50646,7 @@ function collectEvaluationQueries(queryOrAction, concatenate, queryModifier = (q
|
|
|
50646
50646
|
.filter(validationQuery => !!validationQuery.query);
|
|
50647
50647
|
}
|
|
50648
50648
|
|
|
50649
|
-
const version = "1.
|
|
50649
|
+
const version = "1.26.0";
|
|
50650
50650
|
const dataformVersion = "3.0.61";
|
|
50651
50651
|
|
|
50652
50652
|
async function build(compiledGraph, runConfig, dbadapter) {
|
|
@@ -54883,6 +54883,9 @@ async function migrateDataform(opts) {
|
|
|
54883
54883
|
};
|
|
54884
54884
|
if (sourceConfig.vars)
|
|
54885
54885
|
settings.vars = sourceConfig.vars;
|
|
54886
|
+
if (isBigQueryTarget) {
|
|
54887
|
+
settings.environments = { test: { schemaSuffix: "test" } };
|
|
54888
|
+
}
|
|
54886
54889
|
if (report.connections.length > 0) {
|
|
54887
54890
|
settings.connections = Object.fromEntries(report.connections.map(c => {
|
|
54888
54891
|
var _a;
|
|
@@ -54898,6 +54901,33 @@ async function migrateDataform(opts) {
|
|
|
54898
54901
|
}));
|
|
54899
54902
|
}
|
|
54900
54903
|
writer.write("workflow_settings.yaml", jsYaml.dump(settings));
|
|
54904
|
+
if (isBigQueryTarget && sourceConfig.defaultProject) {
|
|
54905
|
+
const adcCredentials = { projectId: sourceConfig.defaultProject };
|
|
54906
|
+
if (sourceConfig.defaultLocation) {
|
|
54907
|
+
adcCredentials.location = sourceConfig.defaultLocation;
|
|
54908
|
+
}
|
|
54909
|
+
writer.write(".df-credentials.json", `${JSON.stringify(adcCredentials, null, 2)}\n`);
|
|
54910
|
+
report.files.push({
|
|
54911
|
+
file: ".df-credentials.json",
|
|
54912
|
+
action: "generated",
|
|
54913
|
+
status: "clean",
|
|
54914
|
+
findings: []
|
|
54915
|
+
});
|
|
54916
|
+
const gitignorePath = path__namespace.join(outDir, ".gitignore");
|
|
54917
|
+
const existingGitignore = fs__namespace$1.existsSync(gitignorePath)
|
|
54918
|
+
? fs__namespace$1.readFileSync(gitignorePath, "utf8")
|
|
54919
|
+
: "";
|
|
54920
|
+
if (!existingGitignore.includes(".df-credentials")) {
|
|
54921
|
+
const separator = existingGitignore === "" || existingGitignore.endsWith("\n") ? "" : "\n";
|
|
54922
|
+
fs__namespace$1.writeFileSync(gitignorePath, `${existingGitignore}${separator}.df-credentials*.json\n`);
|
|
54923
|
+
report.files.push({
|
|
54924
|
+
file: ".gitignore",
|
|
54925
|
+
action: existingGitignore === "" ? "generated" : "updated",
|
|
54926
|
+
status: "clean",
|
|
54927
|
+
findings: []
|
|
54928
|
+
});
|
|
54929
|
+
}
|
|
54930
|
+
}
|
|
54901
54931
|
if (!fs__namespace$1.existsSync(path__namespace.join(outDir, "AGENTS.md"))) {
|
|
54902
54932
|
writer.write("AGENTS.md", agentsMdContents({
|
|
54903
54933
|
warehouse: targetWarehouse,
|
|
@@ -55008,11 +55038,17 @@ function renderReportMd(r) {
|
|
|
55008
55038
|
lines.push("");
|
|
55009
55039
|
if (r.targetWarehouse === "bigquery") {
|
|
55010
55040
|
lines.push(`1. \`sqlanvil compile\` — should already succeed.`);
|
|
55011
|
-
lines.push(`2.
|
|
55012
|
-
`
|
|
55013
|
-
|
|
55014
|
-
|
|
55015
|
-
lines.push(`
|
|
55041
|
+
lines.push(`2. Authenticate the same way Dataform runs locally: \`gcloud auth application-default ` +
|
|
55042
|
+
`login\` (ADC). A secretless \`.df-credentials.json\` (project + location only) was ` +
|
|
55043
|
+
`generated for you — nothing else is needed. Service-account keys and keyless ` +
|
|
55044
|
+
`\`accessToken\` auth are supported for CI (see the BigQuery guide).`);
|
|
55045
|
+
lines.push(`3. \`sqlanvil validate\` — read-only: dry-runs every model against BigQuery without ` +
|
|
55046
|
+
`executing; all-PASS means the swap is complete.`);
|
|
55047
|
+
lines.push(`4. First real run in the scaffolded TEST environment — \`sqlanvil run . --environment ` +
|
|
55048
|
+
`test\` writes to \`<dataset>_test\` datasets, leaving production untouched. To land ` +
|
|
55049
|
+
`tests in a separate GCP project instead, set \`environments.test.defaultDatabase\` in ` +
|
|
55050
|
+
`workflow_settings.yaml. Once verified: \`sqlanvil run .\`.`);
|
|
55051
|
+
lines.push(`5. Compare \`sqlanvil compile\` output with \`dataform compile\` on the source for a ` +
|
|
55016
55052
|
`sample of actions — they should match apart from the compile-global rename.`);
|
|
55017
55053
|
}
|
|
55018
55054
|
else {
|
|
@@ -55564,6 +55600,14 @@ const CREDS_SSLMODE_QUESTION = "SSL mode? (disable/require)";
|
|
|
55564
55600
|
const CONVERT_SOURCE_QUESTION = "Path to the Dataform project to convert (read-only, never modified)?";
|
|
55565
55601
|
const CONVERT_OUT_QUESTION = "Directory for the converted sqlanvil project (created; must be empty)?";
|
|
55566
55602
|
const CONVERT_TARGET_QUESTION = "Target warehouse? (bigquery = keep running on BigQuery, tooling swap only; supabase/postgres = move off BigQuery)";
|
|
55603
|
+
const BQ_AUTH_QUESTION = "How should local runs authenticate to BigQuery? (adc = gcloud Application Default " +
|
|
55604
|
+
"Credentials, like Dataform local runs; key = service-account key file; later)";
|
|
55605
|
+
const BQ_AUTH_LOGIN_QUESTION = "No Application Default Credentials found. Run `gcloud auth application-default login` now?";
|
|
55606
|
+
const BQ_KEY_PATH_QUESTION = "Path to the service-account key JSON file?";
|
|
55607
|
+
const BQ_TEST_TARGET_QUESTION = "Where should test runs land before you touch production? (suffix = same project, " +
|
|
55608
|
+
"`<dataset>_test` datasets; project = a separate GCP project; none = no test environment)";
|
|
55609
|
+
const BQ_TEST_SUFFIX_QUESTION = "Dataset suffix for the test environment?";
|
|
55610
|
+
const BQ_TEST_PROJECT_QUESTION = "GCP project ID for the test environment?";
|
|
55567
55611
|
const SUPABASE_POOLER_HINT = "Use the SESSION POOLER connection (Supabase Dashboard -> Connect -> Session pooler): host " +
|
|
55568
55612
|
"aws-<n>-<region>.pooler.supabase.com, user postgres.<project-ref>. The direct " +
|
|
55569
55613
|
"db.<ref>.supabase.co host is IPv6-only and unreachable from most networks.";
|
|
@@ -55668,7 +55712,104 @@ function ensureGitignoreCoversCredentials(dir) {
|
|
|
55668
55712
|
const separator = existing === "" || existing.endsWith("\n") ? "" : "\n";
|
|
55669
55713
|
fs__namespace$1.writeFileSync(gitignorePath, `${existing}${separator}.df-credentials*.json\n`);
|
|
55670
55714
|
}
|
|
55715
|
+
function detectAdc() {
|
|
55716
|
+
if (process.env.DATAFORM_CLI_TEST_INPUTS !== undefined) {
|
|
55717
|
+
return false;
|
|
55718
|
+
}
|
|
55719
|
+
try {
|
|
55720
|
+
const result = childProcess.spawnSync("gcloud", ["auth", "application-default", "print-access-token"], {
|
|
55721
|
+
stdio: "ignore",
|
|
55722
|
+
timeout: 15000
|
|
55723
|
+
});
|
|
55724
|
+
return result.status === 0;
|
|
55725
|
+
}
|
|
55726
|
+
catch (e) {
|
|
55727
|
+
return false;
|
|
55728
|
+
}
|
|
55729
|
+
}
|
|
55730
|
+
function runBigQueryAuthStep(projectDir) {
|
|
55731
|
+
const mode = askChoice(BQ_AUTH_QUESTION, ["adc", "key", "later"], "adc");
|
|
55732
|
+
if (mode === "adc") {
|
|
55733
|
+
if (detectAdc()) {
|
|
55734
|
+
printSuccess("Application Default Credentials detected — runs authenticate as your gcloud account.");
|
|
55735
|
+
return;
|
|
55736
|
+
}
|
|
55737
|
+
if (askYesNo(BQ_AUTH_LOGIN_QUESTION, true)) {
|
|
55738
|
+
childProcess.spawnSync("gcloud", ["auth", "application-default", "login"], { stdio: "inherit" });
|
|
55739
|
+
if (detectAdc()) {
|
|
55740
|
+
printSuccess("ADC configured — runs authenticate as your gcloud account.");
|
|
55741
|
+
return;
|
|
55742
|
+
}
|
|
55743
|
+
}
|
|
55744
|
+
print("Run `gcloud auth application-default login` before `sqlanvil validate` / `run` — no " +
|
|
55745
|
+
"other credential setup is needed.");
|
|
55746
|
+
return;
|
|
55747
|
+
}
|
|
55748
|
+
if (mode === "key") {
|
|
55749
|
+
for (let attempt = 0; attempt < MAX_ATTEMPTS; attempt++) {
|
|
55750
|
+
const keyPath = actuallyResolve(askRequired(BQ_KEY_PATH_QUESTION));
|
|
55751
|
+
if (!fs__namespace$1.existsSync(keyPath)) {
|
|
55752
|
+
printError(`${keyPath} does not exist.`);
|
|
55753
|
+
continue;
|
|
55754
|
+
}
|
|
55755
|
+
try {
|
|
55756
|
+
const keyContents = fs__namespace$1.readFileSync(keyPath, "utf8");
|
|
55757
|
+
const parsed = JSON.parse(keyContents);
|
|
55758
|
+
if (!parsed.client_email) {
|
|
55759
|
+
printError(`${keyPath} does not look like a service-account key (no client_email).`);
|
|
55760
|
+
continue;
|
|
55761
|
+
}
|
|
55762
|
+
const credentialsPath = path__namespace.join(projectDir, CREDENTIALS_FILENAME);
|
|
55763
|
+
const existing = fs__namespace$1.existsSync(credentialsPath)
|
|
55764
|
+
? JSON.parse(fs__namespace$1.readFileSync(credentialsPath, "utf8"))
|
|
55765
|
+
: {};
|
|
55766
|
+
ensureGitignoreCoversCredentials(projectDir);
|
|
55767
|
+
fs__namespace$1.writeFileSync(credentialsPath, `${JSON.stringify(Object.assign(Object.assign({}, existing), { credentials: keyContents }), null, 2)}\n`);
|
|
55768
|
+
printSuccess(`Runs authenticate as ${parsed.client_email} (key embedded in the gitignored ` +
|
|
55769
|
+
`${CREDENTIALS_FILENAME}).`);
|
|
55770
|
+
return;
|
|
55771
|
+
}
|
|
55772
|
+
catch (e) {
|
|
55773
|
+
printError(`Could not read ${keyPath}: ${e instanceof Error ? e.message : e}`);
|
|
55774
|
+
}
|
|
55775
|
+
}
|
|
55776
|
+
return;
|
|
55777
|
+
}
|
|
55778
|
+
print("Skipped. Before `sqlanvil validate` / `run`: `gcloud auth application-default login`, or " +
|
|
55779
|
+
`add a service-account key as the \`credentials\` field of ${CREDENTIALS_FILENAME}.`);
|
|
55780
|
+
}
|
|
55781
|
+
function runBigQueryTestTargetStep(projectDir) {
|
|
55782
|
+
var _a;
|
|
55783
|
+
const choice = askChoice(BQ_TEST_TARGET_QUESTION, ["suffix", "project", "none"], "suffix");
|
|
55784
|
+
const settingsPath = path__namespace.join(projectDir, "workflow_settings.yaml");
|
|
55785
|
+
const settings = (jsYaml.load(fs__namespace$1.readFileSync(settingsPath, "utf8")) || {});
|
|
55786
|
+
if (choice === "none") {
|
|
55787
|
+
if ((_a = settings.environments) === null || _a === void 0 ? void 0 : _a.test) {
|
|
55788
|
+
delete settings.environments.test;
|
|
55789
|
+
if (Object.keys(settings.environments).length === 0) {
|
|
55790
|
+
delete settings.environments;
|
|
55791
|
+
}
|
|
55792
|
+
fs__namespace$1.writeFileSync(settingsPath, jsYaml.dump(settings));
|
|
55793
|
+
}
|
|
55794
|
+
print("No test environment — runs go straight to the configured datasets.");
|
|
55795
|
+
return;
|
|
55796
|
+
}
|
|
55797
|
+
const testEnv = {};
|
|
55798
|
+
if (choice === "suffix") {
|
|
55799
|
+
testEnv.schemaSuffix = ask(BQ_TEST_SUFFIX_QUESTION, "test");
|
|
55800
|
+
}
|
|
55801
|
+
else {
|
|
55802
|
+
testEnv.defaultDatabase = askRequired(BQ_TEST_PROJECT_QUESTION);
|
|
55803
|
+
}
|
|
55804
|
+
settings.environments = Object.assign(Object.assign({}, (settings.environments || {})), { test: testEnv });
|
|
55805
|
+
fs__namespace$1.writeFileSync(settingsPath, jsYaml.dump(settings));
|
|
55806
|
+
printSuccess(choice === "suffix"
|
|
55807
|
+
? `Test runs write to \`<dataset>_${testEnv.schemaSuffix}\` datasets ` +
|
|
55808
|
+
`(sqlanvil run . --environment test).`
|
|
55809
|
+
: `Test runs land in project ${testEnv.defaultDatabase} (sqlanvil run . --environment test).`);
|
|
55810
|
+
}
|
|
55671
55811
|
async function runConvertFlow() {
|
|
55812
|
+
var _a;
|
|
55672
55813
|
let srcDir = "";
|
|
55673
55814
|
for (let attempt = 0; attempt < MAX_ATTEMPTS; attempt++) {
|
|
55674
55815
|
const candidate = actuallyResolve(askRequired(CONVERT_SOURCE_QUESTION));
|
|
@@ -55687,11 +55828,23 @@ async function runConvertFlow() {
|
|
|
55687
55828
|
const report = await migrateDataform({ srcDir, outDir, targetWarehouse });
|
|
55688
55829
|
printMigrationSummary(report, outDir);
|
|
55689
55830
|
if (targetWarehouse === "bigquery") {
|
|
55831
|
+
print("");
|
|
55832
|
+
runBigQueryAuthStep(outDir);
|
|
55833
|
+
print("");
|
|
55834
|
+
runBigQueryTestTargetStep(outDir);
|
|
55835
|
+
const hasTestEnv = fs__namespace$1.existsSync(path__namespace.join(outDir, "workflow_settings.yaml"))
|
|
55836
|
+
? !!((_a = (jsYaml.load(fs__namespace$1.readFileSync(path__namespace.join(outDir, "workflow_settings.yaml"), "utf8")) || {}).environments) === null || _a === void 0 ? void 0 : _a.test)
|
|
55837
|
+
: false;
|
|
55690
55838
|
print("\nNext steps:");
|
|
55691
55839
|
print(` 1. sqlanvil compile ${outDir}`);
|
|
55692
|
-
print(
|
|
55693
|
-
|
|
55694
|
-
|
|
55840
|
+
print(` 2. sqlanvil validate ${outDir} (read-only dry-run of every model; all-PASS = swap complete)`);
|
|
55841
|
+
if (hasTestEnv) {
|
|
55842
|
+
print(` 3. sqlanvil run ${outDir} --environment test (first real run — production untouched)`);
|
|
55843
|
+
print(` 4. sqlanvil run ${outDir} (once the test run is verified)`);
|
|
55844
|
+
}
|
|
55845
|
+
else {
|
|
55846
|
+
print(` 3. sqlanvil run ${outDir}`);
|
|
55847
|
+
}
|
|
55695
55848
|
return 0;
|
|
55696
55849
|
}
|
|
55697
55850
|
if (askYesNo(INIT_CONFIGURE_CREDS_QUESTION, true)) {
|
|
@@ -55730,10 +55883,17 @@ async function runFreshFlow(defaultProjectDir) {
|
|
|
55730
55883
|
credentialsJson
|
|
55731
55884
|
});
|
|
55732
55885
|
printInitResult(result);
|
|
55733
|
-
const steps = [];
|
|
55734
55886
|
if (warehouse === "bigquery") {
|
|
55735
|
-
|
|
55887
|
+
const credentialsPath = path__namespace.join(projectDir, CREDENTIALS_FILENAME);
|
|
55888
|
+
if (!fs__namespace$1.existsSync(credentialsPath)) {
|
|
55889
|
+
ensureGitignoreCoversCredentials(projectDir);
|
|
55890
|
+
fs__namespace$1.writeFileSync(credentialsPath, `${JSON.stringify(Object.assign({ projectId: projectConfig.defaultDatabase }, (projectConfig.defaultLocation ? { location: projectConfig.defaultLocation } : {})), null, 2)}\n`);
|
|
55891
|
+
}
|
|
55892
|
+
print("");
|
|
55893
|
+
runBigQueryAuthStep(projectDir);
|
|
55736
55894
|
}
|
|
55895
|
+
const steps = [];
|
|
55896
|
+
if (warehouse === "bigquery") ;
|
|
55737
55897
|
else if (!credentialsJson) {
|
|
55738
55898
|
steps.push(`Edit ${CREDENTIALS_FILENAME} (gitignored) with your warehouse credentials.`);
|
|
55739
55899
|
}
|
|
@@ -55992,6 +56152,28 @@ function dependencyBlocked(dependencyKeys, statusByKey) {
|
|
|
55992
56152
|
return status !== undefined && status !== "PASS";
|
|
55993
56153
|
});
|
|
55994
56154
|
}
|
|
56155
|
+
function rewriteSelfReferences(graph, shadowSuffix, resolveTarget) {
|
|
56156
|
+
var _a;
|
|
56157
|
+
const suffix = `_${shadowSuffix}`;
|
|
56158
|
+
for (const action of [...(graph.tables || []), ...(graph.assertions || [])]) {
|
|
56159
|
+
const target = action.target;
|
|
56160
|
+
if (!((_a = target === null || target === void 0 ? void 0 : target.schema) === null || _a === void 0 ? void 0 : _a.endsWith(suffix))) {
|
|
56161
|
+
continue;
|
|
56162
|
+
}
|
|
56163
|
+
const prodTarget = sqlanvil.Target.create(Object.assign(Object.assign({}, target), { schema: target.schema.slice(0, -suffix.length) }));
|
|
56164
|
+
const shadowName = resolveTarget(target);
|
|
56165
|
+
const prodName = resolveTarget(prodTarget);
|
|
56166
|
+
const rewrite = (sql) => sql.split(shadowName).join(prodName);
|
|
56167
|
+
if (action.query) {
|
|
56168
|
+
action.query = rewrite(action.query);
|
|
56169
|
+
}
|
|
56170
|
+
const table = action;
|
|
56171
|
+
if (table.incrementalQuery) {
|
|
56172
|
+
table.incrementalQuery = rewrite(table.incrementalQuery);
|
|
56173
|
+
}
|
|
56174
|
+
}
|
|
56175
|
+
return graph;
|
|
56176
|
+
}
|
|
55995
56177
|
const VALIDATE_SHADOW_PREFIX = "sqlanvil_validate_";
|
|
55996
56178
|
function validateShadowSuffix(nowMs) {
|
|
55997
56179
|
return `${VALIDATE_SHADOW_PREFIX}${nowMs}`;
|
|
@@ -56035,6 +56217,22 @@ function tableType(enumType) {
|
|
|
56035
56217
|
function depKeys(deps) {
|
|
56036
56218
|
return (deps || []).map(targetKey);
|
|
56037
56219
|
}
|
|
56220
|
+
function stripOps(table) {
|
|
56221
|
+
const bare = sqlanvil.Table.create(table);
|
|
56222
|
+
bare.preOps = [];
|
|
56223
|
+
bare.postOps = [];
|
|
56224
|
+
bare.incrementalPreOps = [];
|
|
56225
|
+
bare.incrementalPostOps = [];
|
|
56226
|
+
return bare;
|
|
56227
|
+
}
|
|
56228
|
+
function collectOps(table) {
|
|
56229
|
+
return [
|
|
56230
|
+
...(table.preOps || []),
|
|
56231
|
+
...(table.postOps || []),
|
|
56232
|
+
...(table.incrementalPreOps || []),
|
|
56233
|
+
...(table.incrementalPostOps || [])
|
|
56234
|
+
].filter(op => !!op && !!op.trim());
|
|
56235
|
+
}
|
|
56038
56236
|
async function validate(compiledGraph, deps, options = {}) {
|
|
56039
56237
|
const nodes = [];
|
|
56040
56238
|
for (const table of compiledGraph.tables || []) {
|
|
@@ -56119,20 +56317,33 @@ async function validate(compiledGraph, deps, options = {}) {
|
|
|
56119
56317
|
results.push({ target: node.target, type: node.type, status: "BLOCKED", errors: [] });
|
|
56120
56318
|
continue;
|
|
56121
56319
|
}
|
|
56320
|
+
const evaluationAction = node.kind === "table" ? stripOps(node.table) : node.action;
|
|
56122
56321
|
const evaluations = node.kind === "script"
|
|
56123
56322
|
? await deps.checkScript(node.script)
|
|
56124
|
-
: await deps.evaluate(
|
|
56323
|
+
: await deps.evaluate(evaluationAction);
|
|
56125
56324
|
const failed = evaluations.some(e => e.status === sqlanvil.QueryEvaluation.QueryEvaluationStatus.FAILURE);
|
|
56126
|
-
|
|
56127
|
-
|
|
56128
|
-
results.push({ target: node.target, type: node.type, status, errors: evaluations });
|
|
56325
|
+
let status = failed ? "FAILURE" : "PASS";
|
|
56326
|
+
let stubCreated = false;
|
|
56129
56327
|
if (status === "PASS" && node.kind === "table") {
|
|
56130
56328
|
try {
|
|
56131
56329
|
await deps.execute(deps.validationStubSql(node.table));
|
|
56330
|
+
stubCreated = true;
|
|
56132
56331
|
}
|
|
56133
56332
|
catch (e) {
|
|
56134
56333
|
}
|
|
56135
56334
|
}
|
|
56335
|
+
if (status === "PASS" && node.kind === "table" && stubCreated && deps.evaluateOp) {
|
|
56336
|
+
for (const op of collectOps(node.table)) {
|
|
56337
|
+
const opEvaluations = await deps.evaluateOp(op);
|
|
56338
|
+
evaluations.push(...opEvaluations);
|
|
56339
|
+
if (opEvaluations.some(e => e.status === sqlanvil.QueryEvaluation.QueryEvaluationStatus.FAILURE)) {
|
|
56340
|
+
status = "FAILURE";
|
|
56341
|
+
break;
|
|
56342
|
+
}
|
|
56343
|
+
}
|
|
56344
|
+
}
|
|
56345
|
+
statusByKey.set(node.key, status);
|
|
56346
|
+
results.push({ target: node.target, type: node.type, status, errors: evaluations });
|
|
56136
56347
|
}
|
|
56137
56348
|
}
|
|
56138
56349
|
finally {
|
|
@@ -57203,6 +57414,7 @@ async function runValidate(argv) {
|
|
|
57203
57414
|
tags: argv[tagsOption.name]
|
|
57204
57415
|
});
|
|
57205
57416
|
const executionSql = new ExecutionSql(compiledGraph.projectConfig, dataformVersion);
|
|
57417
|
+
rewriteSelfReferences(prunedGraph, shadowSuffix, target => executionSql.resolveTarget(target));
|
|
57206
57418
|
const shadowSchemas = Array.from(new Set((prunedGraph.tables || []).map(table => table.target.schema)));
|
|
57207
57419
|
process.on("SIGINT", () => {
|
|
57208
57420
|
Promise.all(shadowSchemas.map(schema => dbadapter.execute(executionSql.dropSchemaCascadeSql(schema)).catch(() => undefined))).then(() => process.exit(1));
|
|
@@ -57211,6 +57423,7 @@ async function runValidate(argv) {
|
|
|
57211
57423
|
evaluate: action => dbadapter.evaluate(action.enumType !== undefined
|
|
57212
57424
|
? sqlanvil.Table.create(action)
|
|
57213
57425
|
: sqlanvil.Assertion.create(action)),
|
|
57426
|
+
evaluateOp: warehouse === "bigquery" ? (sql) => dbadapter.evaluate(sql) : undefined,
|
|
57214
57427
|
execute: sql => dbadapter.execute(sql).then(() => undefined),
|
|
57215
57428
|
validationStubSql: table => executionSql.validationStubSql(table),
|
|
57216
57429
|
createSchemaSql: schema => executionSql.createSchemaSql(schema),
|