---
title: Converting Legacy scripts to Core+ Scripts Cheat Sheet
sidebar_label: Legacy to Core+ Cheat Sheet
---

See the User Guide in the [Core docs](/core/docs/conceptual/deephaven-overview) and [Core+ docs](../enterprise-overview.md) for comprehensive documentation on the new APIs.

## Data access methods

| Deephaven method in Legacy | Python method in Core+ | Groovy method in Core+ |
| -------------------------- | ---------------------- | ---------------------- |
| `db.i`                     | `db.live_table`        | `db.liveTable`         |
| `db.t`                     | `db.historical_table`  | `db.historicalTable`   |

## Empty `.where()` clauses

In a Legacy worker, a `.where()` method applied to an uncoalesced table (e.g., the return from `db.t` before filtering
by a partitioning column) would coalesce the table. Alternatively, the table could explicitly be realized with the
`.coalesce()` method. In Core+, you must use the `.coalesce()` method instead of `.where()`.

## Snapshots

In a Legacy worker, `trigger.snapshot(source, ...)`
snapshots table `source` according to table `trigger`. In Core+,
the method is called `snapshotWhen` and the positions of the tables
are inverted in the call: the trigger is the argument and the source
is the table on which the operation is applied:
`source.snapshotWhen(trigger, ...)`.

In Legacy, the second argument to the `snapshot` call is a boolean
specifying if an initial snapshot should be made. In Core+, the
equivalent is to pass `SnapshotWhenOptions.Flag.INITIAL` in the
optional list of flags.

## Parameterized queries

Parameterized queries allow on-demand query execution with user-provided parameters through a UI panel. **This is a Legacy-only feature and is not available in Core+ workers**.

