Skip to content
Browse files

Create Alias for parser.

This should make a minimal parser to parse Var and RangeVar.  Expr is
now an interface, although it is still not clear to me how to represent
this kind of abstract super type.
  • Loading branch information...
1 parent 8b74160 commit 1bcd54a25ebcc7a475152d8066de556467b173e7 @umitanuki committed
Showing with 95 additions and 19 deletions.
  1. +7 −6 src/bigpot/access/common.go
  2. +4 −3 src/bigpot/parser/gram_test.go
  3. +57 −10 src/bigpot/parser/query.go
  4. +27 −0 src/bigpot/parser/query_test.go
View
13 src/bigpot/access/common.go
@@ -44,6 +44,7 @@ var Anum_attribute_atttype int32 = 4
type Relation struct {
RelId system.Oid
+ RelName system.Name
RelDesc *TupleDesc
}
@@ -73,19 +74,19 @@ func HeapOpen(relid system.Oid) (*Relation, error) {
if relid == ClassRelId {
relation := &Relation {
RelId: relid,
+ RelName: "bp_class",
RelDesc: ClassTupleDesc,
}
return relation, nil
} else if relid == AttributeRelId {
relation := &Relation {
RelId: relid,
+ RelName: "bp_attribute",
RelDesc: AttributeTupleDesc,
}
return relation, nil
}
- relation := &Relation{RelId: relid}
-
/*
* Collect class information. Currently, nothing but name is stored.
*/
@@ -105,10 +106,10 @@ func HeapOpen(relid system.Oid) (*Relation, error) {
}
defer class_scan.EndScan()
class_tuple, err := class_scan.Next()
- _ = class_tuple
-// relation = &Relation{
-// RelId: relid,
-// }
+ relation := &Relation{
+ RelId: relid,
+ RelName: class_tuple.Get(2).(system.Name),
+ }
attr_rel, err := HeapOpen(AttributeRelId)
if err != nil {
View
7 src/bigpot/parser/gram_test.go
@@ -3,6 +3,7 @@ package parser
import (
. "launchpad.net/gocheck"
"testing"
+ "bigpot/system"
)
// Hook up gocheck into the gotest runner.
@@ -20,7 +21,7 @@ func (s *MySuite) TestYYParse_1(c *C) {
if !ok {
c.Error("node is not SelectStmt")
}
- c.Check(node.target[0].name, Equals, "col1")
- c.Check(node.target[1].name, Equals, "col2")
- c.Check(node.from[0].name, Equals, "tab1")
+ c.Check(node.targetList[0].name, Equals, "col1")
+ c.Check(node.targetList[1].name, Equals, "col2")
+ c.Check(node.fromList[0].(*RangeVar).RelationName, Equals, system.Name("tab1"))
}
View
67 src/bigpot/parser/query.go
@@ -14,23 +14,29 @@ const (
CMD_DELETE
)
+type Alias struct {
+ AliasName string
+ ColumnNames []string
+}
+
type RangeVar struct {
SchemaName system.Name
RelationName system.Name
+ AliasName Alias
}
-type Expr struct {
- ReturnType system.Oid
+type Expr interface {
+ ResultType() system.Oid
}
type Var struct {
- Expr
+ resultType system.Oid
VarNo uint16
VarAttNo uint16
}
type TargetEntry struct {
- Expr *Expr
+ Expr Expr
ResNo uint16
ResName uint16
ResJunk bool
@@ -49,7 +55,8 @@ const (
type RangeTblEntry struct {
RteType RteType
/* for relation */
- relid system.Oid
+ RelId system.Oid
+ RefAlias *Alias
}
type Query struct {
@@ -121,13 +128,14 @@ func (parser *ParserImpl) transformFromClause(stmt *SelectStmt) error {
case *RangeVar:
rv := item.(*RangeVar)
rte := &RangeTblEntry{}
- /* TODO: implement relation_open_rv() */
relation, err := rv.OpenRelation()
if err != nil {
return err
}
- rte.relid = relation.RelId
- /* TODO: make Alias and add it to namespace, not Rte */
+ defer relation.Close()
+ rte.RelId = relation.RelId
+ rte.RefAlias = buildAlias(relation)
+
parser.namespace = append(parser.namespace, rte)
}
}
@@ -135,6 +143,20 @@ func (parser *ParserImpl) transformFromClause(stmt *SelectStmt) error {
return nil
}
+func buildAlias(relation *access.Relation) *Alias {
+ alias := &Alias{}
+ /* TODO: Add check for user-provided alias name */
+ alias.AliasName = string(relation.RelName)
+
+ names := []string{}
+ for _, attr := range relation.RelDesc.Attrs {
+ names = append(names, string(attr.AttName))
+ }
+ alias.ColumnNames = names
+
+ return alias
+}
+
func (parser *ParserImpl) transformTargetList(targetList []*ResTarget) (tlist []*TargetEntry, err error) {
for _, item := range targetList {
var tle *TargetEntry
@@ -157,12 +179,33 @@ func (parser *ParserImpl) transformTargetEntry(restarget *ResTarget) (tle *Targe
return
}
-func (parser *ParserImpl) transformExpr(node Node) (expr *Expr, err error) {
+func (parser *ParserImpl) transformExpr(node Node) (expr Expr, err error) {
switch node.(type) {
default:
return nil, parseError("unknown node type")
case *ColumnRef:
- /* TODO: Explore namespace and transform to Var */
+ colref := node.(*ColumnRef)
+ /* TODO: use hash instead of linear search? */
+ found := false
+ var variable Var
+ for rteidx, rte := range parser.namespace {
+ for attidx, attname := range rte.RefAlias.ColumnNames {
+ if attname == colref.name {
+ if found {
+ return nil, parseError("ambiguous column reference")
+ }
+ found = true
+ variable.VarNo = uint16(rteidx + 1)
+ variable.VarAttNo = uint16(attidx + 1)
+ }
+ }
+
+ }
+ if !found {
+ return nil, parseError("column reference not found")
+ }
+
+ return Expr(&variable), nil
}
@@ -191,3 +234,7 @@ func (rv *RangeVar) OpenRelation() (rel *access.Relation, err error) {
return access.HeapOpen(relid)
}
+
+func (node *Var) ResultType() system.Oid {
+ return node.resultType
+}
View
27 src/bigpot/parser/query_test.go
@@ -0,0 +1,27 @@
+package parser
+
+import (
+ . "launchpad.net/gocheck"
+// "testing"
+ "bigpot/access"
+ "bigpot/system"
+)
+
+var _ = Suite(&MySuite{})
+func (s *MySuite) TestBuildAlias(c *C) {
+ relation := access.Relation{
+ RelName: "mytable",
+ RelDesc: &access.TupleDesc{
+ Attrs: []*access.Attribute{
+ {"mycol1", system.NameType},
+ {"mycol2", system.Int4Type},
+ },
+ },
+ }
+
+ alias := buildAlias(&relation)
+ c.Check(alias.AliasName, Equals, "mytable")
+ c.Check(len(alias.ColumnNames), Equals, 2)
+ c.Check(alias.ColumnNames[0], Equals, "mycol1")
+ c.Check(alias.ColumnNames[1], Equals, "mycol2")
+}

0 comments on commit 1bcd54a

Please sign in to comment.
Something went wrong with that request. Please try again.