Malloy Documentation
search

There are a few places where Malloy 4.0 will require existing code to change. In the transitional period, both the 4.0 and Pre-4.0 syntax is accepted, and a warning will be generated for Pre-4.0 constructs, to give users guidance in changing their code. Once 4.0 fully releases, these will be errors and not warnings.

This is a list of all the 4.0 compatibility messages, with examples code showing how to transform existing code for Malloy 4.0.

Extend a source with extend

Implicit source extension is deprecated, use the `extend` operator.
Source extension with "+" is deprecated, use the "extend" operator

Creating a new source by adding new propertied to an existing source is called extension in Malloy. There have been three different ways to express extension of a source, now only the form source extend { extensions } is accepted.

Pre-4.0 Malloy 4.0 Malloy
 source: flights is table('duckdb:flights.parquet') {   primary_key: id }
 source: flights is duckdb.table('flights.parquet') extend {   primary_key: id }

Refine a query with +

Implicit query refinement is deprecated, use the `+` operator.
The `refine` keyword is deprecated, use the `+` operator

Creating a new query by adding properties to an existing query is called refinement in Malloy. There have been three different ways to express refinements, now only the form query + { refinements } is accepted.

Pre-4.0 Malloy 4.0 Malloy
query: flights -> by_carrier { limit: 5 } query: flights -> by_carrier refine { limit: 5 }
query: flights -> by_carrier refine + { limit: 5 }

Sources contain views

Use view: inside of a source instead of query:

The object inside a source which can be used to build a query is now called a view:, it used to be called a query:

Pre-4.0 Malloy 4.0 Malloy
 source: flights is table('duckdb:flights.parquet') {   query: by_carrier is -> {     group_by: carrier; aggregate: flight_count is count()   } }  
 source: flights is table('duckdb:flights.parquet') extend {   view: by_carrier is {     group_by: carrier; aggregate: flight_count is count()   } }  

select: instead of project:

`project:` keyword is deprecated, use `select:`

The project: keyword has been renamed to select:.

Pre-4.0 Malloy 4.0 Malloy
query: flights -> { project: * } run: flights -> { select: * }

New syntax for count(*) and count(distinct)

The SQL syntax for distinct counts count(distinct expression) is deprecated in favor of count(expression).

`count(distinct expression)` deprecated, use `count(expression)` instead
Pre-4.0 Malloy 4.0 Malloy
query: people -> {     aggregate: distinct_first_names is count(distinct first_name) }
run: people -> {     aggregate: distinct_first_names is count(first_name) }
`*` illegal inside `count()`

The SQL syntax for counting the records of a table count(*) is deprecated in favor of count().

Pre-4.0 Malloy 4.0 Malloy
query: flights -> { aggregate: flight_count is count(*) } run: flights -> { aggregate: flight_count is count() }

{? } deprecated

Filter shortcut `{? condition }` is deprecated; use `{ where: condition }` instead

The old filter shortcut syntax {? condition } is deprecated. Use the more explicit { where: condition } syntax instead.

Pre-4.0 Malloy 4.0 Malloy
flight_count {? distance > 2 } flight_count { where: distance > 2}
flights {? distance > 2 } flights extend { where: distance > 2}
by_carrier {? distance > 2 } by_carrier + { where: distance > 2}

Nesting Malloy in SQL with %{}% is now %{}

Use `%{ ... }` instead of `%{ ... }%`

Query interpolation in SQL strings should use } to end the interpolation rather than }%.

Pre-4.0 Malloy 4.0 Malloy
 sql: sql_source is {    select: """SELECT * FROM (%{ flights -> by_carrier }%)"""   connection: "bigquery" }
 source: sql_source is    bigquery.sql("""SELECT * FROM (%{ flights -> by_carrier })""")

-> no longer begins a named query or view

Leading arrow (`->`) when referencing a query is deprecated; remove the arrow

It used to be necessary to use an arrow (->) to base a new source or query off of an existing query. This is no longer necessary.

Pre-4.0 Malloy 4.0 Malloy
query: -> flights_by_carrier -> { project: * } run: flights_by_carrier -> { select: * }
Leading '->' in a view or nest definition is no longer needed.

A leading -> operator no longer signifies the beginning of a query pipeline.

