Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[D1] add a json option to execute #2627

Merged
merged 17 commits into from
Jan 27, 2023
Merged
Show file tree
Hide file tree
Changes from 5 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
5 changes: 5 additions & 0 deletions .changeset/wicked-lies-itch.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"wrangler": patch
---

fix: implement `d1 execute --json` with clean output for piping into other commands
2 changes: 2 additions & 0 deletions fixtures/d1-worker-app/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
dist
.wrangler
3 changes: 3 additions & 0 deletions fixtures/d1-worker-app/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Notes about testing with this fixture

- For some reason, miniflare requires node 16 to be able to run `wrangler dev --local`
rozenmd marked this conversation as resolved.
Show resolved Hide resolved
16 changes: 16 additions & 0 deletions fixtures/d1-worker-app/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"name": "d1-worker-app",
"version": "1.0.0",
"private": true,
"description": "",
"license": "ISC",
"author": "",
"main": "src/index.js",
"scripts": {
"check:type": "tsc",
"db:query": "wrangler d1 execute UPDATE_THIS_FOR_REMOTE_USE --local --command='SELECT * FROM Customers'",
"db:query-json": "wrangler d1 execute UPDATE_THIS_FOR_REMOTE_USE --local --command='SELECT * FROM Customers' --json",
"db:reset": "wrangler d1 execute UPDATE_THIS_FOR_REMOTE_USE --local --file=./schema.sql",
"start": "wrangler dev --local"
}
}
3 changes: 3 additions & 0 deletions fixtures/d1-worker-app/schema.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
DROP TABLE IF EXISTS Customers;
CREATE TABLE Customers (CustomerID INT, CompanyName TEXT, ContactName TEXT, PRIMARY KEY (`CustomerID`));
INSERT INTO Customers (CustomerID, CompanyName, ContactName) VALUES (1, 'Alfreds Futterkiste', 'Maria Anders'), (4, 'Around the Horn', 'Thomas Hardy'), (11, 'Bs Beverages', 'Victoria Ashworth'), (13, 'Bs Beverages', 'Random Name');
5 changes: 5 additions & 0 deletions fixtures/d1-worker-app/src/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export default {
async fetch(request) {
return new Response(`Hello world!`);
},
};
12 changes: 12 additions & 0 deletions fixtures/d1-worker-app/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"compilerOptions": {
"target": "ES2020",
"esModuleInterop": true,
"module": "CommonJS",
"lib": ["ES2020"],
"types": ["node"],
"moduleResolution": "node",
"noEmit": true
},
"include": ["tests", "../../node-types.d.ts"]
}
9 changes: 9 additions & 0 deletions fixtures/d1-worker-app/wrangler.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
name = "worker-app"
main = "src/index.js"
compatibility_date = "2022-03-31"

[[d1_databases]]
binding = "DB" # i.e. available in your Worker on env.DB
database_name = "UPDATE_THIS_FOR_REMOTE_USE"
preview_database_id = "UPDATE_THIS_FOR_REMOTE_USE"
database_id = "UPDATE_THIS_FOR_REMOTE_USE"
2 changes: 1 addition & 1 deletion packages/wrangler/src/config/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ export function readConfig<CommandArgs>(
args
);

if (diagnostics.hasWarnings()) {
if (diagnostics.hasWarnings() && !args?.json) {
rozenmd marked this conversation as resolved.
Show resolved Hide resolved
logger.warn(diagnostics.renderWarnings());
}
if (diagnostics.hasErrors()) {
Expand Down
50 changes: 37 additions & 13 deletions packages/wrangler/src/d1/execute.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,11 @@ export function Options(yargs: CommonYargsArgv) {
describe: "Specify directory to use for local persistence (for --local)",
type: "string",
requiresArg: true,
})
.option("json", {
describe: "return output as clean JSON",
rozenmd marked this conversation as resolved.
Show resolved Hide resolved
type: "boolean",
default: false,
});
}

Expand All @@ -94,12 +99,13 @@ export async function executeSql(
command?: string
) {
const sql = file ? readFileSync(file) : command;

if (!sql) throw new Error(`Error: must provide --command or --file.`);
if (persistTo && !local)
throw new Error(`Error: can't use --persist-to without --local`);
if (shouldPrompt) {
logger.log(`πŸŒ€ Mapping SQL input into an array of statements`);
}

rozenmd marked this conversation as resolved.
Show resolved Hide resolved
logger.log(`πŸŒ€ Mapping SQL input into an array of statements`);
const queries = splitSqlQuery(sql);

if (file && sql) {
Expand All @@ -113,7 +119,12 @@ export async function executeSql(

return local
? await executeLocally(config, name, shouldPrompt, queries, persistTo)
: await executeRemotely(config, name, shouldPrompt, batchSplit(queries));
: await executeRemotely(
config,
name,
shouldPrompt,
batchSplit(queries, shouldPrompt)
);
}
type HandlerOptions = StrictYargsOptionsToInterface<typeof Options>;
export const Handler = withConfig<HandlerOptions>(
Expand All @@ -125,8 +136,12 @@ export const Handler = withConfig<HandlerOptions>(
local,
persistTo,
yes,
json,
}): Promise<void> => {
logger.log(d1BetaWarning);
if (!json) {
logger.log(d1BetaWarning);
}

if (file && command)
return logger.error(`Error: can't provide both --command and --file.`);

Expand All @@ -135,7 +150,7 @@ export const Handler = withConfig<HandlerOptions>(
local,
config,
database,
isInteractive && !yes,
!json && isInteractive && !yes,
rozenmd marked this conversation as resolved.
Show resolved Hide resolved
persistTo,
file,
command
Expand Down Expand Up @@ -207,8 +222,9 @@ async function executeLocally(
if (!ok) return null;
await mkdir(dbDir, { recursive: true });
}

logger.log(`πŸŒ€ Loading DB at ${readableRelative(dbPath)}`);
if (shouldPrompt) {
logger.log(`πŸŒ€ Loading DB at ${readableRelative(dbPath)}`);
}
const db = await createSQLiteDB(dbPath);

const results: QueryResult[] = [];
Expand Down Expand Up @@ -275,7 +291,10 @@ async function executeRemotely(
body: JSON.stringify({ sql }),
}
);
result.map(logResult);
if (shouldPrompt) {
result.map(logResult);
}

rozenmd marked this conversation as resolved.
Show resolved Hide resolved
results.push(...result);
}
return results;
Expand All @@ -295,8 +314,11 @@ function logResult(r: QueryResult | QueryResult[]) {
);
}

function batchSplit(queries: string[]) {
logger.log(`πŸŒ€ Parsing ${queries.length} statements`);
function batchSplit(queries: string[], shouldPrompt: boolean | undefined) {
if (shouldPrompt) {
logger.log(`πŸŒ€ Parsing ${queries.length} statements`);
}

rozenmd marked this conversation as resolved.
Show resolved Hide resolved
const num_batches = Math.ceil(queries.length / QUERY_LIMIT);
const batches: string[] = [];
for (let i = 0; i < num_batches; i++) {
Expand All @@ -305,9 +327,11 @@ function batchSplit(queries: string[]) {
);
}
if (num_batches > 1) {
logger.log(
`πŸŒ€ We are sending ${num_batches} batch(es) to D1 (limited to ${QUERY_LIMIT} statements per batch)`
);
if (shouldPrompt) {
logger.log(
`πŸŒ€ We are sending ${num_batches} batch(es) to D1 (limited to ${QUERY_LIMIT} statements per batch)`
);
}
}
return batches;
}