Skip to content
Merged
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
2 changes: 1 addition & 1 deletion crates/squawk_parser/src/generated/syntax_kind.rs

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

19 changes: 12 additions & 7 deletions crates/squawk_parser/src/grammar.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4092,6 +4092,7 @@ pub(crate) fn current_operator(p: &Parser<'_>) -> Option<SyntaxKind> {
}

fn using_index(p: &mut Parser<'_>) {
assert!(p.at(USING_KW));
let m = p.start();
p.bump(USING_KW);
p.expect(INDEX_KW);
Expand Down Expand Up @@ -8516,12 +8517,15 @@ fn opt_key_columns(p: &mut Parser<'_>) {
}

fn opt_element_table_label_and_properties(p: &mut Parser<'_>) {
if !opt_element_table_properties_clause(p) && p.at(DEFAULT_KW) || p.at(LABEL_KW) {
label_and_properties_list(p);
if !opt_element_table_properties_clause(p) {
opt_label_and_properties_list(p);
}
}

fn label_and_properties_list(p: &mut Parser<'_>) {
fn opt_label_and_properties_list(p: &mut Parser<'_>) {
if !p.at(DEFAULT_KW) && !p.at(LABEL_KW) {
return;
}
let m = p.start();
label_and_properties(p);
while p.at(DEFAULT_KW) || p.at(LABEL_KW) {
Expand Down Expand Up @@ -8687,6 +8691,7 @@ fn alter_vertex_edge_table(p: &mut Parser<'_>) {
}

fn drop_edge_tables(p: &mut Parser<'_>) {
assert!(p.at(DROP_KW));
let m = p.start();
p.bump(DROP_KW);
p.bump_any(); // EDGE/RELATIONSHIP
Expand Down Expand Up @@ -8871,20 +8876,20 @@ fn vertex_pattern(p: &mut Parser<'_>) {
let m = p.start();
p.expect(L_PAREN);
opt_name(p);
opt_is_label_expression(p);
opt_is_label(p);
opt_where_clause(p);
p.expect(R_PAREN);
m.complete(p, VERTEX_PATTERN);
}

fn opt_is_label_expression(p: &mut Parser<'_>) {
fn opt_is_label(p: &mut Parser<'_>) {
if p.at(IS_KW) {
let m = p.start();
p.bump(IS_KW);
if expr(p).is_none() {
p.error("expected expression");
}
m.complete(p, IS_LABEL_EXPRESSION);
m.complete(p, IS_LABEL);
}
}

Expand Down Expand Up @@ -8920,7 +8925,7 @@ fn edge_with_bracket(p: &mut Parser<'_>) {

fn opt_edge_pattern_inner(p: &mut Parser<'_>) {
opt_name(p);
opt_is_label_expression(p);
opt_is_label(p);
opt_where_clause(p);
}

Expand Down
157 changes: 157 additions & 0 deletions crates/squawk_parser/tests/data/ok/sql_pgq.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
-- squawk-ignore-file prefer-bigint-over-int, prefer-robust-stmts
set statement_timeout = '5s';
set lock_timeout = '1s';

--
-- via Postgres' docs
-- 5.15. Property Graphs
--
CREATE TABLE products (
product_no integer PRIMARY KEY,
name varchar,
price numeric
);

CREATE TABLE customers (
customer_id integer PRIMARY KEY,
name varchar,
address varchar
);

CREATE TABLE orders (
order_id integer PRIMARY KEY,
ordered_when date
);

CREATE TABLE order_items (
order_items_id integer PRIMARY KEY,
order_id integer REFERENCES orders (order_id),
product_no integer REFERENCES products (product_no),
quantity integer
);

CREATE TABLE customer_orders (
customer_orders_id integer PRIMARY KEY,
customer_id integer REFERENCES customers (customer_id),
order_id integer REFERENCES orders (order_id)
);

CREATE PROPERTY GRAPH myshop
VERTEX TABLES (
products,
customers,
orders
)
EDGE TABLES (
order_items SOURCE orders DESTINATION products,
customer_orders SOURCE customers DESTINATION orders
);

-- get list of customers active today
SELECT customer_name FROM GRAPH_TABLE (myshop MATCH (c IS customers)-[IS customer_orders]->(o IS orders WHERE o.ordered_when = current_date) COLUMNS (c.name AS customer_name));

-- get list of customers active today
SELECT customers.name FROM customers JOIN customer_orders USING (customer_id) JOIN orders USING (order_id) WHERE orders.ordered_when = current_date;

-- explicit version that doesn't require primary & foreign keys
CREATE PROPERTY GRAPH myshop
VERTEX TABLES (
products KEY (product_no),
customers KEY (customer_id),
orders KEY (order_id)
)
EDGE TABLES (
order_items KEY (order_items_id)
SOURCE KEY (order_id) REFERENCES orders (order_id)
DESTINATION KEY (product_no) REFERENCES products (product_no),
customer_orders KEY (customer_orders_id)
SOURCE KEY (customer_id) REFERENCES customers (customer_id)
DESTINATION KEY (order_id) REFERENCES orders (order_id)
);

CREATE PROPERTY GRAPH myshop
VERTEX TABLES (
products LABEL product,
customers LABEL customer,
orders LABEL "order"
)
EDGE TABLES (
order_items SOURCE orders DESTINATION products LABEL contains,
customer_orders SOURCE customers DESTINATION orders LABEL has_placed
);

SELECT customer_name FROM GRAPH_TABLE (myshop MATCH (c IS customer)-[IS has_placed]->(o IS "order" WHERE o.ordered_when = current_date) COLUMNS (c.name AS customer_name));


select * from
GRAPH_TABLE (mygraph MATCH (p IS person)-[h IS has]->(a IS account)
COLUMNS (p.name AS person_name, h.since AS has_account_since, a.num AS account_number));

--
-- via: https://pgql-lang.org
--
create table Persons(
id bigint primary key,
name text,
company_id bigint references Companies
);

create table Companies(
id bigint primary key,
name text
);

create table Accounts(
number bigint primary key,
account_type text,
person_id bigint references Persons,
company_id bigint references Companies
);

create table Transactions(
id bigint primary key,
from_account bigint references Accounts,
to_account bigint references Accounts,
date timestamptz,
amount bigint
);

CREATE PROPERTY GRAPH financial_transactions
VERTEX TABLES (
-- label that gets used in the query lang below, i.e., IS Person
Persons LABEL Person PROPERTIES ( name ),
Companies LABEL Company PROPERTIES ( name ),
Accounts LABEL Account PROPERTIES ( number )
)
EDGE TABLES (
Transactions
SOURCE KEY ( from_account ) REFERENCES Accounts ( number )
DESTINATION KEY ( to_account ) REFERENCES Accounts ( number )
LABEL transaction
PROPERTIES ( amount ),
Accounts AS PersonOwner
SOURCE KEY ( number ) REFERENCES Accounts ( number )
DESTINATION Persons
LABEL owner
NO PROPERTIES,
Accounts AS CompanyOwner
SOURCE KEY ( number ) REFERENCES Accounts ( number )
DESTINATION Companies
LABEL owner
NO PROPERTIES,
Persons AS worksFor
SOURCE KEY ( id ) REFERENCES Persons ( id )
DESTINATION Companies
NO PROPERTIES
);

SELECT account_holder, SUM(amount) AS total_transacted_with_Nikita
FROM GRAPH_TABLE (
financial_transactions
MATCH (p IS Person) <-[IS owner]- (account1 IS Account),
(account1) -[t IS transaction]- (account2), /* match both incoming and outgoing transactions */
(account2 IS Account) -[IS owner]-> (owner IS Person|Company)
WHERE p.name = 'Nikita'
COLUMNS (owner.name AS account_holder, t.amount)
)
GROUP BY account_holder
Loading
Loading