-
Notifications
You must be signed in to change notification settings - Fork 6
Node
\sad_spirit\pg_builder\Node
is an interface implemented by all AST nodes. Its descendant \sad_spirit\pg_builder\NodeList
is a interface for nodes representing lists in SQL expressions (e.g. list of columns returned by a SELECT
or list of tables in FROM
).
Note that all relative class and interface names below assume \sad_spirit\pg_builder\
prefix, which is omitted for readability.
-
dispatch(TreeWalker $walker): mixed
- A double-dispatch method supposed to call the method ofTreeWalker
relevant for the currentNode
. -
getParser(): ?Parser
- Returns theParser
, if one is available. Usually it will be added to aStatement
instance that contains the currentNode
. -
setParentNode(Node $parent = null): void
- Adds the link to the Node containing current one. -
getParentNode(): ?Node
- Returns the node containing current one.
Nodes in the AST keep track of their parent nodes and can only be a child of one parent. This means that if you want to copy some node from one branch of the AST to the other, you actually need to clone it. Otherwise the result might be unexpected,
use sad_spirit\pg_builder\StatementFactory;
$factory = new StatementFactory();
/** @var \sad_spirit\pg_builder\SetOpSelect $select */
$select = $factory->createFromString(
'select foo_id, title, description, pub_date from foosourse union all select bar_id from barsource'
);
// let's copy the field list to the second argument of union
foreach ($select->left->list as $k => $v) {
if ($k > 0) {
$select->right->list[] = $v;
}
}
echo $factory->createFromAST($select)->getSql();
will print
select foo_id
from foosourse
union all
select bar_id, title, description, pub_date
from barsource
If you change the assignment in the loop to read $select->right->list[] = clone $v;
the result will be
select foo_id, title, description, pub_date
from foosourse
union all
select bar_id, title, description, pub_date
from barsource
Usually you work with node's children through exposed properties, but Node
defines two special methods that allow working with any child:
-
replaceChild(Node $oldChild, Node $newChild): ?Node
- Replaces the childNode
with another one. Returns$newChild
in case of successful replace,null
otherwise. -
removeChild(Node $child): ?Node
- Removes the childNode
(actually tries to store a null in a relevant property). Returns$child
in case of successful removal,null
otherwise.
These methods are useful for applications that transform AST: e.g. when ParameterWalker
class needs to replace a node for a named parameter :foo
with a node for a positional parameter $1
it just calls replaceChild()
on the Parameter
's parent node. It doesn't care about that node's type and doesn't know to what property of the parent the Parameter
node is mapped.
This is implemented by Node
s that are used in scalar expressions. It is widely used for type hints and defines methods used when generating SQL to properly add parentheses:
-
getPrecedence(): int
- Returns the integer value specifying relative precedence of thisScalarExpression
, the value is a class constant ofScalarExpression
. -
getAssociativity(): string
- Returns the associativity of thisScalarExpression
. Either ofScalarExpression::ASSOCIATIVE_RIGHT
,ScalarExpression::ASSOCIATIVE_LEFT
,ScalarExpression::ASSOCIATIVE_NONE
constants.
This abstract class is a default implementation of Node
, it contains implementations for all its methods except dispatch()
.
It also implements
- Magic
__get()
/__set()
/__isset()
methods allowing access to its child nodes as properties. - Magic
__clone()
method that performs deep cloning of child nodes. -
Serializable
interface and magic__serialize()
and__unserialize()
methods to support caching itself. Implementing both of these is needed to support multiple PHP versions.
All Node
implementations in the package actually extend GenericNode
class.
NodeList
extends IteratorAggregate
, Countable
, and ArrayAccess
SPL interfaces, its instances behave like typed arrays / collections, allowing only objects of specific class or implementing specific interfaces as their elements.
There are two additional methods
-
merge(...$args)
- Merges one or more lists with the current one. -
replace($array)
- Replaces the elements of the list with the given ones.
Note lack of typehints in method signatures, in most cases they will also allow strings as arguments, those will be processed by Parser
if one is available.
Parseable
interface defines one static method
-
static createFromString(Parser $parser, string $sql): self
- Parses the SQL returning an AST for the relevant element.
Classes implementing this interface allow string arguments for merge()
and replace()
calls.
ElementParseable
interface defines one method
-
createElementFromString(string $sql): Node
- Parses the SQL for a list element, returning the AST for it.
Classes implementing this interface allow string arguments for offsetSet()
and consequently for array offset assignment.
$select->list->merge('foo.id as foo_id, bar.title as bar_title');
$select->list[] = 'baz.*';
If you want to add several elements to the list at once, one merge()
call with a string argument will be cheaper in terms of overhead than several assignments with string arguments.
This abstract class extending nodes\GenericNode
is a default implementation of NodeList
. It also updates methods of nodes\GenericNode
to work with array offset as well as properties.
Most of the lists in the package, with the notable exception of nodes\lists\FunctionArgumentList
inherit from its subclass nodes\lists\NonAssociativeList
which disallows non-numeric array indexes.
The following implementations of NodeList
appear as properties of Statement
objects:
NodeList subclass |
Allowed elements | Implements Parseable ? |
Implements ElementParseable ? |
---|---|---|---|
nodes\lists\ExpressionList |
objects implementing nodes\ScalarExpression
|
Yes | Yes |
nodes\lists\FromList |
instances of nodes\range\FromElement
|
Yes | Yes |
nodes\group\GroupByClause |
objects implementing nodes\ScalarExpression or nodes\group\GroupByElement
|
Yes | Yes |
nodes\lists\LockList |
instances of nodes\LockingElement
|
Yes | Yes |
nodes\lists\OrderByList |
instances of nodes\OrderByElement
|
Yes | Yes |
nodes\lists\RowList |
instances of nodes\expressions\RowExpression
|
Yes | Yes |
nodes\lists\SetClauseList |
instances of nodes\SingleSetClause or nodes\MultipleSetClause
|
Yes | Yes |
nodes\lists\SetTargetList |
instances of nodes\SetTargetElement
|
Yes | Yes |
nodes\lists\TargetList |
instances of nodes\TargetElement or nodes\Star
|
Yes | Yes |
nodes\lists\WindowList |
instances of nodes\WindowDefinition
|
Yes | Yes |
nodes\WithClause |
instances of nodes\CommonTableExpression
|
Yes | Yes |