From 1e419258977485149eac508992ee5f1117b17995 Mon Sep 17 00:00:00 2001 From: hgouchet Date: Thu, 22 Dec 2016 01:03:47 +0100 Subject: [PATCH 1/2] [twgit] Init hotfix 'hotfix-0.1.5'. From b5ce430a0fc6fbb2cdb5b804ea4a4a542693ee56 Mon Sep 17 00:00:00 2001 From: hgouchet Date: Thu, 22 Dec 2016 17:42:39 +0100 Subject: [PATCH 2/2] Adds formatter to output AWQL query as expected by Adwords --- format.go | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++ format_test.go | 40 ++++++++++++++++++++++++++++++++ statement.go | 3 +++ 3 files changed, 105 insertions(+) create mode 100644 format.go create mode 100644 format_test.go diff --git a/format.go b/format.go new file mode 100644 index 0000000..e199ae2 --- /dev/null +++ b/format.go @@ -0,0 +1,62 @@ +package awqlparse + +import "strconv" + +// String formats a SelectStmt as expected by Google Adwords. +// Indeed, aggregate functions, ORDER BY, GROUP BY and LIMIT are not supported for reports. +// Implements fmt.Stringer interface. +func (s SelectStatement) String() (q string) { + if len(s.Fields) == 0 || s.TableName == "" { + return + } + // Concat selected fields. + q = "SELECT " + for i, c := range s.Fields { + if i > 0 { + q += ", " + } + q += c.ColumnName + } + // Data source + q += " FROM " + s.TableName + // Conditions + if len(s.Where) > 0 { + q += " WHERE " + for i, c := range s.Where { + if i > 0 { + q += " AND " + } + q += c.ColumnName + " " + c.Operator + if len(c.Value) > 1 { + q += " [" + for y, v := range c.Value { + if y > 0 { + q += " ," + } + if c.IsValueLiteral { + q += " " + v + } else { + q += " " + strconv.Quote(v) + } + } + q += " ]" + } else if c.IsValueLiteral { + q += " " + c.Value[0] + } else { + q += " " + strconv.Quote(c.Value[0]) + } + } + } + // Range date + d := s.During + if ds := len(d); ds > 0 { + q += " DURING " + if ds == 2 { + q += d[0] + "," + d[1] + } else { + // Literal range date + q += d[0] + } + } + return +} diff --git a/format_test.go b/format_test.go new file mode 100644 index 0000000..1ef722a --- /dev/null +++ b/format_test.go @@ -0,0 +1,40 @@ +package awqlparse_test + +import ( + "strings" + "testing" + + awql "github.com/rvflash/awql-parser" +) + +func TestSelectStmt_String(t *testing.T) { + var tests = []struct { + fq, tq string + }{ + { + fq: `SELECT CampaignName FROM CAMPAIGN_PERFORMANCE_REPORT`, + tq: `SELECT CampaignName FROM CAMPAIGN_PERFORMANCE_REPORT`, + }, + { + fq: `SELECT SUM(Cost) AS c FROM CAMPAIGN_PERFORMANCE_REPORT WHERE CampaignStatus = 'ENABLED'`, + tq: `SELECT Cost FROM CAMPAIGN_PERFORMANCE_REPORT WHERE CampaignStatus = "ENABLED"`, + }, + { + fq: `SELECT CampaignName, Cost FROM CAMPAIGN_PERFORMANCE_REPORT GROUP BY 1 ORDER BY 2 DESC`, + tq: `SELECT CampaignName, Cost FROM CAMPAIGN_PERFORMANCE_REPORT`, + }, + { + fq: `SELECT CampaignName FROM CAMPAIGN_PERFORMANCE_REPORT DURING 20161224,20161225 LIMIT 10`, + tq: `SELECT CampaignName FROM CAMPAIGN_PERFORMANCE_REPORT DURING 20161224,20161225`, + }, + } + + for i, qt := range tests { + stmts, _ := awql.NewParser(strings.NewReader(qt.fq)).Parse() + if stmt, ok := stmts[0].(awql.SelectStmt); ok { + if q := stmt.String(); q != qt.tq { + t.Errorf("%d. Expected the query '%v' with '%s', received '%v'", i, qt.tq, qt.fq, q) + } + } + } +} diff --git a/statement.go b/statement.go index 5f3bd27..6cd700c 100644 --- a/statement.go +++ b/statement.go @@ -1,5 +1,7 @@ package awqlparse +import "fmt" + // Column represents a column. type Column struct { ColumnName, ColumnAlias string @@ -153,6 +155,7 @@ type SelectStmt interface { OrderList() []*Ordering StartIndex() int PageSize() (int, bool) + fmt.Stringer } // ConditionList returns the condition list.