Pre-4.0 Malloy 4.0 Malloy
query: x is -> { group_by: y}
nest: z is -> x + { aggregate: c is count() }
view: x is { group_by: y}
nest: z is x + { aggregate: c is count() }

SQL and tables are accessed through the connection

`table('connection_name:table_path')` is deprecated; use `connection_name.table('table_path')`

When referencing a SQL table, the connection name should now be specified connection_name.table('table_path') instead of table('connection_name:table_path').

Pre-4.0 Malloy 4.0 Malloy
source: flights is table('duckdb:flights.parquet') source: flights is duckdb.table('flights.parquet')
`from_sql` is deprecated; use `connection_name.sql(...)` as a source directly

Prior to Malloy 4.0, SQL blocks were declared using sql: sql_block is ... and used with from_sql(sql_block) .... Now, SQL blocks are created with the connection_name.sql(...) syntax and can be used as sources directly.

Pre-4.0 Malloy 4.0 Malloy
 sql: sql_block is {    select: """SELECT * FROM (%{ flights -> by_carrier }%)"""   connection: "bigquery" }   source: sql_source is from_sql(sql_block)
 source: sql_source is    bigquery.sql("""SELECT * FROM (%{ flights -> by_carrier })""")
`sql:` statement is deprecated, use `connection_name.sql(...)` instead

Prior to Malloy 4.0, SQL blocks were declared using sql: sql_block is .... Now, SQL blocks are created with the connection_name.sql(...) syntax.

Pre-4.0 Malloy 4.0 Malloy
 sql: sql_block is {    select: """SELECT * FROM (%{ flights -> by_carrier }%)"""   connection: "bigquery" }
 source: sql_source is    bigquery.sql("""SELECT * FROM (%{ flights -> by_carrier })""")

Queries can be used as a source without from()

`from(some_query)` is deprecated; use `some_query` directly

Prior to Malloy 4.0, the from() function was required to convert a query into a source. Now a query can be used directly anywhere where a source is needed.

Pre-4.0 Malloy 4.0 Malloy
 source: source_from_query is from(flights -> by_carrier) {   measure: carrier_count is count() }
 source: source_from_query is flights -> by_carrier extend {   measure: carrier_count is count() }

Extensions to view objects move to an extend: {} section

When the ability to extend the source of a query operation was first introduced, the extensions were written alongside the query. Now those extensions should be written in an extend: block inside the query.

Joins in queries are deprecated, move into an `extend:` block.

On the fly joins in queries should now be specified in an extend: block.

Pre-4.0 Malloy 4.0 Malloy
 run: flights -> {   join_one: carriers with carrier   group_by: carriers.nickname }
 run: flights -> {   extend: { join_one: carriers with carrier }   group_by: carriers.nickname }
`declare:` is deprecated; use `dimension:` or `measure:` inside a source or `extend:` block

The declare: keyword has been deprecated, and should be replaced with dimension: or measure:. If the declare: is used inside a query, it also needs to be put into an extend: block.

Pre-4.0 Malloy 4.0 Malloy
 source: flights is table('duckdb:flights.parquet') {   declare: distance_km is distance * 1.6    declare: flight_count is count() }
 source: flights is duckdb.table('flights.parquet') {   dimension: distance_km is distance * 1.6    measure: flight_count is count() }
 run: flights -> {   declare: distance_km is distance * 1.6    declare: flight_count is count()   group_by: distance_km   aggregate: flight_count }
 run: flights -> {   extend: {     dimension: distance_km is distance * 1.6     measure: flight_count is count()   }   group_by: distance_km   aggregate: flight_count }

top: ... by removed

`by` clause of `top` statement unupported. Use `order_by` instead

Previously, you could specify an ordering field in the top: specification. Now you should use order_by: explicitly.

Pre-4.0 Malloy 4.0 Malloy
query: flights -> {    group_by: carrier   aggregate: flight_count   top: 5 by flight_count }
query: flights -> {    group_by: carrier   aggregate: flight_count   limit: 5   order_by: flight_count }

Write nameless queries with run:

Anonymous `query:` statements are deprecated, use `run:` instead

query: should now only be used to declare a query with a name. To run a query without naming it, use run:.

Pre-4.0 Malloy 4.0 Malloy
query: flights -> by_carrier run: flights -> by_carrier
query: flights_by_carrier is flights -> by_carrier Unchanged