In Core+, parameterized queries are replaced by [deephaven.ui](https://github.com/deephaven/deephaven-plugins/blob/main/plugins/ui/README.md), which provides a richer and more flexible set of interactive capabilities.

### Key differences

| Legacy                                                                   | Core+                                                                             |
| ------------------------------------------------------------------------ | --------------------------------------------------------------------------------- |
| `ParameterizedQuery` with `Parameter` definitions                        | `deephaven.ui` components                                                         |
| UI-based parameter control panel                                         | Reactive UI components with Python/JavaScript                                     |
| Limited parameter types (String, Long, Double, DateTime, Boolean, Table) | Full range of UI components (text inputs, sliders, dropdowns, date pickers, etc.) |
| Fixed parameter validation with `Constraint` objects                     | Custom validation logic in Python                                                 |
| Results displayed via `scope.setResult()`                                | Direct table and plot rendering in UI                                             |

### Migration approach

To migrate a Legacy parameterized query to Core+:

1. Replace the `ParameterizedQuery` structure with a `deephaven.ui` application.
2. Convert `Parameter` definitions to appropriate UI input components (e.g., `ui.text_input`, `ui.slider`, `ui.date_input`).
3. Replace the query function's parameter retrieval logic with reactive UI state.
4. Remove `scope.setResult()` calls and directly return tables and visualizations.

For detailed information on Legacy parameterized queries, refer to the parameterized queries documentation in earlier versions of the documentation (Legacy only). For Core+ UI development, see the [deephaven.ui documentation](https://github.com/deephaven/deephaven-plugins/blob/main/plugins/ui/README.md).

## Migrating Persistent Queries

Persistent Queries (PQs) are queries that run regularly to perform data ingestion, analysis, and dashboard creation. Both Legacy and Core+ support PQs, but there are important differences in how they are created and managed.

### Worker types

- **Legacy workers**: Use the Legacy API and syntax.
- **Core+ workers**: Use the modern Core+ API and syntax (Python snake_case, updated imports, etc.).

### Migration steps

To migrate a PQ from a Legacy worker to a Core+ worker:

1. **Update the query script**: Convert all Legacy syntax to Core+ syntax using this cheat sheet.
2. **Change the worker type**: In the PQ configuration, switch from a Legacy worker to a Core+ worker.
3. **Test thoroughly**: Validate that the migrated query produces the same results.
4. **Update dependencies**: Ensure any custom libraries or plugins are compatible with Core+.

### Creating and managing PQs

Both Legacy and Core+ PQs are created and managed through:

- The [Query Monitor](../interfaces/web/query-monitor.md) UI.
- [Programmatic APIs](../query-management/pq-management.md) (Python and Groovy).

The PQ management APIs are largely the same between Legacy and Core+, but the query scripts themselves must use the appropriate syntax for the worker type.

For more information on PQs, see:

- [Persistent Query overview](../query-management/pq-overview.md).
- [Programmatic query management](../query-management/pq-management.md).

## Time handling

The Deephaven Core+ time library is very different from the Legacy Library, having been thoroughly modernized as described in these blog posts:

- [Time library rewrite: part 1](/blog/2023/06/09/time-library-rewrite)
- [Time library rewrite: part 2](/blog/2023/09/13/python-time)

In particular, Legacy queries that used `currentDateNy()` must use `today()`, business calendars are entirely re-written, and the syntax of periods as input to `time_table` have changed.

To get the current date, you must use the `today()` function, which takes an optional time zone. You can use a full time zone name like `America/New_York` or the shortcut `ET` for Eastern time. The equivalent function to `currentDateNy()` is either ``today(timeZone(`America/New_York`))`` or `today('ET')`, as in the following example:

```groovy
quotes = db.liveTable("Market", "EqQuote").where("Date=today('ET')")
```

```python
quotes = db.live_table("Market", "EqQuote").where("Date=today('ET')")
```

When the time zone is omitted, the `today()` function uses the value of the `user.timezone` property.

The common Legacy idiom `lastBusinessDateNy()` to get the previous business day's data has been replaced by functions on the [BusinessCalendar](/core/javadoc/io/deephaven/time/calendar/BusinessCalendar.html) class. First, you must retrieve the calendar with the `calendar()` function, which on a default Core+ installation returns the `USNYSE` business calendar. To verify your default business calendar, you can run the following command:

```groovy
println(io.deephaven.time.calendar.Calendars.calendar().name())
```

```python
import deephaven.calendar

print(deephaven.calendar.calendar().name())
```

You can specify an alternative business calendar name as an argument to the `calendar()` function. For filtering Date partitions, you may either use the `minusBusinessDays` method and pass `today()` as a String argument or use the `pastBusinessDate` method and convert the resulting `java.time.LocalDate` to a String.

As a shortcut, you can elide `calendar()` for the default calendar.

The following examples all retrieve the previous business day's data:

```groovy
quotes = db.historicalTable("Market", "EqQuote").where("Date=minusBusinessDays(today(), 1)")
quotes2 = db.historicalTable("Market", "EqQuote").where("Date=pastBusinessDate(1).toString()")
quotes3 = db.historicalTable("Market", "EqQuote").where("Date=calendar().minusBusinessDays(today(), 1)")
quotes4 = db.historicalTable("Market", "EqQuote").where("Date=calendar().pastBusinessDate(1).toString()")
quotes5 = db.historicalTable("Market", "EqQuote").where("Date=calendar(`USNYSE`).minusBusinessDays(today(), 1)")
quotes6 = db.historicalTable("Market", "EqQuote").where("Date=calendar(`USNYSE`).pastBusinessDate(1).toString()")
quotes7 = db.historical_table("Market", "EqQuote").where("Date=formatDate(calendar(`USNYSE`).pastBusinessDate(1))")
```

```python
quotes = db.historical_table("Market", "EqQuote").where(
    "Date=minusBusinessDays(today(), 1)"
)
quotes2 = db.historical_table("Market", "EqQuote").where(
    "Date=pastBusinessDate(1).toString()"
)
quotes3 = db.historical_table("Market", "EqQuote").where(
    "Date=calendar().minusBusinessDays(today(), 1)"
)
quotes4 = db.historical_table("Market", "EqQuote").where(
    "Date=calendar().pastBusinessDate(1).toString()"
)
quotes5 = db.historical_table("Market", "EqQuote").where(
    "Date=calendar(`USNYSE`).minusBusinessDays(today(), 1)"
)
quotes6 = db.historical_table("Market", "EqQuote").where(
    "Date=calendar(`USNYSE`).pastBusinessDate(1).toString()"
)
quotes7 = db.historical_table("Market", "EqQuote").where(
    "Date=formatDate(calendar(`USNYSE`).pastBusinessDate(1))"
)
```

> [!CAUTION]
> If you use the `pastBusinessDate` function, then you must convert the result from a `LocalDate` to a `String`. If you compare a `LocalDate` to your partitioning column, a match is impossible and the result is an empty table.

If you actually want yesterday's data instead of the previous business day's data, you can use `minusDays` in the clause, which will include non-business days (such as weekends) in the result. For example:

```groovy
quotes = db.historicalTable("Market", "EqQuote").where("Date=calendar().minusDays(today(), 1)")
```

```python
import deephaven.calendar

quotes = db.historical_table("Market", "EqQuote").where(
    "Date=calendar().minusDays(today(), 1)"
)
```

For time tables, you must use the new [Period syntax](https://deephaven.io/core/javadoc/io/deephaven/time/DateTimeUtils.html#parsePeriod(java.lang.String)). For example:

```groovy
fiveSeconds = timeTable("PT5s")
oneHour = timeTable("PT1h")
```

```python
from deephaven import time_table

five_seconds = time_table("PT5s")
one_hour = time_table("PT1h")
```

## Python

### Python-only summary of changes

- Method names are now `snake_case`. For example, `lastBy` becomes `last_by`.
- Aggregation names (previously `ComboAggregateFactory`) have changed, as detailed below. For example, `AggLast` becomes `agg.last`.
- In instances of more than one parameter, arguments may take array lists instead of multiple strings; e.g., `t.update(["Update Statement 1", "Update Statement 2", ...])`. These are marked in the "Python method renames" table below. For comparison:

  - In a Legacy script, `AggTypes` will be comma-separated: `source.by(AggCombo(AggType("Col1"), AggType("Col2 = NewCol1")), "Key1" , "Key2")`.
  - In Core, this becomes an `agg_list` within arrays:

    ```
    agg_list=[
       agg.first(["Col1 = NewCol1"]),
       agg.last(["Col2 = NewCol2"]),
    ]

    source.agg_by(agg_list, by=["GroupingColumns..."])
    ```

> [!IMPORTANT]
> This is not a comprehensive listing of all Python commands -- only those where the syntax has changed.

### Core+ Python import equivalents

| Legacy Python import                                                | Core+ Python import                                                                                                                        |
| ------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------ |
| `import com.illumon.iris.db.Plot.*`                                 | `from deephaven.plot import *`                                                                                                             |
| `import com.illumon.iris.db.Plot.colors.*`                          | `from deephaven.plot.color import *`                                                                                                       |
| `jpy.get_type("com.illumon.iris.db.v2.by.ComboAggregateFactory").*` | `from deephaven import agg`                                                                                                                |
| `import deephaven.Calendars`                                        | `import deephaven.calendar`                                                                                                                |
| `import deephaven.Plot`                                             | `import deephaven.plot`                                                                                                                    |
| `from deephaven.Calendars import`                                   | `from deephaven.calendar import`                                                                                                           |
| `from deephaven import Plot`                                        | `from deephaven import plot`                                                                                                               |
| `from deephaven import TableTools`                                  | <ul><li>`from deephaven import time_table`</li><li>`from deephaven import empty_table`</li><li>`from deephaven import new_table`</li></ul> |
| `from deephaven.Plot import`                                        | `from deephaven.plot import`                                                                                                               |
| `from deephaven.TableTools import emptyTable`                       | `from deephaven import empty_table`                                                                                                        |

### Python method renames

#### Table constructors

| Legacy              | Core+                                                                    | Syntax                                                                 |
| ------------------- | ------------------------------------------------------------------------ | ---------------------------------------------------------------------- |
| `db.timeTable`      | [`time_table`](/core/docs/reference/table-operations/create/timeTable)   | `time_table("PT1S")` Note: requires `from deephaven import time_table` |
| `ttools.emptyTable` | [`empty_table`](/core/docs/reference/table-operations/create/emptyTable) | `empty_table(N)` Note: requires `from deephaven import empty_table`    |

#### Aggregation

| Legacy                        | Core+                                                                              | Syntax                                                                       |
| ----------------------------- | ---------------------------------------------------------------------------------- | ---------------------------------------------------------------------------- |
| `AggArray`                    | [`agg.group`](/core/docs/reference/table-operations/group-and-aggregate/AggGroup)  | `.agg_by([agg.group(cols=["Y"])], by=["X"])`                                 |
| `AggCombo(<original params>)` | `agg_list`                                                                         | `agg_list = [<original params>]`                                             |
| `AggCount`                    | [`agg.count_`](/core/docs/reference/table-operations/group-and-aggregate/AggCount) | `.agg_by([agg.count_(col="Number")]`                                         |
| `AggFirst`                    | [`agg.first`](/core/docs/reference/table-operations/group-and-aggregate/AggFirst)  | `.agg_by([agg.first(cols=["Y"])], by=["X"])`                                 |
| `AggLast`                     | [`agg.last`](/core/docs/reference/table-operations/group-and-aggregate/AggLast)    | `.agg_by([agg.last(cols=["Y"])], by=["X"])`                                  |
| `AggMax`                      | [`agg.max_`](/core/docs/reference/table-operations/group-and-aggregate/AggMax)     | `.agg_by([agg.max_(cols=["Y"])], by=["X"])`                                  |
| `AggMed`                      | [`agg.median`](/core/docs/reference/table-operations/group-and-aggregate/AggMed)   | `.agg_by([agg.median(cols=["Number"])], by=["X"])`                           |
| `AggMin`                      | [`agg.min_`](/core/docs/reference/table-operations/group-and-aggregate/AggMin)     | `.agg_by([agg.min_(cols=["Y"])], by=["X"])`                                  |
| `AggPct`                      | [`agg.pct`](/core/docs/reference/table-operations/group-and-aggregate/AggPct)      | `.agg_by([agg.pct(percentile=0.68, cols=["PctNumber = Number"])], by=["X"])` |
| `AggStd`                      | [`agg.std`](/core/docs/reference/table-operations/group-and-aggregate/AggStd)      | `.agg_by([agg.std(cols=["Number"])], by=["X"])`                              |
| `AggSum`                      | [`agg.sum_`](/core/docs/reference/table-operations/group-and-aggregate/AggSum)     | `.agg_by([agg.sum_(cols=["Number"])], by=["X"])`                             |
| `AggVar`                      | [`agg.var`](/core/docs/reference/table-operations/group-and-aggregate/AggVar)      | `.agg_by([agg.var(cols=["Number"])], by=["X"])`                              |
| `avgBy`                       | [`avg_by`](/core/docs/reference/table-operations/group-and-aggregate/avgBy)        | `.avg_by()` , `.avg_by(by=["X"])`                                            |
| `countBy`                     | [`count_by`](/core/docs/reference/table-operations/group-and-aggregate/countBy)    | `.count_by("Count")`                                                         |
| `lastBy`                      | [`last_by`](/core/docs/reference/table-operations/group-and-aggregate/lastBy)      | `.last_by`                                                                   |
| `firstBy`                     | [`first_by`](/core/docs/reference/table-operations/group-and-aggregate/firstBy)    | `.first_by`                                                                  |
| `headBy`                      | [`head_by`](/core/docs/reference/table-operations/group-and-aggregate/headBy)      | `.head_by(2, by=["X"]`                                                       |
| `maxBy`                       | [`max_by`](/core/docs/reference/table-operations/group-and-aggregate/maxBy)        | `.max_by()`                                                                  |
| `medianBy`                    | [`median_by`](/core/docs/reference/table-operations/group-and-aggregate/medianBy)  | `.median_by()`                                                               |
| `minBy`                       | [`min_by`](/core/docs/reference/table-operations/group-and-aggregate/minBy)        | `.min_by()`                                                                  |
| `stdBy`                       | [`std_by`](/core/docs/reference/table-operations/group-and-aggregate/stdBy)        | `.std_by()`                                                                  |
| `sumBy`                       | [`sum_by`](/core/docs/reference/table-operations/group-and-aggregate/sumBy)        | `.sum_by()`                                                                  |
| `tailBy`                      | [`tail_by`](/core/docs/reference/table-operations/group-and-aggregate/tailBy)      | `.tail_by(2, by=["X"])`                                                      |
| `varBy`                       | [`var_by`](/core/docs/reference/table-operations/group-and-aggregate/varBy)        | `.var_by()`                                                                  |
| `by`                          | [`group_by`](/core/docs/reference/table-operations/group-and-aggregate/groupBy)    | `.group_by()`                                                                |

#### Filter

| Legacy       | Core+                                                                       | Syntax                                                    |
| ------------ | --------------------------------------------------------------------------- | --------------------------------------------------------- |
| `headPct`    | [`head_pct`](/core/docs/reference/table-operations/filter/head-pct)         | `.head_pct(pct=0.40)`                                     |
| `tailPct`    | [`tail_pct`](/core/docs/reference/table-operations/filter/tail-pct)         | `.tail_pct(pct=0.40)`                                     |
| `where`      | [`where`](/core/docs/reference/table-operations/filter/where)               | `.where(filters=["Number > 3"])`                          |
| `whereIn`    | [`where_in`](/core/docs/reference/table-operations/filter/where-in)         | `.where_in(filter_table=filter, cols=["X = Values"])`     |
| `whereNotIn` | [`where_not_in`](/core/docs/reference/table-operations/filter/where-not-in) | `.where_not_in(filter_table=filter, cols=["X = Values"])` |

#### Sort

| Legacy           | Core+                                                                           | Syntax                             |
| ---------------- | ------------------------------------------------------------------------------- | ---------------------------------- |
| `sortDescending` | [`sort_descending`](/core/docs/reference/table-operations/sort/sort-descending) | `.sort_descending(order_by=["X"])` |

#### Select

| Legacy          | Core+                                                                             | Syntax                                            |
| --------------- | --------------------------------------------------------------------------------- | ------------------------------------------------- |
| `dropColumns`   | [`drop_columns`](/core/docs/reference/table-operations/select/drop-columns)       | `.drop_columns(cols=["B", "D"])`                  |
| `moveColumns`   | [`move_columns`](/core/docs/reference/table-operations/select/move-columns)       | `.move_columns(idx=1, cols=["C"])`                |
| `moveUpColumns` | [`move_columns_up`](/core/docs/reference/table-operations/select/move-columns-up) | `.move_columns_up(cols=["B"])`                    |
| `renameColumns` | [`rename_columns`](/core/docs/reference/table-operations/select/rename-columns)   | `.rename_columns(cols=["Fruit = A", "Type = C"])` |
| `select`        | [`select`](/core/docs/reference/table-operations/select/select)                   | `.select(formulas=["B"])`                         |
| `updateView`    | [`update_view`](/core/docs/reference/table-operations/select/update-view)         | `.update_view(formulas=["X = B", "Y = sqrt(C)"])` |
| `update`        | [`update`](/core/docs/reference/table-operations/select/update)                   | `.update(formulas=["A", "X = B", "Y = sqrt(C)"])` |
| `view`          | [`view`](/core/docs/reference/table-operations/select/view)                       | `.view(formulas=["B"])`                           |

#### Join

| Legacy        | Core+                                                                           | Syntax                                                   |
| ------------- | ------------------------------------------------------------------------------- | -------------------------------------------------------- |
| `exactJoin`   | [`exact_join`](/core/docs/reference/table-operations/join/exact-join)           | `left.exact_join(table=right, on=["X"])`                 |
| `leftJoin`    | [`left_outer_join`](/core/docs/reference/table-operations/join/left-outer-join) | `left_outer_join(l_table=left, r_table=right, on=["I"])` |
| `naturalJoin` | [`natural_join`](/core/docs/reference/table-operations/join/natural-join)       | `left.natural_join(table=right, on=["DeptID"])`          |
| `merge`       | [`merge`](/core/docs/reference/table-operations/merge/merge)                    | `merge([source1, source2])`                              |

#### Format

| Legacy              | Core+                                                                                     | Syntax                                                                            |
| ------------------- | ----------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------- |
| `formatColumnWhere` | [`format_column_where`](/core/docs/reference/table-operations/format/format-column-where) | `.format_column_where(col="X", cond="X > 2", formula="RED")`                      |
| `formatColumns`     | [`format_columns`](/core/docs/reference/table-operations/format/format-columns)           | ``.format_columns(["A = B > 2 ? BLUE : NO_FORMATTING", "C = Decimal(`0.00%`)"])`` |
| `formatRowWhere`    | [`format_row_where`](/core/docs/reference/table-operations/format/format-row-where)       | `.format_row_where(cond="X > 2 && X < 4", formula="RED")`                         |

#### Metadata

| Legacy      | Core+                                                                      | Syntax        |
| ----------- | -------------------------------------------------------------------------- | ------------- |
| `getMeta()` | [`meta_table`](/core/docs/reference/table-operations/metadata/meta_table)  | `.meta_table` |
| `size()`    | [`size`](/core/pydoc/code/deephaven.table.html#deephaven.table.Table.size) | `size`        |

#### Plot

| Legacy        | Core+                                                                                                   | Syntax                                                                                                           |
| ------------- | ------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------- |
| `catHistPlot` | [`plot_cat_hist`](/core/docs/reference/plot/catHistPlot)                                                | `.plot_cat_hist(series_name="Keys count", t=source, category="Keys")`                                            |
| `catPlot`     | [`plot_cat`](/core/docs/reference/plot/catPlot)                                                         | `plot_cat(series_name="Cagetories Plot", t=source, category="Categories", y="Values")`                           |
| `chartTitle`  | [`chart_title`](/core/pydoc/code/deephaven.plot.figure.html#deephaven.plot.figure.Figure.chart_title)   | `chart_title(title="Name")`                                                                                      |
| `figureTitle` | [`figure_title`](/core/pydoc/code/deephaven.plot.figure.html#deephaven.plot.figure.Figure.figure_title) | `figure_title(title="Name")`                                                                                     |
| `histPlot`    | [`plot_xy_hist`](/core/docs/reference/plot/histPlot)                                                    | `plot_xy_hist(series_name="Histogram Values", t=source, x="Values", nbins=N)`                                    |
| `lineStyle`   | [`LineEndStyle`](/core/pydoc/code/deephaven.plot.linestyle.html#deephaven.plot.linestyle.LineEndStyle)  | `LineEndStyle(ROUND)`                                                                                            |
| `newChart`    | [`new_chart`](/core/pydoc/code/deephaven.plot.figure.html#deephaven.plot.figure.Figure.new_chart)       | `new_chart(index=int, row=int, col=int)`                                                                         |
| `ohlcPlot`    | [`plot_ohlc`](/core/docs/reference/plot/ohlcPlot)                                                       | `.plot_ohlc(series_name="Name", t=source, x="TimestampBin", open="Open", high="High", low="Low", close="Close")` |
| `piePlot`     | [`plot_pie`](/core/docs/reference/plot/piePlot)                                                         | `.plot_pie(series_name="Name",t=source,category="category",y="y-values")`                                        |
| `twinX`       | [`x_twin`](/core/pydoc/code/deephaven.plot.figure.html#deephaven.plot.figure.Figure.x_twin)             | `x_twin(name="string")`                                                                                          |

#### Time

| Legacy            | Core+                                                             | Syntax                                                                                            |
| ----------------- | ----------------------------------------------------------------- | ------------------------------------------------------------------------------------------------- |
| `convertDateTime` | [`to_j_instant`](/core/docs/reference/time/datetime/to_j_instant) | `to_j_instant("2022-01-01T00:00:00 ET")` Note: requires `from deephaven.time import to_j_instant` |

## Miscellaneous

| Legacy                                                     | Core+                                                          |
| ---------------------------------------------------------- | -------------------------------------------------------------- |
| `com.fishlib.base.verify.Assert`                           | `io.deephaven.base.verify.Assert`                              |
| `nullToValue`                                              | `replaceIfNull`                                                |
| `com.illumon.iris.db.tables.databases.Database#reloadData` | `io.deephaven.enterprise.database.Database#clearLocationCache` |
