Skip to content

feat: Add subfields pushdown for cardinality function#26834

Merged
kevintang2022 merged 1 commit intoprestodb:masterfrom
maniloya:export-D88739396
Jan 29, 2026
Merged

feat: Add subfields pushdown for cardinality function#26834
kevintang2022 merged 1 commit intoprestodb:masterfrom
maniloya:export-D88739396

Conversation

@maniloya
Copy link
Copy Markdown
Contributor

@maniloya maniloya commented Dec 19, 2025

Description

This PR adds subfield pushdown optimization for the cardinality() function in Presto. When enabled, this optimization allows the query engine to skip reading map keys/values or array elements when only the cardinality (count) of these collections is needed.

This PR contains coordinator-side changes only; the corresponding worker-side changes will be added separately to the C++ worker. Since this feature is not yet fully tested end-to-end with the worker, the session property is disabled by default.

Additionally, this implementation takes a conservative approach to subfield pushdown for cardinality: if a column already has other subfields being accessed (e.g., features['key']), we skip adding the structure-only subfield for cardinality to avoid potential correctness issues.

Key Changes:

  1. New StructureOnly PathElement (Subfield.java): Introduced a new path element type represented as [$] that indicates only the structural metadata (size/count) is needed, not the actual content
  2. SubfieldTokenizer Update: Added parsing support for the $ subscript pattern in subfield paths
  3. FunctionResolution: Added isCardinalityFunction() method to identify cardinality function calls
  4. PushdownSubfields Optimizer: Extended the subfield extraction logic to recognize cardinality() calls on maps and arrays, generating [$] subfield hints that downstream readers can use to skip content
  5. Session/Config Properties: Added pushdown_subfields_for_cardinality configuration option (disabled by default)

Motivation and Context

