Substrait consumer doesn't recognise `shift_left` / `shift_right` from functions_arithmetic.yaml

Ouverte Adaptée aux débutants
#27,059 0 commentaires 0 réactions 0 personnes assignées Voir sur GitHub

Les mainteneurs répondent en général sous 1 jour

Personne n'a encore pris cette issue.

Évaluation

Difficulté
2/5
Temps estimé
1-3 heures
Accessibilité débutants
76/100
Type d'issue
Bug
Clarté
Clairement spécifiée
Activité
Active
Stack technique
rust
Domaine
backend

Piste de recherche

Commencez par datafusion/substrait/src/logical_plan/consumer/expr/scalar_function.rs, où l’issue indique que le consumer ne fait actuellement correspondre que les noms bitwise_ ; vérifiez les correspondances et les tests à proximité. Vérifiez que les appels standard à shift_left et shift_right correspondent aux opérateurs de décalage de DataFusion, et vérifiez également la nomenclature du producer. L’objectif est atteint lorsque les noms standard fonctionnent dans le plan reproduit et que shift_right_unsigned signale explicitement une erreur indiquant que cette fonctionnalité n’est pas prise en charge.

Rédigé par le modèle d'indexation à partir du texte de l'issue.

Description

bug
Describe the bug

I found this inconsistency while checking DataFusion against a formalization of Substrait plan semantics, when plans that call Substrait's standard shift functions were rejected by from_substrait_plan.

Substrait's functions_arithmetic.yaml defines shift_left, shift_right and shift_right_unsigned (added in Substrait v0.74.0, substrait-io/substrait#799). DataFusion's consumer maps the names bitwise_shift_left and bitwise_shift_right to its shift operators, and rejects a plan that calls the standard names with Unsupported function name: "shift_left". The producer writes the same non-standard names, so a DataFusion plan with a << 1 calls bitwise_shift_left, which other consumers won't find in the extension. The current names may simply predate the standard functions.

To Reproduce

DataFusion 55.0.0 (Python bindings, datafusion==55.0.0, built on DataFusion 55.1.0); the same on 51.0.0. The consumer's mapping on main still lists only the bitwise_ names (datafusion/substrait/src/logical_plan/consumer/expr/scalar_function.rs).

# uv run --no-project --with datafusion==55.0.0 --with "substrait>=0.37" python DF-10.py
import json
import datafusion
from datafusion import SessionContext
from datafusion.substrait import Consumer, Producer, Serde
from google.protobuf import json_format
from substrait.plan_pb2 import Plan

print("datafusion", datafusion.__version__)
ctx = SessionContext()

# SELECT shift_left(a, 1), shift_right(a, 1) FROM (VALUES (CAST(5 AS INT))) t(a),
# written with the functions of Substrait's functions_arithmetic.yaml.
urn = "extension:io.substrait:functions_arithmetic"
def call(anchor):
    return {"scalarFunction": {"functionReference": anchor,
        "outputType": {"i32": {"nullability": "NULLABILITY_REQUIRED"}},
        "arguments": [
            {"value": {"selection": {"directReference": {"structField": {"field": 0}}, "rootReference": {}}}},
            {"value": {"literal": {"i32": 1}}}]}}
plan = {
  "extensionUrns": [{"extensionUrnAnchor": 1, "urn": urn}],
  "extensions": [
    {"extensionFunction": {"extensionUrnReference": 1, "functionAnchor": 1, "name": "shift_left:i32_i32"}},
    {"extensionFunction": {"extensionUrnReference": 1, "functionAnchor": 2, "name": "shift_right:i32_i32"}}],
  "relations": [{"root": {"names": ["l", "r"], "input": {"project": {
    "common": {"emit": {"outputMapping": [1, 2]}},
    "input": {"read": {
      "baseSchema": {"names": ["a"], "struct": {"types": [{"i32": {"nullability": "NULLABILITY_REQUIRED"}}], "nullability": "NULLABILITY_REQUIRED"}},
      "virtualTable": {"expressions": [{"fields": [{"literal": {"i32": 5}}]}]}}},
    "expressions": [call(1), call(2)]}}}}]}
msg = json_format.ParseDict(plan, Plan())
try:
    lp = Consumer.from_substrait_plan(ctx, Serde.deserialize_bytes(msg.SerializeToString()))
    print(ctx.create_dataframe_from_logical_plan(lp).to_pydict())
except Exception as e:
    print("consumer error:", e)

# The producer, for its part, names these functions bitwise_shift_left / bitwise_shift_right.
ctx.sql("CREATE TABLE t (a INT) AS VALUES (5)").collect()
p = Producer.to_substrait_plan(ctx.sql("SELECT a << 1 AS l, a >> 1 AS r FROM t").logical_plan(), ctx)
out = Plan(); out.ParseFromString(p.encode())
print("producer extensions:", [e.extension_function.name for e in out.extensions])

Output:

datafusion 55.0.0
consumer error: DataFusion error: This feature is not implemented: Unsupported function name: "shift_left"
producer extensions: ['bitwise_shift_left', 'bitwise_shift_right']

With the two names changed to bitwise_shift_left and bitwise_shift_right, the same plan runs and returns {'l': [10], 'r': [2]}, so only the name is in the way.

Expected behavior

The consumer accepts shift_left and shift_right and maps them to Operator::BitwiseShiftLeft and Operator::BitwiseShiftRight, so the plan above returns {'l': [10], 'r': [2]}. The producer could write the standard names too, as was done for is_nan, sign and others in #16949. shift_right_unsigned has no DataFusion operator, so an explicit "not supported" error would fit it.

Additional context
Willingness to contribute

I would like to contribute a fix for this bug, but request guidance from the DataFusion community

Langage dominant
Rust
Étoiles
9.6k
Forks
2.6k
Merge moyen
3 j 22 h
PR mergées (30 j)
331

Préparer son environnement

Ouvrir dans Codespaces

Lance le conteneur de développement du projet dans votre navigateur, avec votre propre compte GitHub.

Par où commencer

  1. Lisez l'issue en entier, puis le guide de contribution du projet.
  2. Signalez en commentaire que vous la prenez — cela évite que deux personnes fassent le même travail.
  3. Forkez le dépôt et travaillez sur une branche.
  4. Ouvrez une pull request qui référence le numéro de l'issue.

Autres issues de apache/datafusion

Toutes les issues de apache/datafusion

Issues similaires

Plus d'issues Rust

Recevez les nouvelles issues par e-mail

Un résumé court des issues GitHub adaptées aux débutants.