Skip to content

Commit

Permalink
add string agg function (dataform-co#1094)
Browse files Browse the repository at this point in the history
* add string agg function

* fix spelling mistake in README

* another sp

* omit redshift for test

* switch != to !==

Co-authored-by: Dan Lee <[email protected]>
  • Loading branch information
DanLee and Dan Lee authored Nov 10, 2020
1 parent ceccc5b commit a1ccc79
Show file tree
Hide file tree
Showing 4 changed files with 47 additions and 12 deletions.
2 changes: 1 addition & 1 deletion packages/@dataform/sql/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ pkg_json(
],
main = "bundle.js",
types = "bundle.d.ts",
version = "0.2.0",
version = "0.3.0",
)

pkg_bundle(
Expand Down
23 changes: 12 additions & 11 deletions sql/README → sql/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ Useful functions for constructing SQL statements in Dataform packages.
- Redshift
- Snowflake

*If you would like us to add support for another warehouse, please get in touch via [email](mailto:[email protected]) or [Slack](https://dataform.co/slack)*
_If you would like us to add support for another warehouse, please get in touch via [email](mailto:[email protected]) or [Slack](https://dataform.co/slack)_

## Installation

Expand All @@ -17,34 +17,35 @@ Useful functions for constructing SQL statements in Dataform packages.
### Common SQL functions

#### surrogateKey

Creates a unique hash from a list of fields. Useful for generating a surrogate key for a table.

`${sql.surrogateKey(["field_one", "field_two"])}`

#### windowFunction

Creates a window function with the given configuration.

`${sql.windowFunction({
name: "window_function_name",
value: "target_column",
ignoreNulls: true,
windowSpecification: {
partitionFields: ["field_to_partition_by_one", "field_to_partition_by_two"],
orderFields: ["field_to_order_by_one", "field_to_order_by_two"],
frameClause: "rows between 0 preceding and unbounded following"
}
})}`
`${sql.windowFunction({ name: "window_function_name", value: "target_column", ignoreNulls: true, windowSpecification: { partitionFields: ["field_to_partition_by_one", "field_to_partition_by_two"], orderFields: ["field_to_order_by_one", "field_to_order_by_two"], frameClause: "rows between 0 preceding and unbounded following" } })}`

#### asTimestamp

Casts the field to timestamp type

`${sql.asTimestamp("field")}`

#### asString

Casts the field to timestamp type

`${sql.asString("field")}`

#### stringAgg

Groups the values in a field into a concatenated string, with an optional delimiter value that defaults to ","

`${sql.stringAgg("field", "delimiter")}`

### Timestamp functions

Calculate the time difference between two timestamps.
Expand Down
9 changes: 9 additions & 0 deletions sql/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,15 @@ export class Sql {
}
}

// String aggregation

public stringAgg(field: string, delimiter = ",") {
if (this.dialect === "snowflake" || this.dialect === "redshift") {
return `listagg(${field}, '${delimiter}')`;
}
return `string_agg(${field}, '${delimiter}')`;
}

// Convenience methods for builders.
public json<S extends ISelectSchema>(data: S[]) {
return new JSONBuilder<S>(this, data);
Expand Down
25 changes: 25 additions & 0 deletions sql/integration.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,31 @@ suite("builders", { parallel: true }, ({ before, after }) => {
expect(result[0].max).equals(1);
expect(result[0].first_value).equals(1);
});
// skipping this test for redshift as the function is only supported on user-defined-tables
// i.e. not when just querying a select statement with no table
if (name !== "redshift") {
test("string agg", async () => {
const rows = [
{
a: "foo"
},
{
a: "bar"
}
];
const query = sql.from(sql.json(rows)).select({
agg: sql.stringAgg("a"),
agg_hyphen: sql.stringAgg("a", "-")
});

const result: any = await execute(query);
expect(result.length).equals(1);
expect(result[0]).deep.equals({
agg: "foo,bar",
agg_hyphen: "foo-bar"
});
});
}

test("timestamp diff", async () => {
const rows = [
Expand Down

0 comments on commit a1ccc79

Please sign in to comment.