From 222b020bcd1961485611df026b722bb518cb0fcd Mon Sep 17 00:00:00 2001
From: Sabra Crolleton Table of Contents
Table of Contents
Table of Contents
is all that is needed to produce the final SQL query.
→ string @@ -485,8 +488,8 @@
→ string @@ -518,8 +521,8 @@
In cases where you do need to build the query at run time, yet you do not @@ -532,8 +535,8 @@
Modifies the current readtable to add a #Q syntax that is read as (sql …). @@ -541,8 +544,8 @@
→ string @@ -561,8 +564,8 @@
→ string @@ -588,16 +591,16 @@
When converting symbols to strings, whether to downcase the symbols is set here. The default is to downcase symbols.
Used to configure whether S-SQL will use standard SQL strings (just replace #\' with ''), or backslash-style escaping. Setting this to NIL is always safe, but when the server is configured to allow standard strings (compile-time parameter 'standard_conforming_strings' is 'on', which will become the default in future versions of PostgreSQL), the noise in queries can be reduced by setting this to T. @@ -605,8 +608,8 @@
A set of all Postgresql's reserved words, for automatic escaping. Probably not a good idea to use these words as identifiers anyway. @@ -625,8 +628,8 @@
Determines whether double quotes are added around column, table, and ** function names in @@ -653,8 +656,8 @@
→ string @@ -666,8 +669,8 @@
→ string @@ -683,8 +686,8 @@
→ keyword @@ -697,8 +700,8 @@
Define simple SQL operators. Arity is one of :unary (like 'not'), :unary-postfix @@ -712,8 +715,8 @@
S-SQL knows the SQL equivalents to a number of Lisp types, and defines some @@ -833,8 +836,8 @@
This is a type of which only the keyword :null is a member. It is used to represent @@ -844,8 +847,8 @@
An S-SQL form is converted to a query through the following rules: @@ -866,8 +869,8 @@
Creates a select query. The arguments are split on the keywords found among @@ -876,19 +879,46 @@
(query (:select 'item :distinct - :from 'item-table - :where (:= 'col1 "Albania"))) + :from 'item-table + :where (:= 'col1 "Albania"))) (query (:select (:+ 'field-1 100) 'field-5 :from (:as 'my-table 'x) @@ -897,29 +927,66 @@:where (:not-null 'a.field-3))) (query (:order-by - (:select 'regions.name - (:count 'regions.name) - :from 'countries 'regions - :where (:= 'regions.id 'countries.region-id) - :group-by 'regions.name) + (:select 'regions.name + (:count 'regions.name) + :from 'countries 'regions + :where (:= 'regions.id 'countries.region-id) + :group-by 'regions.name) 'regions.name)) (query (:select (:count 'c.id) 'r.name - :from (:as 'countries 'c) - :inner-join (:as 'regions 'r) - :on (:= 'c.region-id 'r.id) - :group-by 'r.name - :having (:< (:count 'c.id) 10))) + :from (:as 'countries 'c) + :inner-join (:as 'regions 'r) + :on (:= 'c.region-id 'r.id) + :group-by 'r.name + :having (:< (:count 'c.id) 10))) + +(query (:select 'i.* 'p.* + :from (:as 'individual 'i) + :inner-join (:as 'publisher 'p) + :using ('individualid) + :left-join-lateral (:as 'anothertable 'a) + :on (:= 'a.identifier 'i.individualid) + :where (:= 'a.something \"something\"))) + +(query (:select 't1.id 'a.elem 'a.nr + :from (:as 't12 't1) + :left-join (:unnest (:string-to-array 't1.elements ",")) + :with-ordinality-as (:a 'elem 'nr) + :on 't))
+Other examples can be found in s-sql/tests/tests.lisp +
+Allowable join keywords are: +
++The lateral joins will not be discussed separately. +
From the postgresql documentation: "For every possible combination of rows from T1 and T2 (i.e., a Cartesian product), the joined table will contain a row consisting of all columns in T1 followed by all columns in T2. If the tables have N and M rows respectively, the joined table will have N * M rows." @@ -931,8 +998,8 @@
An inner join looks at two tables and creates a new result consisting of the selected elements in the rows from the two tables that match the specified conditions. You can simplistically think of it as the intersection of the two sets. In reality, it is creating a new set consisting of certain elements of the intersecting rows. An inner join is the default and need not be specified. @@ -1001,8 +1068,8 @@
An outer join not only generates an inner join, it also joins the rows from one table that matches the conditions and adds null values for the joined columns from the second table (which obviously did not match the condition.) Under Postgresql, a "left join", "right join" or "full join" all imply an outer join. @@ -1014,8 +1081,8 @@
Example: Here we assume two tables. A countries table and a many-to-many linking table named countries-topics. (There is an implicit third table named topics.) We are looking for records from the countries table which do not have a match in the countries-topics table. In other words, where do we have a note, but not matched it to a topic? @@ -1050,16 +1117,16 @@
The following operators are defined:
These are expanded as infix operators. When meaningful, they allow more than @@ -1075,8 +1142,8 @@
Unary operators for bitwise and logical negation. @@ -1196,8 +1263,8 @@
Any needs to be considered as a special case. Quoting Marijn Haverbeke here,"Postgres has both a function-call-style any and an infix any, and S-SQL's syntax doesn't allow them to be distinguished." As a result, postmodern has a regular :any sql-op and a :any* sql-op, which expand slightly differently. @@ -1305,8 +1372,8 @@
Create a stored procedure. The argument and return types are interpreted as @@ -1321,8 +1388,8 @@
Regular expression matching operators. The exclamation mark means 'does not match', @@ -1368,8 +1435,8 @@
Simple SQL string matching operators (:ilike is case-insensitive). @@ -1382,8 +1449,8 @@
Fast Text Search match operator. @@ -1391,8 +1458,8 @@
Used to invert the meaning of an operator in an :order-by clause. @@ -1407,8 +1474,8 @@
Used to determine where :null values appear in an :order-by clause. @@ -1416,8 +1483,8 @@
Also known in some explanations as "alias". This assigns a name to a column or @@ -1472,8 +1539,8 @@
The CAST operator. Takes a query as an argument, and returns the result @@ -1502,8 +1569,8 @@
Is similar to cast but uses the postgresql :: formating. Unlike cast it will not @@ -1521,8 +1588,8 @@
Creates a composite type with a type-name and two or more columns. E.g. @@ -1533,8 +1600,8 @@
The EXISTS operator. Takes a query as an argument, and returns true or false @@ -1554,8 +1621,8 @@
Test whether a value is null. @@ -1566,8 +1633,8 @@
Test whether a value is not null. @@ -1578,8 +1645,8 @@
Test whether a value is in a set of values. @@ -1599,8 +1666,8 @@
Inverse of the above. @@ -1608,8 +1675,8 @@
Denote a set of values. This operator has two interfaces. When @@ -1684,8 +1751,8 @@
This is used when calling a select query into an array. See array-notes.html @@ -1710,8 +1777,8 @@
This is the general operator for arrays. It also handles statements that include @@ -1732,8 +1799,8 @@
Dereference an array value. If end is provided, extract a slice of the array. @@ -1749,8 +1816,8 @@
Extract a field from a date/time value. For example, (:extract :month (:now)). @@ -1769,8 +1836,8 @@
A conditional expression. Clauses should take the form (test value). If @@ -1785,8 +1852,8 @@
Test whether a value lies between two other values. @@ -1800,8 +1867,8 @@
Works like :between, except that the start value is not required to be @@ -1810,8 +1877,8 @@
Can be used to combine multiple names into a name of the form A.B to @@ -1821,8 +1888,8 @@
Add a type declaration to a value, as in in "4.3::real". The second @@ -1835,8 +1902,8 @@
Insert a string as-is into the query. This can be useful for doing things @@ -1853,8 +1920,8 @@
Fetch is a more efficient way to do pagination instead of using limit and @@ -1881,8 +1948,8 @@
In S-SQL limit is not part of the select operator, but an extra @@ -1898,8 +1965,8 @@
Order the results of a query by the given expressions. See :desc for @@ -1916,8 +1983,8 @@
Values computes a row value or set of row values for use in a specific @@ -1952,8 +2019,8 @@
This is a fudge. It returns a string "()" where something like '() @@ -1969,8 +2036,8 @@
https://www.postgresql.org/docs/current/static/queries-table-expressions.html#QUERIES-GROUPING-SETS @@ -1995,8 +2062,8 @@
https://www.postgresql.org/docs/current/static/queries-table-expressions.html#QUERIES-GROUPING-SETS @@ -2016,20 +2083,20 @@
Creates an interval data type, generally represented in postmodern as an alist
(query (:select (:current-date)) :single) @@ -2037,33 +2104,33 @@-
sql-op :current-time ()
+ --sql-op :current-timestamp ()
+ --sql-op :timestamp (arg)
+ --sql-op :age (&rest args)
+ --sql-op :date (arg)
+ --sql-op :make-interval (&rest args)
++sql-op :make-interval (&rest args)
Takes lists of (time-unit value) and returns a timestamp type. Example: @@ -2076,8 +2143,8 @@
-
sql-op :make-timestamp (&rest args)
++sql-op :make-timestamp (&rest args)
Takes lists of (time-unit value) and returns a timestamptz type. Example: @@ -2091,8 +2158,8 @@
-
sql-op :make-timestamptz (&rest args)
++sql-op :make-timestamptz (&rest args)
Takes lists of (time-unit value) and returns a timestamptz type. Example: @@ -2108,12 +2175,12 @@
-
Aggregation Operators
++Aggregation Operators
--sql-op :count (&rest args)
++sql-op :count (&rest args)
Count returns the number of rows for which the expression is not null. @@ -2166,8 +2233,8 @@
-
sql-op :avg (&rest rest args)
++sql-op :avg (&rest rest args)
Avg calculates the average value of a list of values. Note that if the @@ -2182,8 +2249,8 @@
-