postgrest-docs icon indicating copy to clipboard operation
postgrest-docs copied to clipboard

Query Grammer

Open saberistic opened this issue 7 years ago • 9 comments

Is there any sort of documentation on what is the grammer for postgrest queries?

saberistic avatar Nov 17 '17 18:11 saberistic

literally at the top of the projects github page :) .... https://postgrest.com

ruslantalpa avatar Nov 17 '17 20:11 ruslantalpa

@ruslantalpa, please be respectful to people's questions on this project.

@amirsaber I'd like to get a better idea about your question. Are you wondering if there is a BNF sort of grammar describing the syntax of queries on the URL?

begriffs avatar Nov 17 '17 20:11 begriffs

@ruslantalpa thanks unfortunatly I couldn't find what I was looking for there. @begriffs Yes, I was looking for something like a BNF.

saberistic avatar Nov 17 '17 21:11 saberistic

The short answer is there is no exhaustive grammar in the docs, although there are examples of use.

This may be less helpful than you hoped, but here's the relevant part of the code:

The Parsers.hs file contains a number of p- prefixed functions, which are parsers. If you look through that file it kind of reads like a grammar because it uses the parsec library to define the language.

begriffs avatar Nov 17 '17 22:11 begriffs

@begriffs thanks I will read through it and if I could write a BNF for it I will definitely share. I really enjoyed your projects and we are using it in production for some serious services. It's amazing

saberistic avatar Nov 17 '17 22:11 saberistic

This is my first try to define the language and it's been a while that I didn't do this. Please help and correct me if I am making a mistake. The reason that I am doing this is that I want to write a typescript client library for postgrest and I want to understand the language fully to be able to design it to my best knowledge.

<query> ::= <parts>

<parts> ::= <clause> | <parts>&<parts>

<clause> ::= "select=" <select> | "order=" <repeat> | "limit=" <integer> | "offset=" <integer> | <filter>

<select> ::= <column> | <select>,<select>

<column> ::= <column-name> | <relation>

<column-name> ::= <string> | "*"

<relation> ::= <string>"(" <column> ")" | <string> ":" <string> "(" <column> ")"

<filter> ::= <string> "=" <filter-type1> "." <string> | <string> "=" <filter-type2> ".(" <repeat> ")" | "and=(" <and-or> ")" | "or=(" <and-or> ")"

<repeat> ::= <repeat>,<repeat> | <string>

<filter-type1> ::= "eq" | "gt" | "gte" | "lt" | "lte" | "neq" | "like" | "ilike" | "is" | "fts" | "not"

<filter-type2> ::= "in" | "cs" | "cd" | "ov" | "sl" | "sr" | "nxr" | "nxl" | "adj"

<and-or> ::= <and-or> "," <and-or> | "or(" <and-or> ")" | "and(" <and-or> ")" | <and-or-clause>

<and-or-clause> ::= <string> "." <filter-type1> "." <string> | <string> "." <filter-type2> ".(" R ")"

saberistic avatar Nov 18 '17 00:11 saberistic

Thanks @amirsaber, that looks accurate to me. @steve-chavez can you confirm? If it's all good I'll add it to docs.

begriffs avatar Nov 20 '17 16:11 begriffs

@begriffs There was a missing part in for renaming relation using ":" notion that I added, I also moved the "and or" part from to rule

saberistic avatar Nov 21 '17 19:11 saberistic

Good initiative @amirsaber, I've improved your proposed BNF a bit, the ABNF:

; An example base-url would be http://my.domain.com/rest/, this definition is omitted for brevity.
path = base-url (table / rpc)

table = identifier ["?" query-param]

query-param = query-param "&" query-param

query-param =/ "select=" select-item / "columns=" columns / "on_conflict=" on-conflict ; these don't have an embed-path

query-param =/ *(embed-path) (filter / "order=" order / "limit=" integer / "offset=" integer / ("and"/"or") "=" "(" and-or ")")

embed-path = identifier "." 

select-item = [alias] field [cast] / embed / "*" / select-item "," select-item

alias = identifier ":"

field = identifier / json-path

cast = "::" identifier

embed = [alias] identifier [embed-hint] "(" select-item ")"

embed-hint = "!" identifier

filter = field "=" operation

operation = ["not."] (operator "." val / "in." in-val)

operator = "eq" / "gt" / "gte" / "lt" / "lte" / "neq" / "like" / "ilike" / "is" / "fts" / "cs" / "cd" / "ov" / "sl" / "sr" / "nxr" / "nxl" / "adj"

order = identifier [".asc"/".desc"] [".nullsfirst"/".nullslast"] / order "," order

and-or = field "." and-or-operation / ("and"/"or") "(" and-or ")"/ and-or "," and-or

and-or-operation = ["not."] (operator "." maybe-quoted-val / "in." in-val)

rpc = "rpc/" identifier ["?" rpc-query]

rpc-query = query / arg

arg = identifier "=" val / arg "&" arg

json-path  = identifier 1*("->" identifier) "->>" identifier

in-val = "(" maybe-quoted-val *("," maybe-quoted-val) ")"

maybe-quoted-val = val / DQUOTE val DQUOTE

identifier = 1*((ALPHA / DIGIT / "_") ["-"])

integer = 1*DIGIT

val = *CHAR

@begriffs @ruslantalpa see if I've made any mistake.

Edit: Added quoted vals inside and-or.

steve-chavez avatar Nov 26 '17 03:11 steve-chavez