datafusion_functions/core/
file_row_index.rs1use arrow::datatypes::DataType;
21use datafusion_common::utils::take_function_args;
22use datafusion_common::{Result, exec_err};
23use datafusion_doc::Documentation;
24use datafusion_expr::{
25 ColumnarValue, ExpressionPlacement, ScalarFunctionArgs, ScalarUDFImpl, Signature,
26 Volatility,
27};
28use datafusion_macros::user_doc;
29
30#[user_doc(
36 doc_section(label = "Other Functions"),
37 description = r#"Returns the zero-based row offset within the source file
38that produced the current row.
39
40The value is scoped to one file, so rows from different files in the same scan
41can have the same row index. This function is intended to be rewritten at
42file-scan time. If the input file is not known (for example, if this function
43is evaluated outside a file scan, or was not pushed down into one), direct
44evaluation returns an error.
45"#,
46 syntax_example = "file_row_index()",
47 sql_example = r#"```sql
48SELECT file_row_index() FROM t;
49```"#
50)]
51#[derive(Debug, PartialEq, Eq, Hash)]
52pub struct FileRowIndexFunc {
53 signature: Signature,
54}
55
56impl Default for FileRowIndexFunc {
57 fn default() -> Self {
58 Self::new()
59 }
60}
61
62impl FileRowIndexFunc {
63 pub fn new() -> Self {
64 Self {
65 signature: Signature::nullary(Volatility::Volatile),
66 }
67 }
68}
69
70impl ScalarUDFImpl for FileRowIndexFunc {
71 fn name(&self) -> &str {
72 "file_row_index"
73 }
74
75 fn signature(&self) -> &Signature {
76 &self.signature
77 }
78
79 fn return_type(&self, args: &[DataType]) -> Result<DataType> {
80 let [] = take_function_args(self.name(), args)?;
81 Ok(DataType::Int64)
82 }
83
84 fn invoke_with_args(&self, args: ScalarFunctionArgs) -> Result<ColumnarValue> {
85 let [] = take_function_args(self.name(), args.args)?;
86 exec_err!("file_row_index() is source dependent and cannot be evaluated directly")
87 }
88
89 fn placement(&self, _args: &[ExpressionPlacement]) -> ExpressionPlacement {
90 ExpressionPlacement::MoveTowardsLeafNodes
91 }
92
93 fn documentation(&self) -> Option<&Documentation> {
94 self.doc()
95 }
96}