When queries only need to know the size of a map or array (e.g., `SELECT cardinality(features) FROM table or WHERE cardinality(tags) > 10), there's no need to read all the keys/values or both. This optimization helps reduce shuffles improve the query performance.

Impact

  • Performance: Reduces I/O and deserialization overhead for queries using cardinality() on maps/arrays
  • Backward Compatible: Feature is disabled by default via optimizer.pushdown-subfield-for-cardinality config
  • No Breaking Changes: Existing behavior is preserved when the feature is disabled
  • Added a new session property pushdown-subfield-for-cardinality

Test Plan

Added comprehensive unit tests in TestHiveLogicalPlanner.java covering:

  • Simple cardinality pushdown for MAP - Verifies cardinality(x) generates x[$] subfield
  • Cardinality pushdown for ARRAY - Verifies array cardinality generates correct subfield
  • Cardinality in WHERE clause - Tests WHERE cardinality(features) > 10
  • Cardinality in aggregation - Tests AVG(cardinality(data))
  • Multiple cardinalities - Tests multiple cardinality calls in same query
  • Cardinality with complex expressions - Tests cardinality(tags) * 2
  • Cardinality on nested structures - Tests transform(arr_of_maps, m -> cardinality(m))
  • Cardinality combined with subscript access - Verifies that when both cardinality(features) and features['key'] are used, the specific subscript takes precedence (avoiding redundant structure-only reads)

Contributor checklist

  • Please make sure your submission complies with our contributing guide, in particular code style and commit standards.
  • PR description addresses the issue accurately and concisely. If the change is non-trivial, a GitHub Issue is referenced.
  • Documented new properties (with its default value), SQL syntax, functions, or other functionality.
  • If release notes are required, they follow the release notes guidelines.
  • Adequate tests were added if applicable.
  • CI passed.
  • If adding new dependencies, verified they have an OpenSSF Scorecard score of 5.0 or higher (or obtained explicit TSC approval for lower scores).

Release Notes

== NO RELEASE NOTE ==

@sourcery-ai
Copy link
Copy Markdown
Contributor

sourcery-ai bot commented Dec 19, 2025

Reviewer's Guide

Implements subfield pushdown support for the cardinality() function by introducing a new StructureOnly subfield path element, a configurable optimizer/session property, and planner logic to extract and de-duplicate these subfields, with corresponding tokenizer and configuration tests plus planner tests for MAP/ARRAY usages.

Sequence diagram for cardinality() subfield pushdown during planning

sequenceDiagram
    actor User
    participant Session
    participant SystemSessionProperties
    participant FeaturesConfig
    participant Planner as PushdownSubfields
    participant Extractor as SubfieldExtractor
    participant FR as FunctionResolution
    participant TS as TableScanNode

    User->>Session: submit query with cardinality(map_col)

    Note over Session,FeaturesConfig: Session created with FeaturesConfig

    Session->>SystemSessionProperties: get PUSHDOWN_SUBFIELDS_FOR_CARDINALITY
    SystemSessionProperties-->>Session: isPushSubfieldsForCardinalityEnabled = true

    Session->>Planner: plan(query)

    Planner->>Extractor: new SubfieldExtractor(FunctionResolution, ExpressionOptimizer, ConnectorSession, FunctionAndTypeManager, Session)
    Extractor->>SystemSessionProperties: isPushSubfieldsForCardinalityEnabled(Session)
    SystemSessionProperties-->>Extractor: true

    Planner->>Extractor: visitCall(cardinality(map_col), Context)
    Extractor->>FR: isCardinalityFunction(call.functionHandle)
    FR-->>Extractor: true
    Extractor->>Extractor: check single argument and type MapType or ArrayType
    Extractor->>Context: add Subfield(map_col, [StructureOnly])

    Planner->>TS: collect required Subfields from Context

    Planner->>Planner: removeRedundantStructureOnlySubfields(columnSubfields)
    Planner-->>TS: set requiredSubfields without redundant StructureOnly

    TS-->>User: execute scan reading only structure for map_col
Loading

Class diagram for Subfield, StructureOnly, and SubfieldTokenizer changes

classDiagram
    class Subfield {
        -String rootName
        -List~PathElement~ path
        +Subfield(String path)
        +Subfield(String rootName, List~PathElement~ path)
        +String getRootName()
        +List~PathElement~ getPath()
        +String toString()
        +static PathElement noSubfield()
        +static PathElement wildcard()
        +static PathElement allSubscripts()
        +static PathElement structureOnly()
    }

    class PathElement {
        <<interface>>
        +boolean isSubscript()
    }

    class StructureOnly {
        -static StructureOnly STRUCTURE_ONLY
        -StructureOnly()
        +static StructureOnly getInstance()
        +boolean isSubscript()
        +String toString()
    }

    class NestedField {
        +NestedField(String name)
        +String getName()
        +boolean isSubscript()
        +String toString()
    }

    class Subscript {
        +Subscript(long index)
        +long getIndex()
        +boolean isSubscript()
        +String toString()
    }

    class AllSubscripts {
        +static AllSubscripts getInstance()
        +boolean isSubscript()
        +String toString()
    }

    class Wildcard {
        +static Wildcard getInstance()
        +boolean isSubscript()
        +String toString()
    }

    class NoSubfield {
        +static NoSubfield getInstance()
        +boolean isSubscript()
        +String toString()
    }

    class SubfieldTokenizer {
        -String path
        -int index
        +SubfieldTokenizer(String path)
        +boolean hasNext()
        +Subfield.PathElement next()
        -Subfield.PathElement computeNext()
        -Subfield.PathElement matchQuotedSubscript()
        -Subfield.PathElement matchWildcardSubscript()
        -Subfield.PathElement matchUnquotedSubscript()
        -Subfield.PathElement matchDollarPathElement()
        -Subfield.PathElement matchStructureOnlySubscript()
    }

    Subfield o-- PathElement
    StructureOnly ..|> PathElement
    NestedField ..|> PathElement
    Subscript ..|> PathElement
    AllSubscripts ..|> PathElement
    Wildcard ..|> PathElement
    NoSubfield ..|> PathElement

    SubfieldTokenizer --> PathElement
    SubfieldTokenizer ..> StructureOnly : creates
    Subfield ..> StructureOnly : structureOnly()
Loading

Class diagram for planner/cardinality subfield pushdown configuration

classDiagram
    class PushdownSubfields {
        +PlanNode visitTableScan(TableScanNode node, RewriteContext~Context~ context)
        -static List~Subfield~ removeRedundantStructureOnlySubfields(List~Subfield~ subfields)
    }

    class SubfieldExtractor {
        -FunctionResolution functionResolution
        -ExpressionOptimizer expressionOptimizer
        -ConnectorSession connectorSession
        -FunctionAndTypeManager functionAndTypeManager
        -boolean isPushDownSubfieldsFromLambdasEnabled
        -boolean isPushdownSubfieldsForMapFunctionsEnabled
        -boolean isPushdownSubfieldsForCardinalityEnabled
        +SubfieldExtractor(FunctionResolution functionResolution, ExpressionOptimizer expressionOptimizer, ConnectorSession connectorSession, FunctionAndTypeManager functionAndTypeManager, Session session)
        +Void visitCall(CallExpression call, Context context)
    }

    class FunctionResolution {
        +boolean isMapFilterFunction(FunctionHandle functionHandle)
        +boolean isCardinalityFunction(FunctionHandle functionHandle)
        +FunctionHandle lookupBuiltInFunction(String functionName, List~Type~ inputTypes)
    }

    class FeaturesConfig {
        -boolean pushdownSubfieldForMapFunctions
        -boolean pushdownSubfieldForCardinality
        +boolean isPushdownSubfieldForMapFunctions()
        +FeaturesConfig setPushdownSubfieldForMapFunctions(boolean value)
        +boolean isPushdownSubfieldForCardinality()
        +FeaturesConfig setPushdownSubfieldForCardinality(boolean value)
    }

    class SystemSessionProperties {
        +static String PUSHDOWN_SUBFIELDS_FOR_MAP_FUNCTIONS
        +static String PUSHDOWN_SUBFIELDS_FOR_CARDINALITY
        +SystemSessionProperties(FeaturesConfig featuresConfig, boolean experimentalSyntaxEnabled, boolean distributedIndexJoinsEnabled, boolean optimizedHashGenerationEnabled)
        +static boolean isPushSubfieldsForMapFunctionsEnabled(Session session)
        +static boolean isPushSubfieldsForCardinalityEnabled(Session session)
    }

    class Session {
        +T getSystemProperty(String name, Class~T~ type)
    }

    class CallExpression {
        +FunctionHandle getFunctionHandle()
        +List~RowExpression~ getArguments()
    }

    class Context {
        +List~Subfield~ subfields
    }

    class VariableReferenceExpression {
        +String getName()
        +Type getType()
    }

    class MapType {
    }

    class ArrayType {
    }

    class Subfield {
        +Subfield(String rootName, List~PathElement~ path)
    }

    PushdownSubfields ..> Subfield : uses
    PushdownSubfields ..> Session : uses
    PushdownSubfields ..> SubfieldExtractor : creates

    SubfieldExtractor ..> FunctionResolution : uses
    SubfieldExtractor ..> ExpressionOptimizer : uses
    SubfieldExtractor ..> ConnectorSession : uses
    SubfieldExtractor ..> FunctionAndTypeManager : uses
    SubfieldExtractor ..> Session : reads properties
    SubfieldExtractor ..> SystemSessionProperties : calls isPushSubfieldsForCardinalityEnabled
    SubfieldExtractor ..> Subfield : creates
    SubfieldExtractor ..> VariableReferenceExpression : casts
    SubfieldExtractor ..> MapType : type check
    SubfieldExtractor ..> ArrayType : type check
    SubfieldExtractor ..> CallExpression : visitCall
    SubfieldExtractor ..> Context : adds subfields

    FunctionResolution ..> FunctionHandle

    SystemSessionProperties ..> FeaturesConfig : constructed from
    SystemSessionProperties ..> Session : reads system properties

    FeaturesConfig ..> SystemSessionProperties : configures defaults
Loading

File-Level Changes

Change Details Files
Add optimizer support to push down subfields for cardinality() calls on MAP and ARRAY columns, gated by a new session property.
  • Extend SubfieldExtractor with a new flag initialized from a session/system property controlling cardinality subfield pushdown.
  • Detect cardinality() calls with a single MAP or ARRAY VariableReferenceExpression argument and record a corresponding StructureOnly subfield for that variable.
  • Integrate detection with existing subfield extraction flow so cardinality-based subfields participate in table scan pruning.
presto-main-base/src/main/java/com/facebook/presto/sql/planner/optimizations/PushdownSubfields.java
presto-main-base/src/main/java/com/facebook/presto/sql/relational/FunctionResolution.java
presto-main-base/src/main/java/com/facebook/presto/SystemSessionProperties.java
Introduce a StructureOnly subfield path element and tokenizer support to represent structure-only access ([$]) used by cardinality pushdown.
  • Add Subfield.StructureOnly PathElement implementation with singleton accessor and string representation "[$]".
  • Expose a Subfield.structureOnly() factory method alongside existing helpers.
  • Extend SubfieldTokenizer to parse "[$]" inside brackets as a StructureOnly subscript and route it through a new matchStructureOnlySubscript() helper.
presto-common/src/main/java/com/facebook/presto/common/Subfield.java
presto-common/src/main/java/com/facebook/presto/common/SubfieldTokenizer.java
Prevent correctness issues by removing redundant StructureOnly subfields when more specific subfields exist for the same column.
  • Add removeRedundantStructureOnlySubfields helper that identifies columns having any non-StructureOnly paths.
  • Filter out StructureOnly subfields for those columns before attaching requiredSubfields to table scan assignments.
  • Document in code that keeping both StructureOnly and specific subfields for a column can cause correctness problems.
presto-main-base/src/main/java/com/facebook/presto/sql/planner/optimizations/PushdownSubfields.java
Add configuration and session wiring for the new cardinality subfield pushdown feature, including defaults and config tests.
  • Add pushdownSubfieldForCardinality boolean field to FeaturesConfig with @config wiring and getter/setter.
  • Expose PUSHDOWN_SUBFIELDS_FOR_CARDINALITY system property and a helper isPushSubfieldsForCardinalityEnabled(Session).
  • Update TestFeaturesConfig defaults and explicit property mappings to cover the new config option.
presto-main-base/src/main/java/com/facebook/presto/sql/analyzer/FeaturesConfig.java
presto-main-base/src/main/java/com/facebook/presto/SystemSessionProperties.java
presto-main-base/src/test/java/com/facebook/presto/sql/analyzer/TestFeaturesConfig.java
Add planner tests verifying cardinality subfield pushdown behavior across various query patterns and nested structures.
  • Introduce testPushdownSubfieldsForCardinality covering SELECT, WHERE, aggregation, multiple cardinality calls, and expressions using cardinality().
  • Add tests for ARRAY, MAP, and ARRAY-of-MAP columns with appropriate expected subfield patterns, including structure-only markers like "x[$]" and "arr_of_maps[*][$]".
  • Add tests combining cardinality() predicates with map subscripts to ensure only specific subscripts are pushed down when needed.
presto-hive/src/test/java/com/facebook/presto/hive/TestHiveLogicalPlanner.java

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@maniloya maniloya changed the title feat: Add subfields pushdown for cardinality function WIP: Add subfields pushdown for cardinality function Dec 19, 2025
Copy link
Copy Markdown
Contributor

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - I've found 2 issues, and left some high level feedback:

  • The new testPushdownSubfieldsForCardinality method contains several very similar cases (e.g., the *_where_limit and *_with_subscript tables/queries are effectively duplicates); consider consolidating or parameterizing these to keep the test concise and focused on distinct behaviors.
  • In Subfield.StructureOnly, overriding isSubscript() to return true is a bit non-obvious; adding a brief comment or renaming the class to indicate that this is modeled as a special kind of subscript (e.g., “structure-only subscript”) would make its role clearer to future maintainers.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- The new `testPushdownSubfieldsForCardinality` method contains several very similar cases (e.g., the `*_where_limit` and `*_with_subscript` tables/queries are effectively duplicates); consider consolidating or parameterizing these to keep the test concise and focused on distinct behaviors.
- In `Subfield.StructureOnly`, overriding `isSubscript()` to return `true` is a bit non-obvious; adding a brief comment or renaming the class to indicate that this is modeled as a special kind of subscript (e.g., “structure-only subscript”) would make its role clearer to future maintainers.

## Individual Comments

### Comment 1
<location> `presto-hive/src/test/java/com/facebook/presto/hive/TestHiveLogicalPlanner.java:1642` </location>
<code_context>
     }

+    @Test
+    public void testPushdownSubfieldsForCardinality()
+    {
+        Session cardinalityPushdown = Session.builder(getSession())
</code_context>

<issue_to_address>
**suggestion (testing):** Add a test case with pushdown-subfields-for-cardinality disabled to prove no subfields are pushed in that mode

Since this test only covers the enabled case, please also add coverage for the disabled case by using a session with `PUSHDOWN_SUBFIELDS_FOR_CARDINALITY = false` and asserting that no `[$]` subfields are pushed for the same queries. This will verify that the session property correctly gates the optimization and guard against regressions where cardinality pushdown is applied unconditionally.

Suggested implementation:

```java
import static com.facebook.presto.SystemSessionProperties.PUSHDOWN_SUBFIELDS_FOR_CARDINALITY;
import static com.facebook.presto.SystemSessionProperties.PUSHDOWN_SUBFIELDS_FOR_MAP_FUNCTIONS;

```

To implement the request fully, add a new test method that mirrors `testPushdownSubfieldsForCardinality` but with `PUSHDOWN_SUBFIELDS_FOR_CARDINALITY` set to `"false"` and with assertions that no `[$]` subfields are pushed.

Place this new method next to the existing `testPushdownSubfieldsForCardinality` method in `TestHiveLogicalPlanner`:

```java
    @Test
    public void testPushdownSubfieldsForCardinalityDisabled()
    {
        Session noCardinalityPushdown = Session.builder(getSession())
                .setSystemProperty(PUSHDOWN_SUBFIELDS_FOR_CARDINALITY, "false")
                .build();

        // Verify that MAP cardinality does not push down subfields when disabled
        assertUpdate("CREATE TABLE test_pushdown_cardinality_map(id integer, x map(integer, double))");
        assertPushdownSubfields(
                noCardinalityPushdown,
                "SELECT t.id, cardinality(x) FROM test_pushdown_cardinality_map t",
                "test_pushdown_cardinality_map",
                ImmutableMap.of());
        assertUpdate("DROP TABLE test_pushdown_cardinality_map");

        // Verify that ARRAY cardinality does not push down subfields when disabled
        assertUpdate("CREATE TABLE test_pushdown_cardinality_array(id integer, x array(double))");
        assertPushdownSubfields(
                noCardinalityPushdown,
                "SELECT t.id, cardinality(x) FROM test_pushdown_cardinality_array t",
                "test_pushdown_cardinality_array",
                ImmutableMap.of());
        assertUpdate("DROP TABLE test_pushdown_cardinality_array");
    }
```

Notes / assumptions you may need to adjust to your codebase:

1. This assumes that `assertPushdownSubfields(Session, String, String, Map<String, Subfield>)` already treats `ImmutableMap.of()` as “no subfields pushed”. If your helper uses a different convention (e.g., `null` or a dedicated `assertNoSubfieldsPushed(...)`), adapt the assertions accordingly.
2. The table names and query shapes are intentionally identical to those in `testPushdownSubfieldsForCardinality`, so the only difference between the tests is the session property value and the expected subfields map.
3. Ensure the new test is inside the `TestHiveLogicalPlanner` class body and near the existing `testPushdownSubfieldsForCardinality` so future maintainers can easily see the enabled/disabled pair.
</issue_to_address>

### Comment 2
<location> `presto-hive/src/test/java/com/facebook/presto/hive/TestHiveLogicalPlanner.java:1690-1699` </location>
<code_context>
+        assertUpdate("CREATE TABLE test_pushdown_cardinality_where_limit(id integer, features map(varchar, double))");
</code_context>

<issue_to_address>
**issue (testing):** Drop the last three test tables to avoid state leakage between tests

The earlier cases create a table, assert behavior, and then immediately `DROP` it. These three tests create tables but never drop them, which risks state leakage and order-dependent failures. Please add matching `DROP TABLE` statements for each of these tables for consistency and isolation.
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment on lines +1690 to +1699
assertUpdate("CREATE TABLE test_pushdown_cardinality_where_limit(id integer, features map(varchar, double))");
assertPushdownSubfields(cardinalityPushdown, "SELECT t.id FROM test_pushdown_cardinality_where_limit t WHERE cardinality(features) > 10 and features['0'] > 0.0", "test_pushdown_cardinality_where_limit",
ImmutableMap.of("features", toSubfields("features[\"0\"]")));

assertUpdate("CREATE TABLE test_pushdown_cardinality_with_subscript(id integer, features map(varchar, double))");
assertPushdownSubfields(cardinalityPushdown, "SELECT t.id FROM test_pushdown_cardinality_with_subscript t WHERE cardinality(features) > 10 AND features['0'] > 0.0", "test_pushdown_cardinality_with_subscript",
ImmutableMap.of("features", toSubfields("features[\"0\"]")));

assertUpdate("CREATE TABLE test_pushdown_cardinality_multi_subscript(id integer, features map(varchar, double))");
assertPushdownSubfields(cardinalityPushdown, "SELECT t.id FROM test_pushdown_cardinality_multi_subscript t WHERE cardinality(features) > 5 AND features['a'] > 1.0 AND features['b'] < 2.0", "test_pushdown_cardinality_multi_subscript",
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue (testing): Drop the last three test tables to avoid state leakage between tests

The earlier cases create a table, assert behavior, and then immediately DROP it. These three tests create tables but never drop them, which risks state leakage and order-dependent failures. Please add matching DROP TABLE statements for each of these tables for consistency and isolation.

@maniloya maniloya changed the title WIP: Add subfields pushdown for cardinality function feat: Add subfields pushdown for cardinality function Dec 20, 2025
feilong-liu
feilong-liu previously approved these changes Dec 20, 2025
@steveburnett
Copy link
Copy Markdown
Contributor

Please add documentation for the new session property pushdown-subfield-for-cardinality to https://github.com/prestodb/presto/blob/master/presto-docs/src/main/sphinx/admin/properties-session.rst.

maniloya added a commit to maniloya/presto that referenced this pull request Jan 22, 2026
Summary: Pull Request resolved: prestodb#26834

Reviewed By: feilong-liu

Differential Revision: D88739396
Summary: Pull Request resolved: prestodb#26834

Reviewed By: feilong-liu

Differential Revision: D88739396
Copy link
Copy Markdown
Contributor

@steveburnett steveburnett left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM! (docs)

Pull branch, local doc build, looks good. Thanks!

@maniloya maniloya requested a review from feilong-liu January 28, 2026 17:39
@kevintang2022 kevintang2022 merged commit ed0c4df into prestodb:master Jan 29, 2026
112 of 113 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants