diff --git a/config/allow.list b/config/allow.list index 16e525d5..c0cd9b3d 100644 --- a/config/allow.list +++ b/config/allow.list @@ -1,28 +1,46 @@ # http://localhost:8080/ -query { - me { +variables { + "update": { + "name": "Wu-Tang", + "description": "No description needed" + }, + "product_id": 1 +} + +mutation { + products(id: $product_id, update: $update) { id - email - full_name + name + description } } variables { - "update": { - "name": "Hellooooo", - "description": "World", + "data": { + "email": "gfk@myspace.com", + "full_name": "Ghostface Killah", "created_at": "now", "updated_at": "now" - }, - "user": 123 + } } mutation { - products(update: $update, where: {id: {eq: 134}}) { + user(insert: $data) { + id + } +} + +variables { + "data": { + "product_id": 5 + } +} + +mutation { + products(id: $product_id, delete: true) { id name - description } } @@ -39,20 +57,33 @@ query { } } - variables { - "update": { - "name": "Hellooooo", - "description": "World" - }, - "user": 123 + "data": [ + { + "name": "Protect Ya Neck", + "created_at": "now", + "updated_at": "now" + }, + { + "name": "Enter the Wu-Tang", + "created_at": "now", + "updated_at": "now" + } + ] } mutation { - products(update: $update, where: {id: {eq: 134}}) { + products(insert: $data) { id name - description + } +} + +query { + me { + id + email + full_name } } @@ -70,5 +101,4 @@ mutation { name description } -} - +} \ No newline at end of file diff --git a/psql/insert.go b/psql/insert.go index 8b24c2dc..87ab4b03 100644 --- a/psql/insert.go +++ b/psql/insert.go @@ -174,7 +174,10 @@ func (c *compilerContext) renderDelete(qc *qcode.QCode, w *bytes.Buffer, vars Va return 0, err } - c.w.WriteString(`DELETE FROM `) + c.w.WriteString(`WITH `) + quoted(c.w, ti.Name) + + c.w.WriteString(` AS (DELETE FROM `) c.w.WriteString(ti.Name) io.WriteString(c.w, ` WHERE `) diff --git a/psql/insert_test.go b/psql/insert_test.go index bee8fa68..8f663984 100644 --- a/psql/insert_test.go +++ b/psql/insert_test.go @@ -12,7 +12,7 @@ func simpleInsert(t *testing.T) { } }` - sql := `WITH "users" AS (WITH "input" AS (SELECT {{data}}::json AS j) INSERT INTO users (full_name, email) SELECT full_name, email FROM input i, json_populate_record(NULL::users, i.j) t RETURNING *) SELECT json_object_agg('user', sel_json_0) FROM (SELECT row_to_json((SELECT "sel_0" FROM (SELECT "users_0"."id" AS "id") AS "sel_0")) AS "sel_json_0" FROM (SELECT "users"."id" FROM "users" LIMIT ('1') :: integer) AS "users_0") AS "done_1337";` + sql := `WITH "users" AS (WITH "input" AS (SELECT {{data}}::json AS j) INSERT INTO users (full_name, email) SELECT full_name, email FROM input i, json_populate_record(NULL::users, i.j) t RETURNING *) SELECT json_object_agg('user', sel_json_0) FROM (SELECT row_to_json((SELECT "sel_0" FROM (SELECT "users_0"."id" AS "id") AS "sel_0")) AS "sel_json_0" FROM (SELECT "users"."id" FROM "users") AS "users_0") AS "done_1337";` vars := map[string]json.RawMessage{ "data": json.RawMessage(`{"email": "reannagreenholt@orn.com", "full_name": "Flo Barton"}`), @@ -36,7 +36,7 @@ func singleInsert(t *testing.T) { } }` - sql := `WITH "products" AS (WITH "input" AS (SELECT {{insert}}::json AS j) INSERT INTO products (name, description) SELECT name, description FROM input i, json_populate_record(NULL::products, i.j) t RETURNING *) SELECT json_object_agg('product', sel_json_0) FROM (SELECT row_to_json((SELECT "sel_0" FROM (SELECT "products_0"."id" AS "id", "products_0"."name" AS "name") AS "sel_0")) AS "sel_json_0" FROM (SELECT "products"."id", "products"."name" FROM "products" LIMIT ('1') :: integer) AS "products_0") AS "done_1337";` + sql := `WITH "products" AS (WITH "input" AS (SELECT {{insert}}::json AS j) INSERT INTO products (name, description) SELECT name, description FROM input i, json_populate_record(NULL::products, i.j) t RETURNING *) SELECT json_object_agg('product', sel_json_0) FROM (SELECT row_to_json((SELECT "sel_0" FROM (SELECT "products_0"."id" AS "id", "products_0"."name" AS "name") AS "sel_0")) AS "sel_json_0" FROM (SELECT "products"."id", "products"."name" FROM "products") AS "products_0") AS "done_1337";` vars := map[string]json.RawMessage{ "insert": json.RawMessage(` { "name": "my_name", "woo": { "hoo": "goo" }, "description": "my_desc" }`), @@ -60,7 +60,7 @@ func bulkInsert(t *testing.T) { } }` - sql := `WITH "products" AS (WITH "input" AS (SELECT {{insert}}::json AS j) INSERT INTO products (name, description) SELECT name, description FROM input i, json_populate_recordset(NULL::products, i.j) t RETURNING *) SELECT json_object_agg('product', sel_json_0) FROM (SELECT row_to_json((SELECT "sel_0" FROM (SELECT "products_0"."id" AS "id", "products_0"."name" AS "name") AS "sel_0")) AS "sel_json_0" FROM (SELECT "products"."id", "products"."name" FROM "products" LIMIT ('1') :: integer) AS "products_0") AS "done_1337";` + sql := `WITH "products" AS (WITH "input" AS (SELECT {{insert}}::json AS j) INSERT INTO products (name, description) SELECT name, description FROM input i, json_populate_recordset(NULL::products, i.j) t RETURNING *) SELECT json_object_agg('product', sel_json_0) FROM (SELECT row_to_json((SELECT "sel_0" FROM (SELECT "products_0"."id" AS "id", "products_0"."name" AS "name") AS "sel_0")) AS "sel_json_0" FROM (SELECT "products"."id", "products"."name" FROM "products") AS "products_0") AS "done_1337";` vars := map[string]json.RawMessage{ "insert": json.RawMessage(` [{ "name": "my_name", "woo": { "hoo": "goo" }, "description": "my_desc" }]`), @@ -84,7 +84,7 @@ func singleUpdate(t *testing.T) { } }` - sql := `WITH "products" AS (WITH "input" AS (SELECT {{update}}::json AS j) UPDATE products SET (name, description) = (SELECT name, description FROM input i, json_populate_record(NULL::products, i.j) t) WHERE (("products"."price") > 0) AND (("products"."price") < 8) AND (("products"."id") = 1) AND (("products"."id") = 15) RETURNING *) SELECT json_object_agg('product', sel_json_0) FROM (SELECT row_to_json((SELECT "sel_0" FROM (SELECT "products_0"."id" AS "id", "products_0"."name" AS "name") AS "sel_0")) AS "sel_json_0" FROM (SELECT "products"."id", "products"."name" FROM "products" LIMIT ('1') :: integer) AS "products_0") AS "done_1337";` + sql := `WITH "products" AS (WITH "input" AS (SELECT {{update}}::json AS j) UPDATE products SET (name, description) = (SELECT name, description FROM input i, json_populate_record(NULL::products, i.j) t) WHERE (("products"."price") > 0) AND (("products"."price") < 8) AND (("products"."id") = 1) AND (("products"."id") = 15) RETURNING *) SELECT json_object_agg('product', sel_json_0) FROM (SELECT row_to_json((SELECT "sel_0" FROM (SELECT "products_0"."id" AS "id", "products_0"."name" AS "name") AS "sel_0")) AS "sel_json_0" FROM (SELECT "products"."id", "products"."name" FROM "products") AS "products_0") AS "done_1337";` vars := map[string]json.RawMessage{ "update": json.RawMessage(` { "name": "my_name", "woo": { "hoo": "goo" }, "description": "my_desc" }`), @@ -108,7 +108,7 @@ func delete(t *testing.T) { } }` - sql := `DELETE FROM products WHERE (("products"."price") > 0) AND (("products"."price") < 8) AND (("products"."id") = 1) RETURNING *) SELECT json_object_agg('product', sel_json_0) FROM (SELECT row_to_json((SELECT "sel_0" FROM (SELECT "products_0"."id" AS "id", "products_0"."name" AS "name") AS "sel_0")) AS "sel_json_0" FROM (SELECT "products"."id", "products"."name" FROM "products" LIMIT ('1') :: integer) AS "products_0") AS "done_1337";` + sql := `WITH "products" AS (DELETE FROM products WHERE (("products"."price") > 0) AND (("products"."price") < 8) AND (("products"."id") = 1) RETURNING *) SELECT json_object_agg('product', sel_json_0) FROM (SELECT row_to_json((SELECT "sel_0" FROM (SELECT "products_0"."id" AS "id", "products_0"."name" AS "name") AS "sel_0")) AS "sel_json_0" FROM (SELECT "products"."id", "products"."name" FROM "products") AS "products_0") AS "done_1337";` vars := map[string]json.RawMessage{ "update": json.RawMessage(` { "name": "my_name", "woo": { "hoo": "goo" }, "description": "my_desc" }`), diff --git a/psql/select.go b/psql/select.go index 1e3a3f3b..1058a622 100644 --- a/psql/select.go +++ b/psql/select.go @@ -570,17 +570,19 @@ func (c *compilerContext) renderBaseSelect(sel *qcode.Select, ti *DBTableInfo, } } - if len(sel.Paging.Limit) != 0 { - //fmt.Fprintf(w, ` LIMIT ('%s') :: integer`, c.sel.Paging.Limit) - c.w.WriteString(` LIMIT ('`) - c.w.WriteString(sel.Paging.Limit) - c.w.WriteString(`') :: integer`) + if sel.Action == 0 { + if len(sel.Paging.Limit) != 0 { + //fmt.Fprintf(w, ` LIMIT ('%s') :: integer`, c.sel.Paging.Limit) + c.w.WriteString(` LIMIT ('`) + c.w.WriteString(sel.Paging.Limit) + c.w.WriteString(`') :: integer`) - } else if ti.Singular { - c.w.WriteString(` LIMIT ('1') :: integer`) + } else if ti.Singular { + c.w.WriteString(` LIMIT ('1') :: integer`) - } else { - c.w.WriteString(` LIMIT ('20') :: integer`) + } else { + c.w.WriteString(` LIMIT ('20') :: integer`) + } } if len(sel.Paging.Offset) != 0 { diff --git a/test.yml b/test.yml deleted file mode 100644 index d073f15c..00000000 --- a/test.yml +++ /dev/null @@ -1,57 +0,0 @@ -app_name: Test App -auth: - cookie: _app_session - header: X-User-ID - rails: - max_active: 12000 - max_idle: 80 - secret_key_base: 0a248500a64c01184edb4d7ad3a805488f8097ac761b76aaa6c17c01dcb7af03a2f18ba61b2868134b9c7b79a122bc0dadff4367414a2d173297bfea92be5566 - version: 5.2 - type: rails -auth_fail_block: never -database: - dbname: app_development - defaults: - blocklist: - - ar_internal_metadata - - schema_migrations - - secret - - password - - encrypted - - token - host: db - password: "" - port: 5432 - schema: public - tables: - - name: users - - filter: none - name: customers - remotes: - - id: stripe_id - name: payments - pass_headers: - - cookie - path: data - set_headers: - - name: Host - value: 0.0.0.0 - url: http://rails_app:3000/stripe/$id - - filter: - - '{ id: { eq: $user_id } }' - name: me - table: users - type: postgres - user: postgres - variables: - account_id: (select account_id from users where id = $user_id) -enable_tracing: true -env: development -host_port: 0.0.0.0:8080 -log_level: debug -migrations_path: ./config/migrations -port: "8080" -reload_on_config_change: true -seed_file: seed.js -use_allow_list: false -web_ui: true