-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
dba5234
commit 96bdb2a
Showing
47 changed files
with
4,483 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
github.com/chzyer/logex v1.2.1 h1:XHDu3E6q+gdHgsdTPH6ImJMIp436vR6MPtH8gP05QzM= | ||
github.com/chzyer/logex v1.2.1/go.mod h1:JLbx6lG2kDbNRFnfkgvh4eRJRPX1QCoOIWomwysCBrQ= | ||
github.com/chzyer/readline v1.5.1 h1:upd/6fQk4src78LMRzh5vItIt361/o4uq553V8B5sGI= | ||
github.com/chzyer/readline v1.5.1/go.mod h1:Eh+b79XXUwfKfcPLepksvw2tcLE/Ct21YObkaSkeBlk= | ||
github.com/chzyer/test v1.0.0 h1:p3BQDXSxOhOG0P9z6/hGnII4LGiEPOYBhs8asl/fC04= | ||
github.com/chzyer/test v1.0.0/go.mod h1:2JlltgoNkt4TW/z9V/IzDdFaMTM2JPIi26O1pF38GC8= | ||
github.com/d4l3k/messagediff v1.2.1 h1:ZcAIMYsUg0EAp9X+tt8/enBE/Q8Yd5kzPynLyKptt9U= | ||
github.com/d4l3k/messagediff v1.2.1/go.mod h1:Oozbb1TVXFac9FtSIxHBMnBCq2qeH/2KkEQxENCrlLo= | ||
github.com/tylertreat/BoomFilters v0.0.0-20210315201527-1a82519a3e43 h1:QEePdg0ty2r0t1+qwfZmQ4OOl/MB2UXIeJSpIZv56lg= | ||
github.com/tylertreat/BoomFilters v0.0.0-20210315201527-1a82519a3e43/go.mod h1:OYRfF6eb5wY9VRFkXJH8FFBi3plw2v+giaIu7P054pM= | ||
github.com/xwb1989/sqlparser v0.0.0-20180606152119-120387863bf2 h1:zzrxE1FKn5ryBNl9eKOeqQ58Y/Qpo3Q9QNxKHX5uzzQ= | ||
github.com/xwb1989/sqlparser v0.0.0-20180606152119-120387863bf2/go.mod h1:hzfGeIUDq/j97IG+FhNqkowIyEcD88LrW6fyU3K3WqY= | ||
golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= | ||
golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y= | ||
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,173 @@ | ||
package godb | ||
|
||
import ( | ||
"fmt" | ||
) | ||
|
||
type Aggregator struct { | ||
// Expressions that when applied to tuples from the child operators, | ||
// respectively, return the value of the group by key tuple | ||
groupByFields []Expr | ||
|
||
// Aggregation states that serves as a template as to which types of | ||
// aggregations in which order are to be computed for every group. | ||
newAggState []AggState | ||
|
||
child Operator // the child operator for the inputs to aggregate | ||
} | ||
|
||
type AggType int | ||
|
||
const ( | ||
IntAggregator AggType = iota | ||
StringAggregator AggType = iota | ||
) | ||
|
||
const DefaultGroup int = 0 // for handling the case of no group-by | ||
|
||
// Construct an aggregator with a group-by. | ||
func NewGroupedAggregator(emptyAggState []AggState, groupByFields []Expr, child Operator) *Aggregator { | ||
return &Aggregator{groupByFields, emptyAggState, child} | ||
} | ||
|
||
// Construct an aggregator with no group-by. | ||
func NewAggregator(emptyAggState []AggState, child Operator) *Aggregator { | ||
return &Aggregator{nil, emptyAggState, child} | ||
} | ||
|
||
// Return a TupleDescriptor for this aggregation. | ||
// | ||
// If the aggregator has no group-by, the returned descriptor should contain the | ||
// union of the fields in the descriptors of the aggregation states. If the | ||
// aggregator has a group-by, the returned descriptor will additionally start | ||
// with the group-by fields, and then the aggregation states descriptors like | ||
// that without group-by. | ||
// | ||
// HINT: for groupByFields, you can use [Expr.GetExprType] to get the FieldType. | ||
// | ||
// HINT: use [TupleDesc.merge] to merge the two [TupleDesc]s. | ||
func (a *Aggregator) Descriptor() *TupleDesc { | ||
// TODO: some code goes here | ||
return &TupleDesc{} //replace me | ||
} | ||
|
||
// Returns an iterator over the results of the aggregate. The aggregate should | ||
// be the result of aggregating each group's tuples and the iterator should | ||
// iterate through each group's result. In the case where there is no group-by, | ||
// the iterator simply iterates through only one tuple, representing the | ||
// aggregation of all child tuples. | ||
func (a *Aggregator) Iterator(tid TransactionID) (func() (*Tuple, error), error) { | ||
// the child iterator | ||
childIter, err := a.child.Iterator(tid) | ||
if err != nil { | ||
return nil, err | ||
} | ||
if childIter == nil { | ||
return nil, GoDBError{MalformedDataError, "child iter unexpectedly nil"} | ||
} | ||
|
||
// the map that stores the aggregation state of each group | ||
aggState := make(map[any]*[]AggState) | ||
if a.groupByFields == nil { | ||
var newAggState []AggState | ||
for _, as := range a.newAggState { | ||
copy := as.Copy() | ||
if copy == nil { | ||
return nil, GoDBError{MalformedDataError, "aggState Copy unexpectedly returned nil"} | ||
} | ||
newAggState = append(newAggState, copy) | ||
} | ||
|
||
aggState[DefaultGroup] = &newAggState | ||
} | ||
|
||
// the list of group key tuples | ||
var groupByList []*Tuple | ||
// the iterator for iterating thru the finalized aggregation results for each group | ||
var finalizedIter func() (*Tuple, error) | ||
|
||
return func() (*Tuple, error) { | ||
// iterates thru all child tuples | ||
for t, err := childIter(); t != nil || err != nil; t, err = childIter() { | ||
if err != nil { | ||
return nil, err | ||
} | ||
if t == nil { | ||
return nil, nil | ||
} | ||
|
||
if a.groupByFields == nil { // adds tuple to the aggregation in the case of no group-by | ||
for i := 0; i < len(a.newAggState); i++ { | ||
(*aggState[DefaultGroup])[i].AddTuple(t) | ||
} | ||
} else { // adds tuple to the aggregation with grouping | ||
keygenTup, err := extractGroupByKeyTuple(a, t) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
key := keygenTup.tupleKey() | ||
if aggState[key] == nil { | ||
asNew := make([]AggState, len(a.newAggState)) | ||
aggState[key] = &asNew | ||
groupByList = append(groupByList, keygenTup) | ||
} | ||
|
||
addTupleToGrpAggState(a, t, aggState[key]) | ||
} | ||
} | ||
|
||
if finalizedIter == nil { // builds the iterator for iterating thru the finalized aggregation results for each group | ||
if a.groupByFields == nil { | ||
var tup *Tuple | ||
for i := 0; i < len(a.newAggState); i++ { | ||
newTup := (*aggState[DefaultGroup])[i].Finalize() | ||
tup = joinTuples(tup, newTup) | ||
} | ||
finalizedIter = func() (*Tuple, error) { return nil, nil } | ||
return tup, nil | ||
} else { | ||
finalizedIter = getFinalizedTuplesIterator(a, groupByList, aggState) | ||
} | ||
} | ||
return finalizedIter() | ||
}, nil | ||
} | ||
|
||
// Given a tuple t from a child iterator, return a tuple that identifies t's | ||
// group. The returned tuple should contain the fields from the groupByFields | ||
// list passed into the aggregator constructor. The ith field can be extracted | ||
// from the supplied tuple using the EvalExpr method on the ith expression of | ||
// groupByFields. | ||
// | ||
// If there is any error during expression evaluation, return the error. | ||
func extractGroupByKeyTuple(a *Aggregator, t *Tuple) (*Tuple, error) { | ||
// TODO: some code goes here | ||
return &Tuple{}, fmt.Errorf("extractGroupByKeyTuple not implemented.") // replace me | ||
} | ||
|
||
// Given a tuple t from child and (a pointer to) the array of partially computed | ||
// aggregates grpAggState, add t into all partial aggregations using | ||
// [AggState.AddTuple]. If any of the array elements is of grpAggState is null | ||
// (i.e., because this is the first invocation of this method, create a new | ||
// aggState using [aggState.Copy] on appropriate element of the a.newAggState | ||
// field and add the new aggState to grpAggState. | ||
func addTupleToGrpAggState(a *Aggregator, t *Tuple, grpAggState *[]AggState) { | ||
// TODO: some code goes here | ||
} | ||
|
||
// Given that all child tuples have been added, return an iterator that iterates | ||
// through the finalized aggregate result one group at a time. The returned | ||
// tuples should be structured according to the TupleDesc returned from the | ||
// Descriptor() method. | ||
// | ||
// HINT: you can call [aggState.Finalize] to get the field for each AggState. | ||
// Then, you should get the groupByTuple and merge it with each of the AggState | ||
// tuples using the joinTuples function in tuple.go you wrote in lab 1. | ||
func getFinalizedTuplesIterator(a *Aggregator, groupByList []*Tuple, aggState map[any]*[]AggState) func() (*Tuple, error) { | ||
// TODO: some code goes here | ||
return func() (*Tuple, error) { | ||
// TODO: some code goes here | ||
return nil, fmt.Errorf("getFinalizedTuplesIterator not implemented.") // replace me | ||
} | ||
} |
Oops, something went wrong.