reference docs so far
Matt S Trout [Tue, 24 Sep 2019 19:34:13 +0000 (19:34 +0000)]
lib/SQL/Abstract/Reference.pm [new file with mode: 0644]

diff --git a/lib/SQL/Abstract/Reference.pm b/lib/SQL/Abstract/Reference.pm
new file mode 100644 (file)
index 0000000..e700b44
--- /dev/null
@@ -0,0 +1,226 @@
+package SQL::Abstract::Reference;
+
+1;
+
+__END__
+=head1 NAME
+
+SQL::Abstract::Reference - Reference documentation for L<SQL::Abstract>
+
+=head1 TERMS
+
+=head2 Expression (expr)
+
+The DWIM structure that's passed to most methods by default is referred to
+as expression syntax. If you see a variable with C<expr> in the name, or a
+comment before a code block saying C<# expr>, this is what's being described.
+
+=head2 Abstract Query Tree (aqt)
+
+The explicit structure that an expression is converted into before it's
+rendered into SQL is referred to as an abstract query tree. If you see a
+variable with C<aqt> in the name, or a comment before a code block saying
+C<# aqt>#, this is what's being described.
+
+=head2 SQL and Bind Values (query)
+
+The final result of L<SQL::Abstract> rendering is generally an SQL statement
+plus bind values for passing to DBI, ala:
+
+  my ($sql, @bind) = $sqla->some_method(@args);
+  my @hashes = @{$dbh->do($sql, { Slice => {} }, @bind)};
+
+If you see a comment before a code block saying C<# query>, the SQL + bind
+array is what's being described.
+
+=head1 AQT node types
+
+An AQT node consists of a hashref with a single key, whose name is C<-type>
+where 'type' is the node type, and whose value is the data for the node.
+
+=head2 literal
+
+  # expr
+  { -literal => [ 'SPANG(?, ?)', 1, 27 ] }
+
+  # query
+  SPANG(?, ?)
+  [ 1, 27 ]
+
+=head2 ident
+
+  # expr
+  { -ident => 'foo' }
+
+  # query
+  foo
+  []
+
+  # expr
+  { -ident => [ 'foo', 'bar' ] }
+
+  # query
+  foo.bar
+  []
+
+=head2 bind
+
+  # expr
+  { -bind => [ 'colname', 'value' ] }
+
+  # query
+  ?
+  [ 'value' ]
+
+=head2 row
+
+  # expr
+  {
+    -row => [ { -bind => [ 'r', 1 ] }, { -ident => [ 'clown', 'car' ] } ]
+  }
+
+  # query
+  (?, clown.car)
+  [ 1 ]
+
+=head2 func
+
+  # expr
+  {
+    -func => [ 'foo', { -ident => [ 'bar' ] }, { -bind => [ undef, 7 ] } ]
+  }
+
+  # query
+  FOO(bar, ?)
+  [ 7 ]
+
+=head2 op
+
+Standard binop:
+
+  # expr
+  { -op => [
+      '=', { -ident => [ 'bomb', 'status' ] },
+      { -value => 'unexploded' },
+  ] }
+
+  # query
+  bomb.status = ?
+  [ 'unexploded' ]
+
+Not:
+
+  # expr
+  { -op => [ 'not', { -ident => 'explosive' } ] }
+
+  # query
+  (NOT explosive)
+  []
+
+Postfix unop: (is_null, is_not_null, asc, desc)
+
+  # expr
+  { -op => [ 'is_null', { -ident => [ 'bobby' ] } ] }
+
+  # query
+  bobby IS NULL
+  []
+
+AND and OR:
+
+  # expr
+  { -op =>
+      [ 'and', { -ident => 'x' }, { -ident => 'y' }, { -ident => 'z' } ]
+  }
+
+  # query
+  ( x AND y AND z )
+  []
+
+IN (and NOT IN):
+
+  # expr
+  { -op => [
+      'in', { -ident => 'card' }, { -bind => [ 'card', 3 ] },
+      { -bind => [ 'card', 'J' ] },
+  ] }
+
+  # query
+  card IN ( ?, ? )
+  [ 3, 'J' ]
+
+BETWEEN (and NOT BETWEEN):
+
+  # expr
+  { -op => [
+      'between', { -ident => 'pints' }, { -bind => [ 'pints', 2 ] },
+      { -bind => [ 'pints', 4 ] },
+  ] }
+
+  # query
+  ( pints BETWEEN ? AND ? )
+  [ 2, 4 ]
+
+Comma (use -row for parens):
+
+  # expr
+  { -op => [ ',', { -literal => [ 1 ] }, { -literal => [ 2 ] } ] }
+
+  # query
+  1, 2
+  []
+
+=head2 values
+
+  # expr
+  { -values =>
+      { -row => [ { -bind => [ undef, 1 ] }, { -bind => [ undef, 2 ] } ] }
+  }
+
+  # query
+  VALUES (?, ?)
+  [ 1, 2 ]
+
+  # expr
+  { -values => [
+      { -row => [ { -literal => [ 1 ] }, { -literal => [ 2 ] } ] },
+      { -row => [ { -literal => [ 3 ] }, { -literal => [ 4 ] } ] },
+  ] }
+
+  # query
+  VALUES (1, 2), (3, 4)
+  []
+
+=head2 statement types
+
+AQT node types are also provided for C<select>, C<insert>, C<update> and
+C<delete>. These types are handled by the clauses system as discussed later.
+
+=head1 Expressions
+
+The simplest expression is just an AQT node:
+
+  # expr
+  { -ident => [ 'foo', 'bar' ] }
+
+  # aqt
+  { -ident => [ 'foo', 'bar' ] }
+
+  # query
+  foo.bar
+  []
+
+However, even in the case of an AQT node, the node value will be expanded if
+an expander has been registered for that node type:
+
+  # expr
+  { -ident => 'foo.bar' }
+
+  # aqt
+  { -ident => [ 'foo', 'bar' ] }
+
+  # query
+  foo.bar
+  []
+
+=head2