Substrait consumer doesn't recognise `shift_left` / `shift_right` from functions_arithmetic.yaml
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
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
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
- The definitions: https://github.com/substrait-io/substrait/blob/main/extensions/functions_arithmetic.yaml (
shift_left,shift_right,shift_right_unsigned). - #16949 / #16950 added other missing Substrait-to-DataFusion name mappings in the same table.
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
Lance le conteneur de développement du projet dans votre navigateur, avec votre propre compte GitHub.
- Aucun Dockerfile ni fichier Docker Compose
- Propose un modèle de pull request
- Lire le guide de contribution
Par où commencer
- Lisez l'issue en entier, puis le guide de contribution du projet.
- Signalez en commentaire que vous la prenez — cela évite que deux personnes fassent le même travail.
- Forkez le dépôt et travaillez sur une branche.
- Ouvrez une pull request qui référence le numéro de l'issue.
Autres issues de apache/datafusion
-
`ProjectionExprs::project_statistics` computes approximate `Statistics::total_byte_size` ignoring column statsPeut-être pris @joseph-isaacs l’a pris aujourd’hui. Ouvertebug
Difficulté 2/5 1-3 heures Accessibilité débutants 72/100
apache/datafusion#27050 ·
Les mainteneurs répondent en général sous 1 jour
-
Difficulté 2/5 1-3 heures Accessibilité débutants 75/100
apache/datafusion#26999 · 1 commentaire ·
Les mainteneurs répondent en général sous 1 jour
-
Difficulté 1/5 Moins d'une heure Accessibilité débutants 85/100
apache/datafusion#26998 ·
Les mainteneurs répondent en général sous 1 jour
-
`repeat` on `LargeUtf8` aborts the process on a result size no allocation can satisfyPeut-être pris @huong8373tt-beep l’a pris il y a 1 jour. Ouvertebug good first issue
Difficulté 2/5 1-3 heures Accessibilité débutants 72/100
apache/datafusion#26948 · 1 commentaire · 1 personne assignée ·
Les mainteneurs répondent en général sous 1 jour
-
[Bug] atan2 does not normalize -0.0 the way Spark doesPeut-être pris @galaxytemple l’a pris il y a 3 jours. Ouvertebug spark
Difficulté 2/5 1-3 heures Accessibilité débutants 72/100
apache/datafusion#26333 ·
Les mainteneurs répondent en général sous 1 jour
Toutes les issues de apache/datafusion
Issues similaires
-
A-linter
Difficulté 2/5 1-3 heures Accessibilité débutants 73/100
oxc-project/oxc#28783 ·
Les mainteneurs répondent en général sous 1 jour
-
Bump calamine to 0.38: RUSTSEC-2026-0436 (CFB/OLE2 panic and unbounded allocation) fails cargo auditOuverte
Difficulté 2/5 1-3 heures Accessibilité débutants 70/100
docling-project/docling.rs#979 ·
Les mainteneurs répondent en général sous 1 jour
-
llm translation
Difficulté 2/5 1-3 heures Accessibilité débutants 72/100
Les mainteneurs répondent en général sous 1 jour
-
Difficulté 2/5 1-3 heures Accessibilité débutants 74/100
Les mainteneurs répondent en général sous 1 jour
-
Difficulté 2/5 1-3 heures Accessibilité débutants 72/100