Commit 03d5c070 authored by Thomas G. Lockhart's avatar Thomas G. Lockhart

Modify the outer join placeholder code with something closer to working

 code. Works here, but not completely implemented past this point.
parent 8f0a76f0
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.56 1999/02/21 03:49:00 scrappy Exp $ * $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.57 1999/02/23 07:42:41 thomas Exp $
* *
* HISTORY * HISTORY
* AUTHOR DATE MAJOR EVENT * AUTHOR DATE MAJOR EVENT
...@@ -107,7 +107,7 @@ Oid param_type(int t); /* used in parse_expr.c */ ...@@ -107,7 +107,7 @@ Oid param_type(int t); /* used in parse_expr.c */
DefElem *defelt; DefElem *defelt;
ParamString *param; ParamString *param;
SortGroupBy *sortgroupby; SortGroupBy *sortgroupby;
JoinUsing *joinusing; JoinExpr *joinexpr;
IndexElem *ielem; IndexElem *ielem;
RangeVar *range; RangeVar *range;
RelExpr *relexp; RelExpr *relexp;
...@@ -131,7 +131,7 @@ Oid param_type(int t); /* used in parse_expr.c */ ...@@ -131,7 +131,7 @@ Oid param_type(int t); /* used in parse_expr.c */
RemoveFuncStmt, RemoveStmt, RemoveFuncStmt, RemoveStmt,
RenameStmt, RevokeStmt, RuleStmt, TransactionStmt, ViewStmt, LoadStmt, RenameStmt, RevokeStmt, RuleStmt, TransactionStmt, ViewStmt, LoadStmt,
CreatedbStmt, DestroydbStmt, VacuumStmt, CursorStmt, SubSelect, CreatedbStmt, DestroydbStmt, VacuumStmt, CursorStmt, SubSelect,
UpdateStmt, InsertStmt, select_w_o_sort, SelectStmt, NotifyStmt, DeleteStmt, UpdateStmt, InsertStmt, select_clause, SelectStmt, NotifyStmt, DeleteStmt,
ClusterStmt, ExplainStmt, VariableSetStmt, VariableShowStmt, VariableResetStmt, ClusterStmt, ExplainStmt, VariableSetStmt, VariableShowStmt, VariableResetStmt,
CreateUserStmt, AlterUserStmt, DropUserStmt, RuleActionStmt CreateUserStmt, AlterUserStmt, DropUserStmt, RuleActionStmt
...@@ -144,7 +144,6 @@ Oid param_type(int t); /* used in parse_expr.c */ ...@@ -144,7 +144,6 @@ Oid param_type(int t); /* used in parse_expr.c */
%type <str> user_valid_clause %type <str> user_valid_clause
%type <list> user_group_list, user_group_clause %type <list> user_group_list, user_group_clause
%type <str> join_expr, join_outer, join_spec
%type <boolean> TriggerActionTime, TriggerForSpec, PLangTrusted %type <boolean> TriggerActionTime, TriggerForSpec, PLangTrusted
%type <str> TriggerEvents, TriggerFuncArg %type <str> TriggerEvents, TriggerFuncArg
...@@ -167,7 +166,7 @@ Oid param_type(int t); /* used in parse_expr.c */ ...@@ -167,7 +166,7 @@ Oid param_type(int t); /* used in parse_expr.c */
oper_argtypes, RuleActionList, RuleActionBlock, RuleActionMulti, oper_argtypes, RuleActionList, RuleActionBlock, RuleActionMulti,
opt_column_list, columnList, opt_va_list, va_list, opt_column_list, columnList, opt_va_list, va_list,
sort_clause, sortby_list, index_params, index_list, name_list, sort_clause, sortby_list, index_params, index_list, name_list,
from_clause, from_list, opt_array_bounds, nest_array_bounds, from_clause, from_expr, table_list, opt_array_bounds, nest_array_bounds,
expr_list, attrs, res_target_list, res_target_list2, expr_list, attrs, res_target_list, res_target_list2,
def_list, opt_indirection, group_clause, TriggerFuncArgs, def_list, opt_indirection, group_clause, TriggerFuncArgs,
opt_select_limit opt_select_limit
...@@ -177,14 +176,16 @@ Oid param_type(int t); /* used in parse_expr.c */ ...@@ -177,14 +176,16 @@ Oid param_type(int t); /* used in parse_expr.c */
%type <boolean> TriggerForOpt, TriggerForType, OptTemp %type <boolean> TriggerForOpt, TriggerForType, OptTemp
%type <list> for_update_clause %type <list> for_update_clause, update_list
%type <list> join_list
%type <joinusing>
join_using
%type <boolean> opt_union %type <boolean> opt_union
%type <boolean> opt_table %type <boolean> opt_table
%type <boolean> opt_trans %type <boolean> opt_trans
%type <list> join_clause_with_union, join_clause, join_list, join_qual, using_list
%type <node> join_expr, using_expr
%type <str> join_outer
%type <ival> join_type
%type <node> position_expr %type <node> position_expr
%type <list> extract_list, position_list %type <list> extract_list, position_list
%type <list> substr_list, substr_from, substr_for, trim_list %type <list> substr_list, substr_from, substr_for, trim_list
...@@ -226,7 +227,7 @@ Oid param_type(int t); /* used in parse_expr.c */ ...@@ -226,7 +227,7 @@ Oid param_type(int t); /* used in parse_expr.c */
%type <attr> event_object, attr %type <attr> event_object, attr
%type <sortgroupby> sortby %type <sortgroupby> sortby
%type <ielem> index_elem, func_index %type <ielem> index_elem, func_index
%type <range> from_val %type <range> table_expr
%type <relexp> relation_expr %type <relexp> relation_expr
%type <target> res_target_el, res_target_el2 %type <target> res_target_el, res_target_el2
%type <paramno> ParamNo %type <paramno> ParamNo
...@@ -858,20 +859,15 @@ ColConstraint: ...@@ -858,20 +859,15 @@ ColConstraint:
{ $$ = $1; } { $$ = $1; }
; ;
/* The column constraint WITH NULL gives a shift/reduce error /* DEFAULT NULL is already the default for Postgres.
* because it requires yacc to look more than one token ahead to
* resolve WITH TIME ZONE and WITH NULL.
* So, leave it out of the syntax for now.
| WITH NULL_P
{
$$ = NULL;
}
* - thomas 1998-09-12
*
* DEFAULT NULL is already the default for Postgres.
* Bue define it here and carry it forward into the system * Bue define it here and carry it forward into the system
* to make it explicit. * to make it explicit.
* - thomas 1998-09-13 * - thomas 1998-09-13
* WITH NULL and NULL are not SQL92-standard syntax elements,
* so leave them out. Use DEFAULT NULL to explicitly indicate
* that a column may have that value. WITH NULL leads to
* shift/reduce conflicts with WITH TIME ZONE anyway.
* - thomas 1999-01-08
*/ */
ColConstraintElem: CHECK '(' constraint_expr ')' ColConstraintElem: CHECK '(' constraint_expr ')'
{ {
...@@ -2735,8 +2731,10 @@ opt_of: OF columnList ...@@ -2735,8 +2731,10 @@ opt_of: OF columnList
* accepts the use of '(' and ')' to select an order of set operations. * accepts the use of '(' and ')' to select an order of set operations.
* *
* The rule returns a SelectStmt Node having the set operations attached to * The rule returns a SelectStmt Node having the set operations attached to
* unionClause and intersectClause (NIL if no set operations were present) */ * unionClause and intersectClause (NIL if no set operations were present)
SelectStmt: select_w_o_sort sort_clause for_update_clause opt_select_limit */
SelectStmt: select_clause sort_clause for_update_clause opt_select_limit
{ {
/* There were no set operations, so just attach the sortClause */ /* There were no set operations, so just attach the sortClause */
if IsA($1, SelectStmt) if IsA($1, SelectStmt)
...@@ -2827,7 +2825,7 @@ SelectStmt: select_w_o_sort sort_clause for_update_clause opt_select_limit ...@@ -2827,7 +2825,7 @@ SelectStmt: select_w_o_sort sort_clause for_update_clause opt_select_limit
* the A_Expr Nodes. * the A_Expr Nodes.
* If no set operations show up in the query the tree consists only of one * If no set operations show up in the query the tree consists only of one
* SelectStmt Node */ * SelectStmt Node */
select_w_o_sort: '(' select_w_o_sort ')' select_clause: '(' select_clause ')'
{ {
$$ = $2; $$ = $2;
} }
...@@ -2835,12 +2833,12 @@ select_w_o_sort: '(' select_w_o_sort ')' ...@@ -2835,12 +2833,12 @@ select_w_o_sort: '(' select_w_o_sort ')'
{ {
$$ = $1; $$ = $1;
} }
| select_w_o_sort EXCEPT select_w_o_sort | select_clause EXCEPT select_clause
{ {
$$ = (Node *)makeA_Expr(AND,NULL,$1, $$ = (Node *)makeA_Expr(AND,NULL,$1,
makeA_Expr(NOT,NULL,NULL,$3)); makeA_Expr(NOT,NULL,NULL,$3));
} }
| select_w_o_sort UNION opt_union select_w_o_sort | select_clause UNION opt_union select_clause
{ {
if (IsA($4, SelectStmt)) if (IsA($4, SelectStmt))
{ {
...@@ -2849,7 +2847,7 @@ select_w_o_sort: '(' select_w_o_sort ')' ...@@ -2849,7 +2847,7 @@ select_w_o_sort: '(' select_w_o_sort ')'
} }
$$ = (Node *)makeA_Expr(OR,NULL,$1,$4); $$ = (Node *)makeA_Expr(OR,NULL,$1,$4);
} }
| select_w_o_sort INTERSECT select_w_o_sort | select_clause INTERSECT select_clause
{ {
$$ = (Node *)makeA_Expr(AND,NULL,$1,$3); $$ = (Node *)makeA_Expr(AND,NULL,$1,$3);
} }
...@@ -3035,19 +3033,12 @@ having_clause: HAVING a_expr ...@@ -3035,19 +3033,12 @@ having_clause: HAVING a_expr
| /*EMPTY*/ { $$ = NULL; } | /*EMPTY*/ { $$ = NULL; }
; ;
for_update_clause: for_update_clause: FOR UPDATE update_list { $$ = $3; }
FOR UPDATE | /* EMPTY */ { $$ = NULL; }
{ ;
$$ = lcons(NULL, NULL);
} update_list: OF va_list { $$ = $2; }
| FOR UPDATE OF va_list | /* EMPTY */ { $$ = lcons(NULL, NULL); }
{
$$ = $4;
}
| /* EMPTY */
{
$$ = NULL;
}
; ;
/***************************************************************************** /*****************************************************************************
...@@ -3058,24 +3049,25 @@ for_update_clause: ...@@ -3058,24 +3049,25 @@ for_update_clause:
* *
*****************************************************************************/ *****************************************************************************/
from_clause: FROM '(' relation_expr join_expr JOIN relation_expr join_spec ')' from_clause: FROM from_expr { $$ = $2; }
{
$$ = NIL;
elog(ERROR,"JOIN not yet implemented");
}
| FROM from_list { $$ = $2; }
| /*EMPTY*/ { $$ = NIL; } | /*EMPTY*/ { $$ = NIL; }
; ;
from_list: from_list ',' from_val from_expr: '(' join_clause_with_union ')'
{ $$ = $2; }
| join_clause
{ $$ = $1; }
| table_list
{ $$ = $1; }
;
table_list: table_list ',' table_expr
{ $$ = lappend($1, $3); } { $$ = lappend($1, $3); }
| from_val CROSS JOIN from_val | table_expr
{ elog(ERROR,"CROSS JOIN not yet implemented"); }
| from_val
{ $$ = lcons($1, NIL); } { $$ = lcons($1, NIL); }
; ;
from_val: relation_expr AS ColLabel table_expr: relation_expr AS ColLabel
{ {
$$ = makeNode(RangeVar); $$ = makeNode(RangeVar);
$$->relExpr = $1; $$->relExpr = $1;
...@@ -3095,64 +3087,130 @@ from_val: relation_expr AS ColLabel ...@@ -3095,64 +3087,130 @@ from_val: relation_expr AS ColLabel
} }
; ;
join_expr: NATURAL join_expr { $$ = NULL; } /* A UNION JOIN is the same as a FULL OUTER JOIN which *omits*
| FULL join_outer * all result rows which would have matched on an INNER JOIN.
{ elog(ERROR,"FULL OUTER JOIN not yet implemented"); } * Let's reject this for now. - thomas 1999-01-08
*/
join_clause_with_union: join_clause
{ $$ = $1; }
| table_expr UNION JOIN table_expr
{ elog(ERROR,"UNION JOIN not yet implemented"); }
;
join_clause: table_expr join_list
{
Node *n = lfirst($2);
/* JoinExpr came back? then it is a join of some sort...
*/
if (IsA(n, JoinExpr))
{
JoinExpr *j = (JoinExpr *)n;
j->larg = $1;
$$ = $2;
}
/* otherwise, it was a cross join,
* which we just represent as an inner join...
*/
else
$$ = lcons($1, $2);
}
;
join_list: join_list join_expr
{
$$ = lappend($1, $2);
}
| join_expr
{
$$ = lcons($1, NIL);
}
;
/* This is everything but the left side of a join.
* Note that a CROSS JOIN is the same as an unqualified
* inner join, so just pass back the right-side table.
* A NATURAL JOIN implicitly matches column names between
* tables, so we'll collect those during the later transformation.
*/
join_expr: join_type JOIN table_expr join_qual
{
JoinExpr *n = makeNode(JoinExpr);
n->jointype = $1;
n->rarg = (Node *)$3;
n->quals = $4;
$$ = (Node *)n;
}
| NATURAL join_type JOIN table_expr
{
JoinExpr *n = makeNode(JoinExpr);
n->jointype = $2;
n->rarg = (Node *)$4;
n->quals = NULL; /* figure out which columns later... */
$$ = (Node *)n;
}
| CROSS JOIN table_expr
{ $$ = (Node *)$3; }
;
/* OUTER is just noise... */
join_type: FULL join_outer
{
$$ = FULL;
elog(NOTICE,"FULL OUTER JOIN not yet implemented");
}
| LEFT join_outer | LEFT join_outer
{ elog(ERROR,"LEFT OUTER JOIN not yet implemented"); } {
$$ = LEFT;
elog(NOTICE,"LEFT OUTER JOIN not yet implemented");
}
| RIGHT join_outer | RIGHT join_outer
{ elog(ERROR,"RIGHT OUTER JOIN not yet implemented"); } {
$$ = RIGHT;
elog(NOTICE,"RIGHT OUTER JOIN not yet implemented");
}
| OUTER_P | OUTER_P
{ elog(ERROR,"OUTER JOIN not yet implemented"); } {
$$ = LEFT;
elog(NOTICE,"OUTER JOIN not yet implemented");
}
| INNER_P | INNER_P
{ elog(ERROR,"INNER JOIN not yet implemented"); } {
| UNION $$ = INNER_P;
{ elog(ERROR,"UNION JOIN not yet implemented"); } }
| /*EMPTY*/ | /*EMPTY*/
{ elog(ERROR,"INNER JOIN not yet implemented"); } {
$$ = INNER_P;
}
; ;
join_outer: OUTER_P { $$ = NULL; } join_outer: OUTER_P { $$ = NULL; }
| /*EMPTY*/ { $$ = NULL; /* no qualifiers */ } | /*EMPTY*/ { $$ = NULL; /* no qualifiers */ }
; ;
join_spec: ON '(' a_expr ')' { $$ = NULL; } /* JOIN qualification clauses
| USING '(' join_list ')' { $$ = NULL; } * Possibilities are:
| /*EMPTY*/ { $$ = NULL; /* no qualifiers */ } * USING ( column list ) allows only unqualified column names,
* which must match between tables.
* ON expr allows more general qualifications.
* - thomas 1999-01-07
*/
join_qual: USING '(' using_list ')' { $$ = $3; }
| ON a_expr { $$ = lcons($2, NIL); }
; ;
join_list: join_using { $$ = lcons($1, NIL); } using_list: using_list ',' using_expr { $$ = lappend($1, $3); }
| join_list ',' join_using { $$ = lappend($1, $3); } | using_expr { $$ = lcons($1, NIL); }
; ;
join_using: ColId using_expr: ColId
/* Changed from SortGroupBy parse node to new JoinUsing node.
* SortGroupBy no longer needs these structure members.
*
* Once, acknowledged, this comment can be removed by the
* developer(s) working on the JOIN clause.
*
* - daveh@insightdist.com 1998-07-31
*/
{
$$ = makeNode(JoinUsing);
$$->resno = 0;
$$->range = NULL;
$$->name = $1;
}
| ColId '.' ColId
{
$$ = makeNode(JoinUsing);
$$->resno = 0;
$$->range = $1;
$$->name = $3;
}
| Iconst
{ {
$$ = makeNode(JoinUsing); /* could be a column name or a relation_name */
$$->resno = $1; Ident *n = makeNode(Ident);
$$->range = NULL; n->name = $1;
$$->name = NULL; n->indirection = NULL;
$$ = (Node *)n;
} }
; ;
...@@ -4737,12 +4795,15 @@ case_expr: CASE case_arg when_clause_list case_default END_TRANS ...@@ -4737,12 +4795,15 @@ case_expr: CASE case_arg when_clause_list case_default END_TRANS
{ {
CaseExpr *c = makeNode(CaseExpr); CaseExpr *c = makeNode(CaseExpr);
CaseWhen *w = makeNode(CaseWhen); CaseWhen *w = makeNode(CaseWhen);
/*
A_Const *n = makeNode(A_Const);
n->val.type = T_Null;
w->result = (Node *)n;
*/
w->expr = makeA_Expr(OP, "=", $3, $5);
c->args = lcons(w, NIL); c->args = lcons(w, NIL);
c->defresult = $3; c->defresult = $3;
w->expr = makeA_Expr(OP, "=", $3, $5);
$$ = (Node *)c; $$ = (Node *)c;
elog(NOTICE,"NULLIF() not yet fully implemented");
} }
| COALESCE '(' expr_list ')' | COALESCE '(' expr_list ')'
{ {
...@@ -4757,8 +4818,6 @@ case_expr: CASE case_arg when_clause_list case_default END_TRANS ...@@ -4757,8 +4818,6 @@ case_expr: CASE case_arg when_clause_list case_default END_TRANS
c->args = lappend(c->args, w); c->args = lappend(c->args, w);
} }
$$ = (Node *)c; $$ = (Node *)c;
elog(NOTICE,"COALESCE() not yet fully implemented");
} }
; ;
...@@ -5147,7 +5206,6 @@ ColLabel: ColId { $$ = $1; } ...@@ -5147,7 +5206,6 @@ ColLabel: ColId { $$ = $1; }
| COALESCE { $$ = "coalesce"; } | COALESCE { $$ = "coalesce"; }
| CONSTRAINT { $$ = "constraint"; } | CONSTRAINT { $$ = "constraint"; }
| COPY { $$ = "copy"; } | COPY { $$ = "copy"; }
| CROSS { $$ = "cross"; }
| CURRENT { $$ = "current"; } | CURRENT { $$ = "current"; }
| DO { $$ = "do"; } | DO { $$ = "do"; }
| ELSE { $$ = "else"; } | ELSE { $$ = "else"; }
...@@ -5210,7 +5268,8 @@ makeA_Expr(int oper, char *opname, Node *lexpr, Node *rexpr) ...@@ -5210,7 +5268,8 @@ makeA_Expr(int oper, char *opname, Node *lexpr, Node *rexpr)
/* makeRowExpr() /* makeRowExpr()
* Generate separate operator nodes for a single row descriptor expression. * Generate separate operator nodes for a single row descriptor expression.
* Perhaps this should go deeper in the parser someday... - thomas 1997-12-22 * Perhaps this should go deeper in the parser someday...
* - thomas 1997-12-22
*/ */
static Node * static Node *
makeRowExpr(char *opr, List *largs, List *rargs) makeRowExpr(char *opr, List *largs, List *rargs)
...@@ -5250,23 +5309,6 @@ makeRowExpr(char *opr, List *largs, List *rargs) ...@@ -5250,23 +5309,6 @@ makeRowExpr(char *opr, List *largs, List *rargs)
elog(ERROR,"Operator '%s' not implemented for row expressions",opr); elog(ERROR,"Operator '%s' not implemented for row expressions",opr);
} }
#ifdef NOT_USED
while ((largs != NIL) && (rargs != NIL))
{
larg = lfirst(largs);
rarg = lfirst(rargs);
if (expr == NULL)
expr = makeA_Expr(OP, opr, larg, rarg);
else
expr = makeA_Expr(AND, NULL, expr, makeA_Expr(OP, opr, larg, rarg));
largs = lnext(largs);
rargs = lnext(rargs);
}
pprint(expr);
#endif
return expr; return expr;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment