From 08940f17cde78328f557d5aab8f1761855002c5e Mon Sep 17 00:00:00 2001
From: Yongting You <2010youy01@gmail.com>
Date: Fri, 4 Oct 2024 21:17:50 +0800
Subject: [PATCH 1/3] StringView support
---
pom.xml | 2 +-
src/sqlancer/Main.java | 15 +-
src/sqlancer/datafusion/DataFusionErrors.java | 32 ++--
.../datafusion/DataFusionOptions.java | 10 +-
.../datafusion/DataFusionProvider.java | 49 +++++-
src/sqlancer/datafusion/DataFusionSchema.java | 142 ++++++++++++++----
.../datafusion/DataFusionToStringVisitor.java | 74 ++++++---
src/sqlancer/datafusion/DataFusionUtil.java | 58 +++----
.../datafusion/ast/DataFusionSelect.java | 125 +++++++++++++--
.../datafusion/ast/DataFusionSpecialExpr.java | 13 ++
.../gen/DataFusionTableGenerator.java | 43 +++++-
.../server/datafusion_server/Cargo.toml | 20 +--
.../server/datafusion_server/src/main.rs | 7 +-
.../test/DataFusionNoRECOracle.java | 19 ++-
...ataFusionQueryPartitioningWhereTester.java | 6 +
15 files changed, 476 insertions(+), 139 deletions(-)
create mode 100644 src/sqlancer/datafusion/ast/DataFusionSpecialExpr.java
diff --git a/pom.xml b/pom.xml
index 9bee8348..53f15988 100644
--- a/pom.xml
+++ b/pom.xml
@@ -376,7 +376,7 @@
org.apache.arrow
flight-sql-jdbc-driver
- 16.1.0
+ 17.0.0
diff --git a/src/sqlancer/Main.java b/src/sqlancer/Main.java
index 1cbc0264..5667b928 100644
--- a/src/sqlancer/Main.java
+++ b/src/sqlancer/Main.java
@@ -31,6 +31,7 @@
import sqlancer.common.query.Query;
import sqlancer.common.query.SQLancerResultSet;
import sqlancer.databend.DatabendProvider;
+import sqlancer.datafusion.DataFusionProvider;
import sqlancer.doris.DorisProvider;
import sqlancer.duckdb.DuckDBProvider;
import sqlancer.h2.H2Provider;
@@ -706,9 +707,13 @@ private boolean run(MainOptions options, ExecutorService execService,
}
/**
- * To register a new provider, it is necessary to implement the DatabaseProvider interface and add an additional
- * configuration file, see https://docs.oracle.com/javase/9/docs/api/java/util/ServiceLoader.html. Currently, we use
- * an @AutoService annotation to create the configuration file automatically. This allows SQLancer to pick up
+ * To register a new provider, it is necessary to implement the DatabaseProvider
+ * interface and add an additional
+ * configuration file, see
+ * https://docs.oracle.com/javase/9/docs/api/java/util/ServiceLoader.html.
+ * Currently, we use
+ * an @AutoService annotation to create the configuration file automatically.
+ * This allows SQLancer to pick up
* providers in other JARs on the classpath.
*
* @return The list of service providers on the classpath
@@ -734,6 +739,7 @@ private static void checkForIssue799(List> providers)
providers.add(new CnosDBProvider());
providers.add(new CockroachDBProvider());
providers.add(new DatabendProvider());
+ providers.add(new DataFusionProvider());
providers.add(new DorisProvider());
providers.add(new DuckDBProvider());
providers.add(new H2Provider());
@@ -757,7 +763,8 @@ private static void checkForIssue799(List> providers)
private static synchronized void startProgressMonitor() {
if (progressMonitorStarted) {
/*
- * it might be already started if, for example, the main method is called multiple times in a test (see
+ * it might be already started if, for example, the main method is called
+ * multiple times in a test (see
* https://github.com/sqlancer/sqlancer/issues/90).
*/
return;
diff --git a/src/sqlancer/datafusion/DataFusionErrors.java b/src/sqlancer/datafusion/DataFusionErrors.java
index a646f304..9f065e45 100644
--- a/src/sqlancer/datafusion/DataFusionErrors.java
+++ b/src/sqlancer/datafusion/DataFusionErrors.java
@@ -10,11 +10,14 @@ private DataFusionErrors() {
}
/*
- * During Oracle Checks, if ANY query returns one of the following error Then the current oracle check will be
- * skipped. e.g.: NoREC Q1 -> throw an expected error NoREC Q2 -> succeed Since it's a known error, `SQLancer` will
+ * During Oracle Checks, if ANY query returns one of the following error Then
+ * the current oracle check will be
+ * skipped. e.g.: NoREC Q1 -> throw an expected error NoREC Q2 -> succeed Since
+ * it's a known error, `SQLancer` will
* skip this check and don't report bug.
*
- * Note now it's implemented this way for simplicity This way might cause false negative, because Q1 and Q2 should
+ * Note now it's implemented this way for simplicity This way might cause false
+ * negative, because Q1 and Q2 should
* both succeed or both fail TODO(datafusion): ensure both succeed or both fail
*/
public static void registerExpectedExecutionErrors(ExpectedErrors errors) {
@@ -44,28 +47,28 @@ public static void registerExpectedExecutionErrors(ExpectedErrors errors) {
errors.add("There is only support Literal types for field at idx:");
errors.add("nth_value not supported for n:");
errors.add("Invalid argument error: Nested comparison: List(");
+ errors.add("This feature is not implemented: Percentile value for 'APPROX_PERCENTILE_CONT' must be a literal");
+ errors.add(
+ "This feature is not implemented: Tdigest max_size value for 'APPROX_PERCENTILE_CONT' must be a literal");
/*
* Known bugs
*/
- errors.add("to type Int"); // https://github.com/apache/datafusion/issues/11249
errors.add("bitwise"); // https://github.com/apache/datafusion/issues/11260
errors.add("Sort expressions cannot be empty for streaming merge."); // https://github.com/apache/datafusion/issues/11561
- errors.add("compute_utf8_flag_op_scalar failed to cast literal value NULL for operation"); // https://github.com/apache/datafusion/issues/11623
errors.add("Schema error: No field named "); // https://github.com/apache/datafusion/issues/12006
- errors.add("Internal error: PhysicalExpr Column references column"); // https://github.com/apache/datafusion/issues/12012
- errors.add("APPROX_"); // https://github.com/apache/datafusion/issues/12058
- errors.add("External error: task"); // https://github.com/apache/datafusion/issues/12057
- errors.add("NTH_VALUE"); // https://github.com/apache/datafusion/issues/12073
- errors.add("SUBSTR"); // https://github.com/apache/datafusion/issues/12129
+ // errors.add("regexp_is_match"); //
+ // https://github.com/apache/datafusion/issues/12180
+ errors.add("SUBSTR"); // https://github.com/apache/datafusion/issues/12699
/*
* False positives
*/
errors.add("Cannot cast string"); // ifnull() is passed two non-compattable type and caused execution error
- errors.add("Physical plan does not support logical expression AggregateFunction"); // False positive: when aggr
- // is generated in where
- // clause
+ // False positive: when aggr is generated in where clause
+ errors.add("Physical plan does not support logical expression AggregateFunction");
+ errors.add("Unsupported ArrowType Utf8View"); // Maybe bug in arrow flight
+ // jdbc driver
/*
* Not critical, investigate in the future
@@ -73,5 +76,8 @@ public static void registerExpectedExecutionErrors(ExpectedErrors errors) {
errors.add("does not match with the projection expression");
errors.add("invalid operator for nested");
errors.add("Arrow error: Cast error: Can't cast value");
+ errors.add("Nth value indices are 1 based");
+ errors.add("could not cast value to arrow_array:"); // https://github.com/apache/datafusion/issues/12150
+ errors.add("length not supported for Utf8View"); // https://github.com/apache/datafusion/issues/12149
}
}
diff --git a/src/sqlancer/datafusion/DataFusionOptions.java b/src/sqlancer/datafusion/DataFusionOptions.java
index 5a2d8b69..96256fef 100644
--- a/src/sqlancer/datafusion/DataFusionOptions.java
+++ b/src/sqlancer/datafusion/DataFusionOptions.java
@@ -27,12 +27,12 @@ public class DataFusionOptions implements DBMSSpecificOptions getTestOracleFactory() {
return Arrays.asList(
- // DataFusionOracleFactory.NO_CRASH_WINDOW,
- // DataFusionOracleFactory.NO_CRASH_AGGREGATE,
- DataFusionOracleFactory.NOREC, DataFusionOracleFactory.QUERY_PARTITIONING_WHERE
+ DataFusionOracleFactory.NO_CRASH_WINDOW,
+ DataFusionOracleFactory.NO_CRASH_AGGREGATE,
+ DataFusionOracleFactory.NOREC,
+ DataFusionOracleFactory.QUERY_PARTITIONING_WHERE);
// DataFusionOracleFactory.QUERY_PARTITIONING_AGGREGATE
- // ,DataFusionOracleFactory.QUERY_PARTITIONING_HAVING
- );
+ // DataFusionOracleFactory.QUERY_PARTITIONING_HAVING);
}
public enum DataFusionOracleFactory implements OracleFactory {
diff --git a/src/sqlancer/datafusion/DataFusionProvider.java b/src/sqlancer/datafusion/DataFusionProvider.java
index 37328e4b..2e91cd71 100644
--- a/src/sqlancer/datafusion/DataFusionProvider.java
+++ b/src/sqlancer/datafusion/DataFusionProvider.java
@@ -10,6 +10,7 @@
import java.util.List;
import java.util.Properties;
import java.util.stream.Collectors;
+import java.util.Optional;
import com.google.auto.service.AutoService;
@@ -34,11 +35,30 @@ public DataFusionProvider() {
super(DataFusionGlobalState.class, DataFusionOptions.class);
}
+ // Basic tables generated are DataFusion memory tables (named t1, t2, ...)
+ // Equivalent table can be backed by different physical implementation
+ // which will be named like t1_stringview, t2_parquet, etc.
+ //
+ // e.g. t1 and t1_stringview are logically equivalent table, but backed by
+ // different physical representation
+ //
+ // This helps to do more metamorphic testing on tables, for example
+ // `select * from t1` and `select * from t1_stringview` should give same
+ // result
+ //
+ // Supported physical implementation for tables:
+ // 1. Memory table (t1)
+ // 2. Memory table use StringView for TEXT columns (t1_stringview)
+ // Note: It's possible only convert random TEXT columns to StringView
@Override
public void generateDatabase(DataFusionGlobalState globalState) throws Exception {
+ // Create base tables
+ // ============================
+
int tableCount = Randomly.fromOptions(1, 2, 3, 4, 5, 6, 7);
for (int i = 0; i < tableCount; i++) {
- SQLQueryAdapter queryCreateRandomTable = new DataFusionTableGenerator().getQuery(globalState);
+ SQLQueryAdapter queryCreateRandomTable = new DataFusionTableGenerator()
+ .getCreateStmt(globalState);
queryCreateRandomTable.execute(globalState);
globalState.updateSchema();
globalState.dfLogger.appendToLog(DML, queryCreateRandomTable.toString() + "\n");
@@ -48,15 +68,20 @@ public void generateDatabase(DataFusionGlobalState globalState) throws Exception
// If more DMLs are added later, should use`StatementExecutor` instead
// (see DuckDB's implementation for reference)
+ // Generating rows in base tables (t1, t2, ... not include t1_stringview, etc.)
+ // ============================
+
globalState.updateSchema();
- List allTables = globalState.getSchema().getDatabaseTables();
- List allTablesName = allTables.stream().map(t -> t.getName()).collect(Collectors.toList());
- if (allTablesName.isEmpty()) {
+ List allBaseTables = globalState.getSchema().getDatabaseTables();
+ List allBaseTablesName = allBaseTables.stream()
+ .map(DataFusionTable::getName)
+ .collect(Collectors.toList());
+ if (allBaseTablesName.isEmpty()) {
dfAssert(false, "Generate Database failed.");
}
// Randomly insert some data into existing tables
- for (DataFusionTable table : allTables) {
+ for (DataFusionTable table : allBaseTables) {
int nInsertQuery = globalState.getRandomly().getInteger(0, globalState.getOptions().getMaxNumberInserts());
for (int i = 0; i < nInsertQuery; i++) {
@@ -73,6 +98,20 @@ public void generateDatabase(DataFusionGlobalState globalState) throws Exception
}
}
+ // Construct mutated tables like t1_stringview, etc.
+ // ============================
+ for (DataFusionTable table : allBaseTables) {
+ Optional queryCreateStringViewTable = new DataFusionTableGenerator()
+ .createStringViewTable(globalState, table);
+ if (queryCreateStringViewTable.isPresent()) {
+ queryCreateStringViewTable.get().execute(globalState);
+ globalState.dfLogger.appendToLog(DML, queryCreateStringViewTable.get().toString() + "\n");
+ }
+ }
+ globalState.updateSchema();
+ List allTables = globalState.getSchema().getDatabaseTables();
+ List allTablesName = allTables.stream().map(DataFusionTable::getName).collect(Collectors.toList());
+
// TODO(datafusion) add `DataFUsionLogType.STATE` for this whole db state log
if (globalState.getDbmsSpecificOptions().showDebugInfo) {
System.out.println(displayTables(globalState, allTablesName));
diff --git a/src/sqlancer/datafusion/DataFusionSchema.java b/src/sqlancer/datafusion/DataFusionSchema.java
index 24c3a4eb..1028f4bc 100644
--- a/src/sqlancer/datafusion/DataFusionSchema.java
+++ b/src/sqlancer/datafusion/DataFusionSchema.java
@@ -10,6 +10,9 @@
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
+import java.util.Optional;
+import java.util.regex.Pattern;
+import java.util.regex.Matcher;
import sqlancer.Randomly;
import sqlancer.SQLConnection;
@@ -32,6 +35,9 @@ public DataFusionSchema(List databaseTables) {
// update existing tables in DB by query again
// (like `show tables;`)
+ //
+ // This function also setup table<->column reference pointers
+ // and equivalent tables(see `DataFusionTable.equivalentTables)
public static DataFusionSchema fromConnection(SQLConnection con, String databaseName) throws SQLException {
List databaseTables = new ArrayList<>();
List tableNames = getTableNames(con);
@@ -47,6 +53,26 @@ public static DataFusionSchema fromConnection(SQLConnection con, String database
databaseTables.add(t);
}
+ // Setup equivalent tables
+ // For example, now we have t1, t1_csv, t1_parquet, t2_csv, t2_parquet
+ // t1's equivalent tables: t1, t1_csv, t1_parquet
+ // t2_csv's equivalent tables: t2_csv, t2_parquet
+ // ...
+ //
+ // It can be assumed that:
+ // base table names are like t1, t2, ...
+ // equivalent tables are like t1_csv, t1_parquet, ...
+ for (DataFusionTable t : databaseTables) {
+ String baseTableName = t.getName().split("_")[0];
+ String patternString = "^" + baseTableName + "(_.*)?$"; // t1 or t1_*
+ Pattern pattern = Pattern.compile(patternString);
+
+ t.equivalentTables = databaseTables.stream()
+ .filter(table -> pattern.matcher(table.getName()).matches())
+ .map(DataFusionTable::getName)
+ .collect(Collectors.toList());
+ }
+
return new DataFusionSchema(databaseTables);
}
@@ -84,7 +110,8 @@ private static List getTableColumns(SQLConnection con, String
}
/*
- * When adding a new type: 1. Update all methods inside this enum 2. Update all `DataFusionBaseExpr`'s signature, if
+ * When adding a new type: 1. Update all methods inside this enum 2. Update all
+ * `DataFusionBaseExpr`'s signature, if
* it can support new type (in `DataFusionBaseExprFactory.java`)
*
* Types are 'SQL DataType' in DataFusion's documentation
@@ -112,16 +139,18 @@ public boolean isNumeric() {
// select table_name, column_name, data_type from information_schema.columns;
public static DataFusionDataType parseFromDataFusionCatalog(String typeString) {
switch (typeString) {
- case "Int64":
- return DataFusionDataType.BIGINT;
- case "Float64":
- return DataFusionDataType.DOUBLE;
- case "Boolean":
- return DataFusionDataType.BOOLEAN;
- case "Utf8":
- return DataFusionDataType.STRING;
- default:
- dfAssert(false, "Unreachable. All branches should be eovered");
+ case "Int64":
+ return DataFusionDataType.BIGINT;
+ case "Float64":
+ return DataFusionDataType.DOUBLE;
+ case "Boolean":
+ return DataFusionDataType.BOOLEAN;
+ case "Utf8":
+ return DataFusionDataType.STRING;
+ case "Utf8View":
+ return DataFusionDataType.STRING;
+ default:
+ dfAssert(false, "Uncovered branch typeString: " + typeString);
}
dfAssert(false, "Unreachable. All branches should be eovered");
@@ -134,31 +163,32 @@ public Node getRandomConstant(DataFusionGlobalState state)
return DataFusionConstant.createNullConstant();
}
switch (this) {
- case BIGINT:
- long randInt = Randomly.getBoolean() ? state.getRandomly().getInteger()
- : state.getRandomly().getInteger(-5, 5);
- return DataFusionConstant.createIntConstant(randInt);
- case BOOLEAN:
- return new DataFusionConstant.DataFusionBooleanConstant(Randomly.getBoolean());
- case DOUBLE:
- if (Randomly.getBoolean()) {
+ case BIGINT:
+ long randInt = Randomly.getBoolean() ? state.getRandomly().getInteger()
+ : state.getRandomly().getInteger(-5, 5);
+ return DataFusionConstant.createIntConstant(randInt);
+ case BOOLEAN:
+ return new DataFusionConstant.DataFusionBooleanConstant(Randomly.getBoolean());
+ case DOUBLE:
if (Randomly.getBoolean()) {
- Double randomDouble = state.getRandomly().getDouble(); // [0.0, 1.0);
- Double scaledDouble = (randomDouble - 0.5) * 2 * Double.MAX_VALUE;
- return new DataFusionConstant.DataFusionDoubleConstant(scaledDouble);
+ if (Randomly.getBoolean()) {
+ Double randomDouble = state.getRandomly().getDouble(); // [0.0, 1.0);
+ Double scaledDouble = (randomDouble - 0.5) * 2 * Double.MAX_VALUE;
+ return new DataFusionConstant.DataFusionDoubleConstant(scaledDouble);
+ }
+ String doubleStr = Randomly.fromOptions("'NaN'::Double", "'+Inf'::Double", "'-Inf'::Double",
+ "-0.0",
+ "+0.0");
+ return new DataFusionConstant.DataFusionDoubleConstant(doubleStr);
}
- String doubleStr = Randomly.fromOptions("'NaN'::Double", "'+Inf'::Double", "'-Inf'::Double", "-0.0",
- "+0.0");
- return new DataFusionConstant.DataFusionDoubleConstant(doubleStr);
- }
- return new DataFusionConstant.DataFusionDoubleConstant(state.getRandomly().getDouble());
- case NULL:
- return DataFusionConstant.createNullConstant();
- case STRING:
- return new DataFusionConstant.DataFusionStringConstant(state.getRandomly().getString());
- default:
- dfAssert(false, "Unreachable. All branches should be eovered");
+ return new DataFusionConstant.DataFusionDoubleConstant(state.getRandomly().getDouble());
+ case NULL:
+ return DataFusionConstant.createNullConstant();
+ case STRING:
+ return new DataFusionConstant.DataFusionStringConstant(state.getRandomly().getString());
+ default:
+ dfAssert(false, "Unreachable. All branches should be eovered");
}
dfAssert(false, "Unreachable. All branches should be eovered");
@@ -183,11 +213,57 @@ public boolean isNullable() {
public static class DataFusionTable
extends AbstractRelationalTable {
+ // There might exist multiple logically equivalent tables with
+ // different physical format.
+ // e.g. t1_csv, t1_parquet, ...
+ //
+ // When generating random query, it's possible to randomly pick one
+ // of them for stronger randomization.
+ public List equivalentTables;
+
+ // Pick a random equivalent table name
+ // This can be used when generating differential queries
+ public Optional currentEquivalentTableName;
+
+ // For example in query `select * from t1 as tt1, t1 as tt2`
+ // `tt1` is the alias for the first occurance of `t1`
+ public Optional alias;
public DataFusionTable(String tableName, List columns, boolean isView) {
super(tableName, columns, Collections.emptyList(), isView);
}
+ public String getNotAliasedName() {
+ if (currentEquivalentTableName != null && currentEquivalentTableName.isPresent()) {
+ // In case setup is not done yet
+ return currentEquivalentTableName.get();
+ } else {
+ return super.getName();
+ }
+ }
+
+ // TODO(datafusion) Now implementation is hacky, should send a patch
+ // to core to support this
+ @Override
+ public String getName() {
+ // Before setup equivalent tables, we use the original table name
+ // Setup happens in `fromConnection()`
+ if (equivalentTables == null || currentEquivalentTableName == null) {
+ return super.getName();
+ }
+
+ if (alias.isPresent()) {
+ return alias.get();
+ } else {
+ return currentEquivalentTableName.get();
+ }
+ }
+
+ public void pickAnotherEquivalentTableName() {
+ dfAssert(!equivalentTables.isEmpty(), "equivalentTables should not be empty");
+ currentEquivalentTableName = Optional.of(Randomly.fromList(equivalentTables));
+ }
+
public static List getAllColumns(List tables) {
return tables.stream().map(AbstractTable::getColumns).flatMap(List::stream).collect(Collectors.toList());
}
diff --git a/src/sqlancer/datafusion/DataFusionToStringVisitor.java b/src/sqlancer/datafusion/DataFusionToStringVisitor.java
index f07e4a16..3c91e331 100644
--- a/src/sqlancer/datafusion/DataFusionToStringVisitor.java
+++ b/src/sqlancer/datafusion/DataFusionToStringVisitor.java
@@ -7,11 +7,15 @@
import sqlancer.Randomly;
import sqlancer.common.ast.newast.NewToStringVisitor;
import sqlancer.common.ast.newast.Node;
+import sqlancer.common.ast.newast.TableReferenceNode;
import sqlancer.datafusion.ast.DataFusionConstant;
import sqlancer.datafusion.ast.DataFusionExpression;
import sqlancer.datafusion.ast.DataFusionSelect;
import sqlancer.datafusion.ast.DataFusionSelect.DataFusionFrom;
+import sqlancer.datafusion.DataFusionSchema.DataFusionTable;
import sqlancer.datafusion.ast.DataFusionWindowExpr;
+import sqlancer.datafusion.ast.DataFusionSpecialExpr.CastToStringView;
+import sqlancer.datafusion.ast.DataFusionSelect.DataFusionAlias;
public class DataFusionToStringVisitor extends NewToStringVisitor {
@@ -37,6 +41,10 @@ public void visitSpecific(Node expr) {
visit((DataFusionFrom) expr);
} else if (expr instanceof DataFusionWindowExpr) {
visit((DataFusionWindowExpr) expr);
+ } else if (expr instanceof CastToStringView) {
+ visit((CastToStringView) expr);
+ } else if (expr instanceof DataFusionAlias) {
+ visit((DataFusionAlias) expr);
} else {
throw new AssertionError(expr.getClass());
}
@@ -58,26 +66,26 @@ private void visit(DataFusionFrom from) {
visit(from.tableList.get(0));
for (int i = 0; i < from.joinConditionList.size(); i++) {
switch (from.joinTypeList.get(i)) {
- case INNER:
- sb.append(Randomly.fromOptions(" JOIN ", " INNER JOIN "));
- break;
- case LEFT:
- sb.append(Randomly.fromOptions(" LEFT JOIN ", " LEFT OUTER JOIN "));
- break;
- case RIGHT:
- sb.append(Randomly.fromOptions(" RIGHT JOIN ", " RIGHT OUTER JOIN "));
- break;
- case FULL:
- sb.append(Randomly.fromOptions(" FULL JOIN ", " FULL OUTER JOIN "));
- break;
- case CROSS:
- sb.append(" CROSS JOIN ");
- break;
- case NATURAL:
- sb.append(" NATURAL JOIN ");
- break;
- default:
- dfAssert(false, "Unreachable");
+ case INNER:
+ sb.append(Randomly.fromOptions(" JOIN ", " INNER JOIN "));
+ break;
+ case LEFT:
+ sb.append(Randomly.fromOptions(" LEFT JOIN ", " LEFT OUTER JOIN "));
+ break;
+ case RIGHT:
+ sb.append(Randomly.fromOptions(" RIGHT JOIN ", " RIGHT OUTER JOIN "));
+ break;
+ case FULL:
+ sb.append(Randomly.fromOptions(" FULL JOIN ", " FULL OUTER JOIN "));
+ break;
+ case CROSS:
+ sb.append(" CROSS JOIN ");
+ break;
+ case NATURAL:
+ sb.append(" NATURAL JOIN ");
+ break;
+ default:
+ dfAssert(false, "Unreachable");
}
visit(from.tableList.get(i + 1)); // ti
@@ -163,4 +171,30 @@ private void visit(DataFusionWindowExpr window) {
sb.append(")");
}
+ private void visit(CastToStringView castToStringView) {
+ sb.append("ARROW_CAST(");
+ visit(castToStringView.expr);
+ sb.append(", 'Utf8')");
+ }
+
+ private void visit(DataFusionAlias alias) {
+ if (alias.table instanceof TableReferenceNode) {
+ DataFusionTable t = null;
+ if (alias.table instanceof TableReferenceNode) {
+ t = ((TableReferenceNode) alias.table).getTable();
+ } else {
+ dfAssert(false, "Unreachable");
+ }
+
+ String baseName = t.getNotAliasedName();
+ sb.append(baseName);
+
+ dfAssert(t.alias.isPresent(), "Alias should be present");
+ sb.append(" AS ");
+ sb.append(t.alias.get());
+ } else {
+ dfAssert(false, "Unreachable");
+ }
+ }
+
}
diff --git a/src/sqlancer/datafusion/DataFusionUtil.java b/src/sqlancer/datafusion/DataFusionUtil.java
index ac082afd..b79a6c12 100644
--- a/src/sqlancer/datafusion/DataFusionUtil.java
+++ b/src/sqlancer/datafusion/DataFusionUtil.java
@@ -34,7 +34,6 @@ public static String displayTables(DataFusionGlobalState state, List fro
ResultSetMetaData metaData = wholeTable.getMetaData();
int columnCount = metaData.getColumnCount();
- resultStringBuilder.append("Table: ").append(tableName).append("\n");
for (int i = 1; i <= columnCount; i++) {
resultStringBuilder.append(metaData.getColumnName(i)).append(" (")
.append(metaData.getColumnTypeName(i)).append(")");
@@ -58,7 +57,8 @@ public static String displayTables(DataFusionGlobalState state, List fro
} catch (SQLException err) {
resultStringBuilder.append("Table: ").append(tableName).append("\n");
resultStringBuilder.append("----------------------------------------\n\n");
- // resultStringBuilder.append("Error retrieving data from table ").append(tableName).append(":
+ // resultStringBuilder.append("Error retrieving data from table
+ // ").append(tableName).append(":
// ").append(err.getMessage()).append("\n");
}
}
@@ -66,7 +66,8 @@ public static String displayTables(DataFusionGlobalState state, List fro
return resultStringBuilder.toString();
}
- // During development, you might want to manually let this function call exit(1) to fail fast
+ // During development, you might want to manually let this function call exit(1)
+ // to fail fast
public static void dfAssert(boolean condition, String message) {
if (!condition) {
// Development mode assertion failure
@@ -117,7 +118,8 @@ public String toString() {
}
/*
- * Extra logs stored in 'logs/datafusion_custom_log/' In case re-run overwrite previous logs
+ * Extra logs stored in 'logs/datafusion_custom_log/' In case re-run overwrite
+ * previous logs
*/
public static class DataFusionLogger {
private final DataFusionInstanceID dfID;
@@ -149,25 +151,25 @@ public void appendToLog(DataFusionLogType logType, String logContent) {
// Determine which log file to use based on the LogType
String logLineHeader = "";
switch (logType) {
- case ERROR:
- try {
- logFileWriter = new FileWriter(errorLogFile, true);
- } catch (IOException e) {
- dfAssert(false, "Failed to create FileWriter for errorLogFIle");
- }
- DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
- String formattedDateTime = LocalDateTime.now().format(formatter);
- logLineHeader = "Run@" + formattedDateTime + " (" + dfID + ")\n";
- break;
- case DML:
- logFileWriter = state.getLogger().getCurrentFileWriter();
- logLineHeader = "/*DML*/";
- break;
- case SELECT:
- logFileWriter = state.getLogger().getCurrentFileWriter();
- break;
- default:
- dfAssert(false, "All branch should be covered");
+ case ERROR:
+ try {
+ logFileWriter = new FileWriter(errorLogFile, true);
+ } catch (IOException e) {
+ dfAssert(false, "Failed to create FileWriter for errorLogFIle");
+ }
+ DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
+ String formattedDateTime = LocalDateTime.now().format(formatter);
+ logLineHeader = "Run@" + formattedDateTime + " (" + dfID + ")\n";
+ break;
+ case DML:
+ logFileWriter = state.getLogger().getCurrentFileWriter();
+ logLineHeader = "/*DML*/";
+ break;
+ case SELECT:
+ logFileWriter = state.getLogger().getCurrentFileWriter();
+ break;
+ default:
+ dfAssert(false, "All branch should be covered");
}
// Append content to the appropriate log file
@@ -198,11 +200,11 @@ public static String cleanResultSetString(String value) {
}
switch (value) {
- case "-0.0":
- return "0.0";
- case "-0":
- return "0";
- default:
+ case "-0.0":
+ return "0.0";
+ case "-0":
+ return "0";
+ default:
}
if (value.getBytes().length > 7) {
diff --git a/src/sqlancer/datafusion/ast/DataFusionSelect.java b/src/sqlancer/datafusion/ast/DataFusionSelect.java
index 0b3922b1..a0148e8f 100644
--- a/src/sqlancer/datafusion/ast/DataFusionSelect.java
+++ b/src/sqlancer/datafusion/ast/DataFusionSelect.java
@@ -31,11 +31,13 @@ public class DataFusionSelect extends SelectBase> imp
// First randomly pick a subset say {c2, c1, c3, c4}
// `exprGenAll` can generate random expr using above 4 columns
//
- // Next, randomly take two non-overlapping subset from all columns used by `exprGenAll`
+ // Next, randomly take two non-overlapping subset from all columns used by
+ // `exprGenAll`
// exprGenGroupBy: {c1} (randomly generate group by exprs using c1 only)
// exprGenAggregate: {c3, c4}
//
- // Finally, use all `Gen`s to generate different clauses in a query (`exprGenAll` in where clause, `exprGenGroupBy`
+ // Finally, use all `Gen`s to generate different clauses in a query
+ // (`exprGenAll` in where clause, `exprGenGroupBy`
// in group by clause, etc.)
public DataFusionExpressionGenerator exprGenAll;
public DataFusionExpressionGenerator exprGenGroupBy;
@@ -46,7 +48,8 @@ public enum JoinType {
}
// DataFusionFrom can be used to represent from table list or join list
- // 1. When `joinConditionList` is empty, then it's a table list (implicit cross join)
+ // 1. When `joinConditionList` is empty, then it's a table list (implicit cross
+ // join)
// join condition can be generated in `WHERE` clause (outside `FromClause`)
// e.g. select * from [expr], [expr] is t1, t3, t2
// - tableList -> {t1, t3,t2}
@@ -71,7 +74,8 @@ public DataFusionFrom() {
}
public boolean isExplicitJoin() {
- // if it's explicit join, joinTypeList and joinConditionList should be both length of tableList.len - 1
+ // if it's explicit join, joinTypeList and joinConditionList should be both
+ // length of tableList.len - 1
// Otherwise, both is empty
dfAssert(joinTypeList.size() == joinConditionList.size(), "Validate FromClause");
return !joinTypeList.isEmpty();
@@ -93,13 +97,15 @@ public static DataFusionFrom generateFromClause(DataFusionGlobalState state,
/* If JoinConditionList is empty, FromClause will be interpreted as from list */
if (Randomly.getBoolean() && Randomly.getBoolean()) {
+ fromClause.setupAlias();
return fromClause;
}
/* Set fromClause's joinTypeList and joinConditionList */
List possibleColsToGenExpr = new ArrayList<>();
possibleColsToGenExpr.addAll(randomTables.get(0).getColumns()); // first table
- // Generate join conditions (see class-level comment example's joinConditionList)
+ // Generate join conditions (see class-level comment example's
+ // joinConditionList)
//
// Join Type | `ON` Clause Requirement
// INNER JOIN | Required
@@ -130,12 +136,83 @@ public static DataFusionFrom generateFromClause(DataFusionGlobalState state,
.add(exprGen.generateExpression(DataFusionSchema.DataFusionDataType.BOOLEAN));
}
}
- // TODO(datafusion) make join conditions more likely to be 'col1=col2', also some join types don't have
+ // TODO(datafusion) make join conditions more likely to be 'col1=col2', also
+ // some join types don't have
// 'ON' condition
}
+ // TODO(datafusion) add an option to disable this when issue fixed
+ // https://github.com/apache/datafusion/issues/12337
+ fromClause.setupAlias();
+
return fromClause;
}
+
+ public void setupAlias() {
+ for (int i = 0; i < tableList.size(); i++) {
+ if (tableList.get(i) instanceof TableReferenceNode) {
+ ((TableReferenceNode) tableList.get(i))
+ .getTable().alias = Optional.of("tt" + i);
+ } else {
+ dfAssert(false, "Expected all items in tableList to be TableReferenceNode instances");
+ }
+ }
+
+ // wrap table in `DataFusionAlias` for display
+ List> wrappedTables = new ArrayList<>();
+ for (Node table : tableList) {
+ wrappedTables.add(new DataFusionAlias(table));
+ }
+ tableList = wrappedTables;
+ }
+
+ }
+
+ // If original query is
+ // select * from t1, t2, t3
+ // The randomly mutated query looks like:
+ // select * from t1_csv, t2, t3_parquet
+ public void mutateEquivalentTableName() {
+ for (Node table : from.tableList) {
+ if (table instanceof DataFusionAlias) {
+ Node aliasedTable = ((DataFusionAlias) table).table;
+
+ if (aliasedTable instanceof TableReferenceNode) {
+ ((TableReferenceNode) aliasedTable).getTable()
+ .pickAnotherEquivalentTableName();
+ } else {
+ dfAssert(false, "Expected all items in tableList to be TableReferenceNode instances");
+ }
+ } else {
+ // I want to print the exact type of table
+ System.out.println("DBG mutateEquivalentTableName: " + table.getClass().getName());
+ try {
+ throw new RuntimeException("DBG mutateEquivalentTableName");
+ } catch (RuntimeException e) {
+ e.printStackTrace();
+ }
+ dfAssert(false, "Expected all items in tableList to be TableReferenceNode instances");
+ }
+ }
+ }
+
+ // Just a marker for table in `DataFusionFrom`
+ //
+ // For example in query `select * from t1 as tt1, t1 as tt2`
+ // If it's in the from list, we use `DataFusionAlias` wrapper on the table
+ // and print it as 't1 as tt1'
+ // If the same table is in expressions, don't use the wrapper and print it as
+ // 'tt1'
+ public static class DataFusionAlias implements Node {
+ public Node table;
+
+ public DataFusionAlias(Node table) {
+ dfAssert(table instanceof TableReferenceNode, "Expected table reference node");
+ DataFusionTable t = ((TableReferenceNode) table).getTable();
+ dfAssert(t.alias.isPresent(), "Expected table to have alias");
+
+ this.table = table;
+ }
}
// Generate SELECT statement according to the dependency of exprs, e.g.:
@@ -149,12 +226,17 @@ public static DataFusionFrom generateFromClause(DataFusionGlobalState state,
//
// The generation order will be:
// 1. [from_clause] - Pick tables like t1, t2, t3 and get a join clause
- // 2. [expr_all_cols] - Generate a non-aggregate expression with all columns in t1, t2, t3. e.g.:
+ // 2. [expr_all_cols] - Generate a non-aggregate expression with all columns in
+ // t1, t2, t3. e.g.:
// - t1.v1 = t2.v1 and t1.v2 > t3.v2
- // 3. [expr_groupby_cols], [expr_aggr_cols] - Randomly pick some cols in t1, t2, t3 as group by columns, and pick
- // some other columns as aggregation columns, and generate non-aggr expression [expr_groupby_cols] on group by
- // columns, finally generate aggregation expressions [expr_aggr_cols] on non-group-by/aggregation columns.
- // For example, group by column is t1.v1, and aggregate columns is t2.v1, t3.v1, generated expressions can be:
+ // 3. [expr_groupby_cols], [expr_aggr_cols] - Randomly pick some cols in t1, t2,
+ // t3 as group by columns, and pick
+ // some other columns as aggregation columns, and generate non-aggr expression
+ // [expr_groupby_cols] on group by
+ // columns, finally generate aggregation expressions [expr_aggr_cols] on
+ // non-group-by/aggregation columns.
+ // For example, group by column is t1.v1, and aggregate columns is t2.v1, t3.v1,
+ // generated expressions can be:
// - [expr_groupby_cols] t1.v1 + 1
// - [expr_aggr_cols] SUM(t3.v1 + t2.v1)
public static DataFusionSelect getRandomSelect(DataFusionGlobalState state) {
@@ -191,7 +273,17 @@ public static DataFusionSelect getRandomSelect(DataFusionGlobalState state) {
/* Constructing result */
List> randomColumnNodes = randomColumnsAll.stream()
- .map((c) -> new ColumnReferenceNode(c))
+ .map((c) -> {
+ if (c.getType() == DataFusionSchema.DataFusionDataType.STRING) {
+ Node colRef = new ColumnReferenceNode(
+ c);
+ Node castedColRef = new DataFusionSpecialExpr.CastToStringView(colRef);
+
+ return castedColRef;
+ } else {
+ return new ColumnReferenceNode(c);
+ }
+ })
.collect(Collectors.toList());
randomSelect.setFetchColumns(randomColumnNodes); // TODO(datafusion) make it more random like 'select *'
@@ -218,7 +310,8 @@ public static DataFusionSelect getRandomSelect(DataFusionGlobalState state) {
// ...
// group by v1
//
- // This method assume `DataFusionSelect` is propoerly initialized with `getRandomSelect()`
+ // This method assume `DataFusionSelect` is propoerly initialized with
+ // `getRandomSelect()`
public void setAggregates(DataFusionGlobalState state) {
// group by exprs (e.g. group by v1, abs(v2))
List> groupByExprs = this.exprGenGroupBy.generateExpressionsPreferColumns();
@@ -242,10 +335,12 @@ public void setAggregates(DataFusionGlobalState state) {
}
/*
- * If set fetch columns with string It will override `fetchColumns` in base class when
+ * If set fetch columns with string It will override `fetchColumns` in base
+ * class when
* `DataFusionToStringVisitor.asString()` is called
*
- * This method can be helpful to mutate select in oracle checks: SELECT [expr] ... -> SELECT SUM[expr]
+ * This method can be helpful to mutate select in oracle checks: SELECT [expr]
+ * ... -> SELECT SUM[expr]
*/
public void setFetchColumnsString(String selectExpr) {
this.fetchColumnsString = Optional.of(selectExpr);
diff --git a/src/sqlancer/datafusion/ast/DataFusionSpecialExpr.java b/src/sqlancer/datafusion/ast/DataFusionSpecialExpr.java
new file mode 100644
index 00000000..8ae63861
--- /dev/null
+++ b/src/sqlancer/datafusion/ast/DataFusionSpecialExpr.java
@@ -0,0 +1,13 @@
+package sqlancer.datafusion.ast;
+
+import sqlancer.common.ast.newast.Node;
+
+public class DataFusionSpecialExpr {
+ public static class CastToStringView implements Node {
+ public Node expr;
+
+ public CastToStringView(Node expr) {
+ this.expr = expr;
+ }
+ }
+}
diff --git a/src/sqlancer/datafusion/gen/DataFusionTableGenerator.java b/src/sqlancer/datafusion/gen/DataFusionTableGenerator.java
index 28ce5da3..37b71fff 100644
--- a/src/sqlancer/datafusion/gen/DataFusionTableGenerator.java
+++ b/src/sqlancer/datafusion/gen/DataFusionTableGenerator.java
@@ -1,18 +1,23 @@
package sqlancer.datafusion.gen;
+import java.util.Optional;
import sqlancer.Randomly;
import sqlancer.common.query.ExpectedErrors;
import sqlancer.common.query.SQLQueryAdapter;
import sqlancer.datafusion.DataFusionProvider.DataFusionGlobalState;
import sqlancer.datafusion.DataFusionSchema.DataFusionDataType;
+import sqlancer.datafusion.DataFusionSchema.DataFusionTable;
+import sqlancer.datafusion.DataFusionSchema.DataFusionColumn;
public class DataFusionTableGenerator {
// Randomly generate a query like 'create table t1 (v1 bigint, v2 boolean)'
- public SQLQueryAdapter getQuery(DataFusionGlobalState globalState) {
+ public SQLQueryAdapter getCreateStmt(DataFusionGlobalState globalState) {
ExpectedErrors errors = new ExpectedErrors();
StringBuilder sb = new StringBuilder();
String tableName = globalState.getSchema().getFreeTableName();
+
+ // Build "create table t1..." using sb
sb.append("CREATE TABLE ");
sb.append(tableName);
sb.append("(");
@@ -30,4 +35,40 @@ public SQLQueryAdapter getQuery(DataFusionGlobalState globalState) {
return new SQLQueryAdapter(sb.toString(), errors, true);
}
+
+ // Given a table t1, return create statement to generate t1_stringview
+ // If t1 has no string column, return empty
+ //
+ // Query looks like (only v2 is TEXT column):
+ // create table t1_stringview as
+ // select v1, arrow_cast(v2, 'Utf8View') as v2 from t1;
+ public Optional createStringViewTable(DataFusionGlobalState globalState, DataFusionTable table) {
+ if (!table.getColumns().stream().anyMatch(c -> c.getType().equals(DataFusionDataType.STRING))) {
+ return Optional.empty();
+ }
+
+ StringBuilder sb = new StringBuilder();
+ sb.append("CREATE TABLE ");
+ sb.append(table.getName());
+ sb.append("_stringview AS SELECT ");
+ for (DataFusionColumn column : table.getColumns()) {
+ String colName = column.getName();
+ if (column.getType().equals(DataFusionDataType.STRING)) {
+ // Found a TEXT column, cast it
+ sb.append("arrow_cast(").append(colName).append(", 'Utf8View') as ").append(colName);
+ } else {
+ sb.append(colName);
+ }
+
+ // Join expressions with ','
+ if (column != table.getColumns().get(table.getColumns().size() - 1)) {
+ sb.append(", ");
+ }
+ }
+
+ sb.append(" FROM ").append(table.getName()).append(";");
+
+ return Optional.of(new SQLQueryAdapter(sb.toString(), new ExpectedErrors(), true));
+ }
+
}
diff --git a/src/sqlancer/datafusion/server/datafusion_server/Cargo.toml b/src/sqlancer/datafusion/server/datafusion_server/Cargo.toml
index dd441ba3..6ee59f99 100644
--- a/src/sqlancer/datafusion/server/datafusion_server/Cargo.toml
+++ b/src/sqlancer/datafusion/server/datafusion_server/Cargo.toml
@@ -6,14 +6,14 @@ license = "Apache-2.0"
[dependencies]
ahash = { version = "0.8", default-features = false, features = ["runtime-rng"] }
-arrow = { version = "52.1.0", features = ["prettyprint"] }
-arrow-array = { version = "52.1.0", default-features = false, features = ["chrono-tz"] }
-arrow-buffer = { version = "52.1.0", default-features = false }
-arrow-flight = { version = "52.1.0", features = ["flight-sql-experimental"] }
-arrow-ipc = { version = "52.1.0", default-features = false, features = ["lz4"] }
-arrow-ord = { version = "52.1.0", default-features = false }
-arrow-schema = { version = "52.1.0", default-features = false }
-arrow-string = { version = "52.1.0", default-features = false }
+arrow = { version = "53.0.0", features = ["prettyprint"] }
+arrow-array = { version = "53.0.0", default-features = false, features = ["chrono-tz"] }
+arrow-buffer = { version = "53.0.0", default-features = false }
+arrow-flight = { version = "53.0.0", features = ["flight-sql-experimental"] }
+arrow-ipc = { version = "53.0.0", default-features = false, features = ["lz4"] }
+arrow-ord = { version = "53.0.0", default-features = false }
+arrow-schema = { version = "53.0.0", default-features = false }
+arrow-string = { version = "53.0.0", default-features = false }
async-trait = "0.1.73"
bytes = "1.4"
chrono = { version = "0.4.34", default-features = false }
@@ -35,9 +35,9 @@ rand = "0.8"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1"
tokio = { version = "1.36", features = ["macros", "rt", "sync"] }
-tonic = "0.11"
+tonic = "0.12.1"
uuid = "1.0"
-prost = { version = "0.12", default-features = false }
+prost = { version = "0.13.1" }
prost-derive = { version = "0.12", default-features = false }
mimalloc = { version = "0.1", default-features = false }
diff --git a/src/sqlancer/datafusion/server/datafusion_server/src/main.rs b/src/sqlancer/datafusion/server/datafusion_server/src/main.rs
index 13ec73e9..41b12e21 100644
--- a/src/sqlancer/datafusion/server/datafusion_server/src/main.rs
+++ b/src/sqlancer/datafusion/server/datafusion_server/src/main.rs
@@ -17,7 +17,7 @@ use arrow_flight::{
use arrow_schema::{DataType, Field, Schema};
use dashmap::DashMap;
use datafusion::logical_expr::LogicalPlan;
-use datafusion::prelude::{DataFrame, ParquetReadOptions, SessionConfig, SessionContext};
+use datafusion::prelude::{DataFrame, SessionConfig, SessionContext};
use futures::{Stream, StreamExt, TryStreamExt};
use log::info;
use mimalloc::MiMalloc;
@@ -292,7 +292,7 @@ impl FlightSqlService for FlightSqlServiceImpl {
let result = df
.collect()
.await
- .map_err(|e| status!("Error executing query", e))?;
+ .map_err(|e| status!("Errorr executing query", e))?;
// if we get an empty result, create an empty schema
let schema = match result.first() {
@@ -400,6 +400,8 @@ impl FlightSqlService for FlightSqlServiceImpl {
.and_then(|df| df.into_optimized_plan())
.map_err(|e| Status::internal(format!("Error building plan: {e}")))?;
+ info!("Plan is {:#?}", plan);
+
// store a copy of the plan, it will be used for execution
let plan_uuid = Uuid::new_v4().hyphenated().to_string();
self.statements.insert(plan_uuid.clone(), plan.clone());
@@ -417,6 +419,7 @@ impl FlightSqlService for FlightSqlServiceImpl {
dataset_schema: schema_bytes,
parameter_schema: Default::default(),
};
+ info!("do_action_create_prepared_statement SUCCEED!");
Ok(res)
}
diff --git a/src/sqlancer/datafusion/test/DataFusionNoRECOracle.java b/src/sqlancer/datafusion/test/DataFusionNoRECOracle.java
index c4a7defb..a4c69a0b 100644
--- a/src/sqlancer/datafusion/test/DataFusionNoRECOracle.java
+++ b/src/sqlancer/datafusion/test/DataFusionNoRECOracle.java
@@ -7,6 +7,7 @@
import java.util.List;
import sqlancer.ComparatorHelper;
+import sqlancer.IgnoreMeException;
import sqlancer.common.oracle.NoRECBase;
import sqlancer.common.oracle.TestOracle;
import sqlancer.datafusion.DataFusionErrors;
@@ -43,24 +44,31 @@ public void check() throws SQLException {
// generate a random:
// SELECT [expr1] FROM [expr2] WHERE [expr3]
DataFusionSelect randomSelect = getRandomSelect(state);
+
// Q1: SELECT count(*) FROM [expr2] WHERE [expr3]
+ // Q1 and Q2 is constructed from randomSelect's fields
+ // So for equivalent table mutation, we mutate randomSelect
+ randomSelect.mutateEquivalentTableName();
DataFusionSelect q1 = new DataFusionSelect();
q1.setFetchColumnsString("COUNT(*)");
q1.from = randomSelect.from;
q1.setWhereClause(randomSelect.getWhereClause());
+ String q1String = DataFusionToStringVisitor.asString(q1);
+
// Q2: SELECT count(case when [expr3] then 1 else null end) FROM [expr2]
+ randomSelect.mutateEquivalentTableName();
DataFusionSelect q2 = new DataFusionSelect();
String selectExpr = String.format("COUNT(CASE WHEN %s THEN 1 ELSE NULL END)",
DataFusionToStringVisitor.asString(randomSelect.getWhereClause()));
q2.setFetchColumnsString(selectExpr);
q2.from = randomSelect.from;
q2.setWhereClause(null);
+ String q2String = DataFusionToStringVisitor.asString(q2);
/*
* Execute Q1 and Q2
*/
- String q1String = DataFusionToStringVisitor.asString(q1);
- String q2String = DataFusionToStringVisitor.asString(q2);
+ // System.out.println("DBG: " + q1String + "\n" + q2String);
List q1ResultSet = null;
List q2ResultSet = null;
try {
@@ -81,6 +89,13 @@ public void check() throws SQLException {
int count1 = q1ResultSet != null ? Integer.parseInt(q1ResultSet.get(0)) : -1;
int count2 = q2ResultSet != null ? Integer.parseInt(q2ResultSet.get(0)) : -1;
if (count1 != count2) {
+ // whitelist
+ // ---------
+ // https://github.com/apache/datafusion/issues/12468
+ if (q1String.contains("NATURAL JOIN")) {
+ throw new IgnoreMeException();
+ }
+
StringBuilder errorMessage = new StringBuilder().append("NoREC oracle violated:\n")
.append(" Q1(result size ").append(count1).append("):").append(q1String).append(";\n")
.append(" Q2(result size ").append(count2).append("):").append(q2String).append(";\n")
diff --git a/src/sqlancer/datafusion/test/DataFusionQueryPartitioningWhereTester.java b/src/sqlancer/datafusion/test/DataFusionQueryPartitioningWhereTester.java
index 9d6c2efc..b604cbc9 100644
--- a/src/sqlancer/datafusion/test/DataFusionQueryPartitioningWhereTester.java
+++ b/src/sqlancer/datafusion/test/DataFusionQueryPartitioningWhereTester.java
@@ -43,6 +43,7 @@ public void check() throws SQLException {
// generate a random 'SELECT [expr1] FROM [expr2] WHERE [expr3]
super.check();
DataFusionSelect randomSelect = select;
+ randomSelect.mutateEquivalentTableName();
if (Randomly.getBoolean()) {
randomSelect.distinct = true;
@@ -69,12 +70,15 @@ public void check() throws SQLException {
randomSelect.setWhereClause(null);
qString = DataFusionToStringVisitor.asString(randomSelect);
+ randomSelect.mutateEquivalentTableName();
randomSelect.setWhereClause(predicate);
qp1String = DataFusionToStringVisitor.asString(randomSelect);
+ randomSelect.mutateEquivalentTableName();
randomSelect.setWhereClause(negatedPredicate);
qp2String = DataFusionToStringVisitor.asString(randomSelect);
+ randomSelect.mutateEquivalentTableName();
randomSelect.setWhereClause(isNullPredicate);
qp3String = DataFusionToStringVisitor.asString(randomSelect);
} else {
@@ -111,6 +115,8 @@ public void check() throws SQLException {
/*
* Run all queires
*/
+ // System.out.println("DBG TLP: " + qString + "\n" + qp1String + "\n" +
+ // qp2String + "\n" + qp3String);
List qResultSet = ComparatorHelper.getResultSetFirstColumnAsString(qString, errors, state);
List combinedString = new ArrayList<>();
List qpResultSet = ComparatorHelper.getCombinedResultSet(qp1String, qp2String, qp3String,
From 7d594c994874b1762a06862703dfa2b74ece0529 Mon Sep 17 00:00:00 2001
From: Yongting You <2010youy01@gmail.com>
Date: Mon, 6 Jan 2025 17:18:54 +0800
Subject: [PATCH 2/3] Support PQS test oracle
---
src/sqlancer/ComparatorHelper.java | 3 +-
src/sqlancer/IgnoreMeException.java | 7 +
src/sqlancer/Main.java | 13 +-
.../common/query/SQLancerResultSet.java | 2 +-
src/sqlancer/datafusion/DataFusionErrors.java | 25 +-
.../datafusion/DataFusionOptions.java | 13 +-
.../datafusion/DataFusionProvider.java | 19 +-
src/sqlancer/datafusion/DataFusionSchema.java | 99 +-
.../datafusion/DataFusionToStringVisitor.java | 63 +-
src/sqlancer/datafusion/DataFusionUtil.java | 51 +-
.../datafusion/ast/DataFusionSelect.java | 84 +-
.../gen/DataFusionExpressionGenerator.java | 18 +-
.../gen/DataFusionTableGenerator.java | 3 +-
.../server/datafusion_server/Cargo.lock | 3366 +++++++++++++++++
.../server/datafusion_server/Cargo.toml | 38 +-
.../test/DataFusionNoRECOracle.java | 1 +
.../datafusion/test/DataFusionPQS.java | 344 ++
...ataFusionQueryPartitioningWhereTester.java | 8 +
18 files changed, 3959 insertions(+), 198 deletions(-)
create mode 100644 src/sqlancer/datafusion/server/datafusion_server/Cargo.lock
create mode 100644 src/sqlancer/datafusion/test/DataFusionPQS.java
diff --git a/src/sqlancer/ComparatorHelper.java b/src/sqlancer/ComparatorHelper.java
index 5da635de..d061ecb7 100644
--- a/src/sqlancer/ComparatorHelper.java
+++ b/src/sqlancer/ComparatorHelper.java
@@ -131,7 +131,8 @@ public static void assumeResultSetsAreEqual(List resultSet, List
public static void assumeResultSetsAreEqual(List resultSet, List secondResultSet,
String originalQueryString, List combinedString, SQLGlobalState, ?> state,
UnaryOperator canonicalizationRule) {
- // Overloaded version of assumeResultSetsAreEqual that takes a canonicalization function which is applied to
+ // Overloaded version of assumeResultSetsAreEqual that takes a canonicalization
+ // function which is applied to
// both result sets before their comparison.
List canonicalizedResultSet = resultSet.stream().map(canonicalizationRule).collect(Collectors.toList());
List canonicalizedSecondResultSet = secondResultSet.stream().map(canonicalizationRule)
diff --git a/src/sqlancer/IgnoreMeException.java b/src/sqlancer/IgnoreMeException.java
index bc2e2591..cdae6acd 100644
--- a/src/sqlancer/IgnoreMeException.java
+++ b/src/sqlancer/IgnoreMeException.java
@@ -4,4 +4,11 @@ public class IgnoreMeException extends RuntimeException {
private static final long serialVersionUID = 1L;
+ public IgnoreMeException() {
+ super();
+ }
+
+ public IgnoreMeException(String message) {
+ super(message);
+ }
}
diff --git a/src/sqlancer/Main.java b/src/sqlancer/Main.java
index 5667b928..68639093 100644
--- a/src/sqlancer/Main.java
+++ b/src/sqlancer/Main.java
@@ -707,13 +707,9 @@ private boolean run(MainOptions options, ExecutorService execService,
}
/**
- * To register a new provider, it is necessary to implement the DatabaseProvider
- * interface and add an additional
- * configuration file, see
- * https://docs.oracle.com/javase/9/docs/api/java/util/ServiceLoader.html.
- * Currently, we use
- * an @AutoService annotation to create the configuration file automatically.
- * This allows SQLancer to pick up
+ * To register a new provider, it is necessary to implement the DatabaseProvider interface and add an additional
+ * configuration file, see https://docs.oracle.com/javase/9/docs/api/java/util/ServiceLoader.html. Currently, we use
+ * an @AutoService annotation to create the configuration file automatically. This allows SQLancer to pick up
* providers in other JARs on the classpath.
*
* @return The list of service providers on the classpath
@@ -763,8 +759,7 @@ private static void checkForIssue799(List> providers)
private static synchronized void startProgressMonitor() {
if (progressMonitorStarted) {
/*
- * it might be already started if, for example, the main method is called
- * multiple times in a test (see
+ * it might be already started if, for example, the main method is called multiple times in a test (see
* https://github.com/sqlancer/sqlancer/issues/90).
*/
return;
diff --git a/src/sqlancer/common/query/SQLancerResultSet.java b/src/sqlancer/common/query/SQLancerResultSet.java
index d1221a7f..7cc1523e 100644
--- a/src/sqlancer/common/query/SQLancerResultSet.java
+++ b/src/sqlancer/common/query/SQLancerResultSet.java
@@ -6,7 +6,7 @@
public class SQLancerResultSet implements Closeable {
- ResultSet rs;
+ public ResultSet rs;
private Runnable runnableEpilogue;
public SQLancerResultSet(ResultSet rs) {
diff --git a/src/sqlancer/datafusion/DataFusionErrors.java b/src/sqlancer/datafusion/DataFusionErrors.java
index 9f065e45..9e62bbe9 100644
--- a/src/sqlancer/datafusion/DataFusionErrors.java
+++ b/src/sqlancer/datafusion/DataFusionErrors.java
@@ -10,14 +10,11 @@ private DataFusionErrors() {
}
/*
- * During Oracle Checks, if ANY query returns one of the following error Then
- * the current oracle check will be
- * skipped. e.g.: NoREC Q1 -> throw an expected error NoREC Q2 -> succeed Since
- * it's a known error, `SQLancer` will
+ * During Oracle Checks, if ANY query returns one of the following error Then the current oracle check will be
+ * skipped. e.g.: NoREC Q1 -> throw an expected error NoREC Q2 -> succeed Since it's a known error, `SQLancer` will
* skip this check and don't report bug.
*
- * Note now it's implemented this way for simplicity This way might cause false
- * negative, because Q1 and Q2 should
+ * Note now it's implemented this way for simplicity This way might cause false negative, because Q1 and Q2 should
* both succeed or both fail TODO(datafusion): ensure both succeed or both fail
*/
public static void registerExpectedExecutionErrors(ExpectedErrors errors) {
@@ -57,9 +54,7 @@ public static void registerExpectedExecutionErrors(ExpectedErrors errors) {
errors.add("bitwise"); // https://github.com/apache/datafusion/issues/11260
errors.add("Sort expressions cannot be empty for streaming merge."); // https://github.com/apache/datafusion/issues/11561
errors.add("Schema error: No field named "); // https://github.com/apache/datafusion/issues/12006
- // errors.add("regexp_is_match"); //
- // https://github.com/apache/datafusion/issues/12180
- errors.add("SUBSTR"); // https://github.com/apache/datafusion/issues/12699
+ errors.add("NATURAL JOIN"); // https://github.com/apache/datafusion/issues/14015
/*
* False positives
@@ -77,7 +72,15 @@ public static void registerExpectedExecutionErrors(ExpectedErrors errors) {
errors.add("invalid operator for nested");
errors.add("Arrow error: Cast error: Can't cast value");
errors.add("Nth value indices are 1 based");
- errors.add("could not cast value to arrow_array:"); // https://github.com/apache/datafusion/issues/12150
- errors.add("length not supported for Utf8View"); // https://github.com/apache/datafusion/issues/12149
+ /*
+ * Example query that triggers this error: create table t1(v1 int, v2 bool); select v1, sum(1) over (partition
+ * by v1 order by v2 range between 0 preceding and 0 following) from t1;
+ *
+ * Current error message: Arrow error: Invalid argument error: Invalid arithmetic operation: Boolean - Boolean
+ *
+ * TODO: The error message could be more meaningful to indicate that RANGE frame is not supported for boolean
+ * ORDER BY columns
+ */
+ errors.add("Invalid arithmetic operation");
}
}
diff --git a/src/sqlancer/datafusion/DataFusionOptions.java b/src/sqlancer/datafusion/DataFusionOptions.java
index 96256fef..56db6b76 100644
--- a/src/sqlancer/datafusion/DataFusionOptions.java
+++ b/src/sqlancer/datafusion/DataFusionOptions.java
@@ -15,6 +15,7 @@
import sqlancer.datafusion.test.DataFusionNoCrashAggregate;
import sqlancer.datafusion.test.DataFusionNoCrashWindow;
import sqlancer.datafusion.test.DataFusionNoRECOracle;
+import sqlancer.datafusion.test.DataFusionPQS;
import sqlancer.datafusion.test.DataFusionQueryPartitioningAggrTester;
import sqlancer.datafusion.test.DataFusionQueryPartitioningHavingTester;
import sqlancer.datafusion.test.DataFusionQueryPartitioningWhereTester;
@@ -26,10 +27,8 @@ public class DataFusionOptions implements DBMSSpecificOptions getTestOracleFactory() {
- return Arrays.asList(
- DataFusionOracleFactory.NO_CRASH_WINDOW,
- DataFusionOracleFactory.NO_CRASH_AGGREGATE,
- DataFusionOracleFactory.NOREC,
+ return Arrays.asList(DataFusionOracleFactory.PQS, DataFusionOracleFactory.NO_CRASH_WINDOW,
+ DataFusionOracleFactory.NO_CRASH_AGGREGATE, DataFusionOracleFactory.NOREC,
DataFusionOracleFactory.QUERY_PARTITIONING_WHERE);
// DataFusionOracleFactory.QUERY_PARTITIONING_AGGREGATE
// DataFusionOracleFactory.QUERY_PARTITIONING_HAVING);
@@ -42,6 +41,12 @@ public TestOracle create(DataFusionGlobalState globalStat
return new DataFusionNoRECOracle(globalState);
}
},
+ PQS {
+ @Override
+ public TestOracle create(DataFusionGlobalState globalState) throws SQLException {
+ return new DataFusionPQS(globalState);
+ }
+ },
QUERY_PARTITIONING_WHERE {
@Override
public TestOracle create(DataFusionGlobalState globalState) throws SQLException {
diff --git a/src/sqlancer/datafusion/DataFusionProvider.java b/src/sqlancer/datafusion/DataFusionProvider.java
index 2e91cd71..5ad60561 100644
--- a/src/sqlancer/datafusion/DataFusionProvider.java
+++ b/src/sqlancer/datafusion/DataFusionProvider.java
@@ -1,6 +1,5 @@
package sqlancer.datafusion;
-import static sqlancer.datafusion.DataFusionUtil.DataFusionLogger.DataFusionLogType.DML;
import static sqlancer.datafusion.DataFusionUtil.dfAssert;
import static sqlancer.datafusion.DataFusionUtil.displayTables;
@@ -8,9 +7,9 @@
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.List;
+import java.util.Optional;
import java.util.Properties;
import java.util.stream.Collectors;
-import java.util.Optional;
import com.google.auto.service.AutoService;
@@ -55,13 +54,13 @@ public void generateDatabase(DataFusionGlobalState globalState) throws Exception
// Create base tables
// ============================
- int tableCount = Randomly.fromOptions(1, 2, 3, 4, 5, 6, 7);
+ int tableCount = Randomly.fromOptions(1, 2, 3, 4);
for (int i = 0; i < tableCount; i++) {
- SQLQueryAdapter queryCreateRandomTable = new DataFusionTableGenerator()
- .getCreateStmt(globalState);
+ SQLQueryAdapter queryCreateRandomTable = new DataFusionTableGenerator().getCreateStmt(globalState);
queryCreateRandomTable.execute(globalState);
globalState.updateSchema();
- globalState.dfLogger.appendToLog(DML, queryCreateRandomTable.toString() + "\n");
+ globalState.dfLogger.appendToLog(DataFusionLogger.DataFusionLogType.DML,
+ queryCreateRandomTable.toString() + "\n");
}
// Now only `INSERT` DML is supported
@@ -73,8 +72,7 @@ public void generateDatabase(DataFusionGlobalState globalState) throws Exception
globalState.updateSchema();
List allBaseTables = globalState.getSchema().getDatabaseTables();
- List allBaseTablesName = allBaseTables.stream()
- .map(DataFusionTable::getName)
+ List allBaseTablesName = allBaseTables.stream().map(DataFusionTable::getName)
.collect(Collectors.toList());
if (allBaseTablesName.isEmpty()) {
dfAssert(false, "Generate Database failed.");
@@ -94,7 +92,7 @@ public void generateDatabase(DataFusionGlobalState globalState) throws Exception
}
insertQuery.execute(globalState);
- globalState.dfLogger.appendToLog(DML, insertQuery.toString() + "\n");
+ globalState.dfLogger.appendToLog(DataFusionLogger.DataFusionLogType.DML, insertQuery.toString() + "\n");
}
}
@@ -105,7 +103,8 @@ public void generateDatabase(DataFusionGlobalState globalState) throws Exception
.createStringViewTable(globalState, table);
if (queryCreateStringViewTable.isPresent()) {
queryCreateStringViewTable.get().execute(globalState);
- globalState.dfLogger.appendToLog(DML, queryCreateStringViewTable.get().toString() + "\n");
+ globalState.dfLogger.appendToLog(DataFusionLogger.DataFusionLogType.DML,
+ queryCreateStringViewTable.get().toString() + "\n");
}
}
globalState.updateSchema();
diff --git a/src/sqlancer/datafusion/DataFusionSchema.java b/src/sqlancer/datafusion/DataFusionSchema.java
index 1028f4bc..2d08a347 100644
--- a/src/sqlancer/datafusion/DataFusionSchema.java
+++ b/src/sqlancer/datafusion/DataFusionSchema.java
@@ -9,10 +9,9 @@
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
-import java.util.stream.Collectors;
import java.util.Optional;
import java.util.regex.Pattern;
-import java.util.regex.Matcher;
+import java.util.stream.Collectors;
import sqlancer.Randomly;
import sqlancer.SQLConnection;
@@ -67,10 +66,8 @@ public static DataFusionSchema fromConnection(SQLConnection con, String database
String patternString = "^" + baseTableName + "(_.*)?$"; // t1 or t1_*
Pattern pattern = Pattern.compile(patternString);
- t.equivalentTables = databaseTables.stream()
- .filter(table -> pattern.matcher(table.getName()).matches())
- .map(DataFusionTable::getName)
- .collect(Collectors.toList());
+ t.equivalentTables = databaseTables.stream().filter(table -> pattern.matcher(table.getName()).matches())
+ .map(DataFusionTable::getName).collect(Collectors.toList());
}
return new DataFusionSchema(databaseTables);
@@ -110,8 +107,7 @@ private static List getTableColumns(SQLConnection con, String
}
/*
- * When adding a new type: 1. Update all methods inside this enum 2. Update all
- * `DataFusionBaseExpr`'s signature, if
+ * When adding a new type: 1. Update all methods inside this enum 2. Update all `DataFusionBaseExpr`'s signature, if
* it can support new type (in `DataFusionBaseExprFactory.java`)
*
* Types are 'SQL DataType' in DataFusion's documentation
@@ -139,18 +135,18 @@ public boolean isNumeric() {
// select table_name, column_name, data_type from information_schema.columns;
public static DataFusionDataType parseFromDataFusionCatalog(String typeString) {
switch (typeString) {
- case "Int64":
- return DataFusionDataType.BIGINT;
- case "Float64":
- return DataFusionDataType.DOUBLE;
- case "Boolean":
- return DataFusionDataType.BOOLEAN;
- case "Utf8":
- return DataFusionDataType.STRING;
- case "Utf8View":
- return DataFusionDataType.STRING;
- default:
- dfAssert(false, "Uncovered branch typeString: " + typeString);
+ case "Int64":
+ return DataFusionDataType.BIGINT;
+ case "Float64":
+ return DataFusionDataType.DOUBLE;
+ case "Boolean":
+ return DataFusionDataType.BOOLEAN;
+ case "Utf8":
+ return DataFusionDataType.STRING;
+ case "Utf8View":
+ return DataFusionDataType.STRING;
+ default:
+ dfAssert(false, "Uncovered branch typeString: " + typeString);
}
dfAssert(false, "Unreachable. All branches should be eovered");
@@ -163,32 +159,31 @@ public Node getRandomConstant(DataFusionGlobalState state)
return DataFusionConstant.createNullConstant();
}
switch (this) {
- case BIGINT:
- long randInt = Randomly.getBoolean() ? state.getRandomly().getInteger()
- : state.getRandomly().getInteger(-5, 5);
- return DataFusionConstant.createIntConstant(randInt);
- case BOOLEAN:
- return new DataFusionConstant.DataFusionBooleanConstant(Randomly.getBoolean());
- case DOUBLE:
+ case BIGINT:
+ long randInt = Randomly.getBoolean() ? state.getRandomly().getInteger()
+ : state.getRandomly().getInteger(-5, 5);
+ return DataFusionConstant.createIntConstant(randInt);
+ case BOOLEAN:
+ return new DataFusionConstant.DataFusionBooleanConstant(Randomly.getBoolean());
+ case DOUBLE:
+ if (Randomly.getBoolean()) {
if (Randomly.getBoolean()) {
- if (Randomly.getBoolean()) {
- Double randomDouble = state.getRandomly().getDouble(); // [0.0, 1.0);
- Double scaledDouble = (randomDouble - 0.5) * 2 * Double.MAX_VALUE;
- return new DataFusionConstant.DataFusionDoubleConstant(scaledDouble);
- }
- String doubleStr = Randomly.fromOptions("'NaN'::Double", "'+Inf'::Double", "'-Inf'::Double",
- "-0.0",
- "+0.0");
- return new DataFusionConstant.DataFusionDoubleConstant(doubleStr);
+ Double randomDouble = state.getRandomly().getDouble(); // [0.0, 1.0);
+ Double scaledDouble = (randomDouble - 0.5) * 2 * Double.MAX_VALUE;
+ return new DataFusionConstant.DataFusionDoubleConstant(scaledDouble);
}
+ String doubleStr = Randomly.fromOptions("'NaN'::Double", "'+Inf'::Double", "'-Inf'::Double", "-0.0",
+ "+0.0");
+ return new DataFusionConstant.DataFusionDoubleConstant(doubleStr);
+ }
- return new DataFusionConstant.DataFusionDoubleConstant(state.getRandomly().getDouble());
- case NULL:
- return DataFusionConstant.createNullConstant();
- case STRING:
- return new DataFusionConstant.DataFusionStringConstant(state.getRandomly().getString());
- default:
- dfAssert(false, "Unreachable. All branches should be eovered");
+ return new DataFusionConstant.DataFusionDoubleConstant(state.getRandomly().getDouble());
+ case NULL:
+ return DataFusionConstant.createNullConstant();
+ case STRING:
+ return new DataFusionConstant.DataFusionStringConstant(state.getRandomly().getString());
+ default:
+ dfAssert(false, "Unreachable. All branches should be eovered");
}
dfAssert(false, "Unreachable. All branches should be eovered");
@@ -199,16 +194,34 @@ public Node getRandomConstant(DataFusionGlobalState state)
public static class DataFusionColumn extends AbstractTableColumn {
private final boolean isNullable;
+ public Optional alias;
public DataFusionColumn(String name, DataFusionDataType columnType, boolean isNullable) {
super(name, null, columnType);
this.isNullable = isNullable;
+ this.alias = Optional.empty();
}
public boolean isNullable() {
return isNullable;
}
+ public String getOrignalName() {
+ return getTable().getName() + "." + getName();
+ }
+
+ @Override
+ public String getFullQualifiedName() {
+ if (getTable() == null) {
+ return getName();
+ } else {
+ if (alias.isPresent()) {
+ return alias.get();
+ } else {
+ return getTable().getName() + "." + getName();
+ }
+ }
+ }
}
public static class DataFusionTable
diff --git a/src/sqlancer/datafusion/DataFusionToStringVisitor.java b/src/sqlancer/datafusion/DataFusionToStringVisitor.java
index 3c91e331..11965841 100644
--- a/src/sqlancer/datafusion/DataFusionToStringVisitor.java
+++ b/src/sqlancer/datafusion/DataFusionToStringVisitor.java
@@ -8,14 +8,14 @@
import sqlancer.common.ast.newast.NewToStringVisitor;
import sqlancer.common.ast.newast.Node;
import sqlancer.common.ast.newast.TableReferenceNode;
+import sqlancer.datafusion.DataFusionSchema.DataFusionTable;
import sqlancer.datafusion.ast.DataFusionConstant;
import sqlancer.datafusion.ast.DataFusionExpression;
import sqlancer.datafusion.ast.DataFusionSelect;
+import sqlancer.datafusion.ast.DataFusionSelect.DataFusionAliasedTable;
import sqlancer.datafusion.ast.DataFusionSelect.DataFusionFrom;
-import sqlancer.datafusion.DataFusionSchema.DataFusionTable;
-import sqlancer.datafusion.ast.DataFusionWindowExpr;
import sqlancer.datafusion.ast.DataFusionSpecialExpr.CastToStringView;
-import sqlancer.datafusion.ast.DataFusionSelect.DataFusionAlias;
+import sqlancer.datafusion.ast.DataFusionWindowExpr;
public class DataFusionToStringVisitor extends NewToStringVisitor {
@@ -43,8 +43,8 @@ public void visitSpecific(Node expr) {
visit((DataFusionWindowExpr) expr);
} else if (expr instanceof CastToStringView) {
visit((CastToStringView) expr);
- } else if (expr instanceof DataFusionAlias) {
- visit((DataFusionAlias) expr);
+ } else if (expr instanceof DataFusionAliasedTable) {
+ visit((DataFusionAliasedTable) expr);
} else {
throw new AssertionError(expr.getClass());
}
@@ -57,38 +57,38 @@ private void visit(DataFusionFrom from) {
/* e.g. from t1, t2, t3 */
if (from.joinConditionList.isEmpty()) {
- visit(from.tableList);
+ visit(from.tableExprList);
return;
}
- dfAssert(from.joinConditionList.size() == from.tableList.size() - 1, "Validate from");
+ dfAssert(from.joinConditionList.size() == from.tableExprList.size() - 1, "Validate from");
/* e.g. from t1 join t2 on t1.v1=t2.v1 */
- visit(from.tableList.get(0));
+ visit(from.tableExprList.get(0));
for (int i = 0; i < from.joinConditionList.size(); i++) {
switch (from.joinTypeList.get(i)) {
- case INNER:
- sb.append(Randomly.fromOptions(" JOIN ", " INNER JOIN "));
- break;
- case LEFT:
- sb.append(Randomly.fromOptions(" LEFT JOIN ", " LEFT OUTER JOIN "));
- break;
- case RIGHT:
- sb.append(Randomly.fromOptions(" RIGHT JOIN ", " RIGHT OUTER JOIN "));
- break;
- case FULL:
- sb.append(Randomly.fromOptions(" FULL JOIN ", " FULL OUTER JOIN "));
- break;
- case CROSS:
- sb.append(" CROSS JOIN ");
- break;
- case NATURAL:
- sb.append(" NATURAL JOIN ");
- break;
- default:
- dfAssert(false, "Unreachable");
+ case INNER:
+ sb.append(Randomly.fromOptions(" JOIN ", " INNER JOIN "));
+ break;
+ case LEFT:
+ sb.append(Randomly.fromOptions(" LEFT JOIN ", " LEFT OUTER JOIN "));
+ break;
+ case RIGHT:
+ sb.append(Randomly.fromOptions(" RIGHT JOIN ", " RIGHT OUTER JOIN "));
+ break;
+ case FULL:
+ sb.append(Randomly.fromOptions(" FULL JOIN ", " FULL OUTER JOIN "));
+ break;
+ case CROSS:
+ sb.append(" CROSS JOIN ");
+ break;
+ case NATURAL:
+ sb.append(" NATURAL JOIN ");
+ break;
+ default:
+ dfAssert(false, "Unreachable");
}
- visit(from.tableList.get(i + 1)); // ti
+ visit(from.tableExprList.get(i + 1)); // ti
/* ON ... */
Node cond = from.joinConditionList.get(i);
@@ -177,11 +177,12 @@ private void visit(CastToStringView castToStringView) {
sb.append(", 'Utf8')");
}
- private void visit(DataFusionAlias alias) {
+ private void visit(DataFusionAliasedTable alias) {
if (alias.table instanceof TableReferenceNode) {
DataFusionTable t = null;
if (alias.table instanceof TableReferenceNode) {
- t = ((TableReferenceNode) alias.table).getTable();
+ TableReferenceNode, ?> tableRef = (TableReferenceNode, ?>) alias.table;
+ t = (DataFusionTable) tableRef.getTable();
} else {
dfAssert(false, "Unreachable");
}
diff --git a/src/sqlancer/datafusion/DataFusionUtil.java b/src/sqlancer/datafusion/DataFusionUtil.java
index b79a6c12..4f5b34f6 100644
--- a/src/sqlancer/datafusion/DataFusionUtil.java
+++ b/src/sqlancer/datafusion/DataFusionUtil.java
@@ -118,8 +118,7 @@ public String toString() {
}
/*
- * Extra logs stored in 'logs/datafusion_custom_log/' In case re-run overwrite
- * previous logs
+ * Extra logs stored in 'logs/datafusion_custom_log/' In case re-run overwrite previous logs
*/
public static class DataFusionLogger {
private final DataFusionInstanceID dfID;
@@ -151,25 +150,25 @@ public void appendToLog(DataFusionLogType logType, String logContent) {
// Determine which log file to use based on the LogType
String logLineHeader = "";
switch (logType) {
- case ERROR:
- try {
- logFileWriter = new FileWriter(errorLogFile, true);
- } catch (IOException e) {
- dfAssert(false, "Failed to create FileWriter for errorLogFIle");
- }
- DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
- String formattedDateTime = LocalDateTime.now().format(formatter);
- logLineHeader = "Run@" + formattedDateTime + " (" + dfID + ")\n";
- break;
- case DML:
- logFileWriter = state.getLogger().getCurrentFileWriter();
- logLineHeader = "/*DML*/";
- break;
- case SELECT:
- logFileWriter = state.getLogger().getCurrentFileWriter();
- break;
- default:
- dfAssert(false, "All branch should be covered");
+ case ERROR:
+ try {
+ logFileWriter = new FileWriter(errorLogFile, true);
+ } catch (IOException e) {
+ dfAssert(false, "Failed to create FileWriter for errorLogFIle");
+ }
+ DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
+ String formattedDateTime = LocalDateTime.now().format(formatter);
+ logLineHeader = "Run@" + formattedDateTime + " (" + dfID + ")\n";
+ break;
+ case DML:
+ logFileWriter = state.getLogger().getCurrentFileWriter();
+ logLineHeader = "/*DML*/";
+ break;
+ case SELECT:
+ logFileWriter = state.getLogger().getCurrentFileWriter();
+ break;
+ default:
+ dfAssert(false, "All branch should be covered");
}
// Append content to the appropriate log file
@@ -200,11 +199,11 @@ public static String cleanResultSetString(String value) {
}
switch (value) {
- case "-0.0":
- return "0.0";
- case "-0":
- return "0";
- default:
+ case "-0.0":
+ return "0.0";
+ case "-0":
+ return "0";
+ default:
}
if (value.getBytes().length > 7) {
diff --git a/src/sqlancer/datafusion/ast/DataFusionSelect.java b/src/sqlancer/datafusion/ast/DataFusionSelect.java
index a0148e8f..d91b59cc 100644
--- a/src/sqlancer/datafusion/ast/DataFusionSelect.java
+++ b/src/sqlancer/datafusion/ast/DataFusionSelect.java
@@ -27,6 +27,10 @@ public class DataFusionSelect extends SelectBase> imp
// `from` is used to represent from table list and join clause
// `fromList` and `joinList` in base class should always be empty
public DataFusionFrom from;
+ // Randomly selected table (equivalent to `from.tableList`)
+ // Can be refactored, it's a hack for now
+ public List tableList;
+
// e.g. let's say all colummns are {c1, c2, c3, c4, c5}
// First randomly pick a subset say {c2, c1, c3, c4}
// `exprGenAll` can generate random expr using above 4 columns
@@ -63,16 +67,22 @@ public enum JoinType {
// - joinTypeList -> {INNER, LEFT}
// - joinConditionList -> {[expr_with_t1_t2], [expr_with_t1_t2_t3]}
public static class DataFusionFrom implements Node {
- public List> tableList;
+ public List> tableExprList;
public List joinTypeList;
public List> joinConditionList;
public DataFusionFrom() {
- tableList = new ArrayList<>();
+ tableExprList = new ArrayList<>();
joinTypeList = new ArrayList<>();
joinConditionList = new ArrayList<>();
}
+ public DataFusionFrom(List tables) {
+ this();
+ tableExprList = tables.stream().map(t -> new TableReferenceNode(t))
+ .map(tableExpr -> new DataFusionAliasedTable(tableExpr)).collect(Collectors.toList());
+ }
+
public boolean isExplicitJoin() {
// if it's explicit join, joinTypeList and joinConditionList should be both
// length of tableList.len - 1
@@ -93,7 +103,7 @@ public static DataFusionFrom generateFromClause(DataFusionGlobalState state,
List> randomTableNodes = randomTables.stream()
.map(t -> new TableReferenceNode(t))
.collect(Collectors.toList());
- fromClause.tableList = randomTableNodes;
+ fromClause.tableExprList = randomTableNodes;
/* If JoinConditionList is empty, FromClause will be interpreted as from list */
if (Randomly.getBoolean() && Randomly.getBoolean()) {
@@ -149,10 +159,12 @@ public static DataFusionFrom generateFromClause(DataFusionGlobalState state,
}
public void setupAlias() {
- for (int i = 0; i < tableList.size(); i++) {
- if (tableList.get(i) instanceof TableReferenceNode) {
- ((TableReferenceNode) tableList.get(i))
- .getTable().alias = Optional.of("tt" + i);
+ for (int i = 0; i < tableExprList.size(); i++) {
+ if (tableExprList.get(i) instanceof TableReferenceNode) {
+ @SuppressWarnings("unchecked") // Suppress the unchecked cast warning
+ TableReferenceNode node = (TableReferenceNode) tableExprList
+ .get(i);
+ node.getTable().alias = Optional.of("tt" + i);
} else {
dfAssert(false, "Expected all items in tableList to be TableReferenceNode instances");
}
@@ -160,10 +172,10 @@ public void setupAlias() {
// wrap table in `DataFusionAlias` for display
List> wrappedTables = new ArrayList<>();
- for (Node table : tableList) {
- wrappedTables.add(new DataFusionAlias(table));
+ for (Node table : tableExprList) {
+ wrappedTables.add(new DataFusionAliasedTable(table));
}
- tableList = wrappedTables;
+ tableExprList = wrappedTables;
}
}
@@ -173,24 +185,18 @@ public void setupAlias() {
// The randomly mutated query looks like:
// select * from t1_csv, t2, t3_parquet
public void mutateEquivalentTableName() {
- for (Node table : from.tableList) {
- if (table instanceof DataFusionAlias) {
- Node aliasedTable = ((DataFusionAlias) table).table;
+ for (Node table : from.tableExprList) {
+ if (table instanceof DataFusionAliasedTable) {
+ Node aliasedTable = ((DataFusionAliasedTable) table).table;
if (aliasedTable instanceof TableReferenceNode) {
- ((TableReferenceNode) aliasedTable).getTable()
- .pickAnotherEquivalentTableName();
+ @SuppressWarnings("unchecked") // Suppress the unchecked cast warning
+ TableReferenceNode tableRef = (TableReferenceNode) aliasedTable;
+ tableRef.getTable().pickAnotherEquivalentTableName();
} else {
dfAssert(false, "Expected all items in tableList to be TableReferenceNode instances");
}
} else {
- // I want to print the exact type of table
- System.out.println("DBG mutateEquivalentTableName: " + table.getClass().getName());
- try {
- throw new RuntimeException("DBG mutateEquivalentTableName");
- } catch (RuntimeException e) {
- e.printStackTrace();
- }
dfAssert(false, "Expected all items in tableList to be TableReferenceNode instances");
}
}
@@ -203,11 +209,12 @@ public void mutateEquivalentTableName() {
// and print it as 't1 as tt1'
// If the same table is in expressions, don't use the wrapper and print it as
// 'tt1'
- public static class DataFusionAlias implements Node {
+ public static class DataFusionAliasedTable implements Node {
public Node table;
- public DataFusionAlias(Node table) {
+ public DataFusionAliasedTable(Node table) {
dfAssert(table instanceof TableReferenceNode, "Expected table reference node");
+ @SuppressWarnings("unchecked") // Suppress the unchecked cast warning
DataFusionTable t = ((TableReferenceNode) table).getTable();
dfAssert(t.alias.isPresent(), "Expected table to have alias");
@@ -254,6 +261,7 @@ public static DataFusionSelect getRandomSelect(DataFusionGlobalState state) {
randomTables = randomTables.subList(0, maxSize);
}
DataFusionFrom randomFrom = DataFusionFrom.generateFromClause(state, randomTables);
+ randomSelect.tableList = randomTables;
/* Setup expression generators (to generate different clauses) */
List randomColumnsAll = DataFusionTable.getRandomColumns(randomTables);
@@ -272,19 +280,15 @@ public static DataFusionSelect getRandomSelect(DataFusionGlobalState state) {
.generateExpression(DataFusionSchema.DataFusionDataType.BOOLEAN);
/* Constructing result */
- List> randomColumnNodes = randomColumnsAll.stream()
- .map((c) -> {
- if (c.getType() == DataFusionSchema.DataFusionDataType.STRING) {
- Node colRef = new ColumnReferenceNode(
- c);
- Node castedColRef = new DataFusionSpecialExpr.CastToStringView(colRef);
-
- return castedColRef;
- } else {
- return new ColumnReferenceNode(c);
- }
- })
- .collect(Collectors.toList());
+ List> randomColumnNodes = randomColumnsAll.stream().map((c) -> {
+ if (c.getType() == DataFusionSchema.DataFusionDataType.STRING) {
+ Node colRef = new ColumnReferenceNode(c);
+ return new DataFusionSpecialExpr.CastToStringView(colRef);
+
+ } else {
+ return new ColumnReferenceNode(c);
+ }
+ }).collect(Collectors.toList());
randomSelect.setFetchColumns(randomColumnNodes); // TODO(datafusion) make it more random like 'select *'
randomSelect.from = randomFrom;
@@ -335,12 +339,10 @@ public void setAggregates(DataFusionGlobalState state) {
}
/*
- * If set fetch columns with string It will override `fetchColumns` in base
- * class when
+ * If set fetch columns with string It will override `fetchColumns` in base class when
* `DataFusionToStringVisitor.asString()` is called
*
- * This method can be helpful to mutate select in oracle checks: SELECT [expr]
- * ... -> SELECT SUM[expr]
+ * This method can be helpful to mutate select in oracle checks: SELECT [expr] ... -> SELECT SUM[expr]
*/
public void setFetchColumnsString(String selectExpr) {
this.fetchColumnsString = Optional.of(selectExpr);
diff --git a/src/sqlancer/datafusion/gen/DataFusionExpressionGenerator.java b/src/sqlancer/datafusion/gen/DataFusionExpressionGenerator.java
index 3754a826..c19ad00d 100644
--- a/src/sqlancer/datafusion/gen/DataFusionExpressionGenerator.java
+++ b/src/sqlancer/datafusion/gen/DataFusionExpressionGenerator.java
@@ -55,7 +55,8 @@ protected boolean canGenerateColumnOfType(DataFusionDataType type) {
return true;
}
- // If target expr type is numeric, when `supportAggregate`, make it more likely to generate aggregate functions
+ // If target expr type is numeric, when `supportAggregate`, make it more likely
+ // to generate aggregate functions
// Since randomly generated expressions are nested:
// For window/aggregate case, we want only outer layer to be window/aggr
// to make it more likely to generate valid query
@@ -82,7 +83,8 @@ private boolean filterBaseExpr(DataFusionBaseExpr expr, DataFusionDataType type,
}
// By default all possible non-aggregate expressions
- // To generate aggregate functions: set this.supportAggregate to `true`, generate exprs, and reset.
+ // To generate aggregate functions: set this.supportAggregate to `true`,
+ // generate exprs, and reset.
@Override
protected Node generateExpression(DataFusionDataType type, int depth) {
if (depth >= globalState.getOptions().getMaxExpressionDepth() || Randomly.getBoolean()) {
@@ -103,7 +105,8 @@ protected Node generateExpression(DataFusionDataType type,
DataFusionBaseExpr randomExpr = Randomly.fromList(possibleBaseExprs);
- // if (randomExpr.exprType == DataFusionBaseExprCategory.AGGREGATE || randomExpr.exprType ==
+ // if (randomExpr.exprType == DataFusionBaseExprCategory.AGGREGATE ||
+ // randomExpr.exprType ==
// DataFusionBaseExprCategory.WINDOW) {
// if (depth == 0) {
// System.out.println("DBG depth 0");
@@ -143,7 +146,8 @@ protected Node generateExpression(DataFusionDataType type,
case BINARY:
dfAssert(randomExpr.argTypes.size() == 2 && randomExpr.nArgs == 2,
"Binrary expression should only have 2 argument" + randomExpr.argTypes);
- List argTypeList = new ArrayList<>(); // types of current expression's input arguments
+ List argTypeList = new ArrayList<>(); // types of current expression's input
+ // arguments
for (ArgumentType argumentType : randomExpr.argTypes) {
if (argumentType instanceof ArgumentType.Fixed) {
ArgumentType.Fixed possibleArgTypes = (ArgumentType.Fixed) randomExpr.argTypes.get(0);
@@ -333,13 +337,15 @@ public Node isNull(Node expr) {
return new NewUnaryPostfixOperatorNode<>(expr, createExpr(DataFusionBaseExprType.IS_NULL));
}
- // TODO(datafusion) refactor: make single generate aware of group by and aggr columns, and it can directly generate
+ // TODO(datafusion) refactor: make single generate aware of group by and aggr
+ // columns, and it can directly generate
// having clause
// Try best to generate a valid having clause
//
// Suppose query "... group by a, b ..."
// and all available columns are "a, b, c, d"
- // then a valid having clause can have expr of {a, b}, and expr of aggregation of {c, d}
+ // then a valid having clause can have expr of {a, b}, and expr of aggregation
+ // of {c, d}
// e.g. "having a=b and avg(c) > avg(d)"
//
// `groupbyGen` can generate expression only with group by cols
diff --git a/src/sqlancer/datafusion/gen/DataFusionTableGenerator.java b/src/sqlancer/datafusion/gen/DataFusionTableGenerator.java
index 37b71fff..e1acddcf 100644
--- a/src/sqlancer/datafusion/gen/DataFusionTableGenerator.java
+++ b/src/sqlancer/datafusion/gen/DataFusionTableGenerator.java
@@ -1,13 +1,14 @@
package sqlancer.datafusion.gen;
import java.util.Optional;
+
import sqlancer.Randomly;
import sqlancer.common.query.ExpectedErrors;
import sqlancer.common.query.SQLQueryAdapter;
import sqlancer.datafusion.DataFusionProvider.DataFusionGlobalState;
+import sqlancer.datafusion.DataFusionSchema.DataFusionColumn;
import sqlancer.datafusion.DataFusionSchema.DataFusionDataType;
import sqlancer.datafusion.DataFusionSchema.DataFusionTable;
-import sqlancer.datafusion.DataFusionSchema.DataFusionColumn;
public class DataFusionTableGenerator {
diff --git a/src/sqlancer/datafusion/server/datafusion_server/Cargo.lock b/src/sqlancer/datafusion/server/datafusion_server/Cargo.lock
new file mode 100644
index 00000000..2d7286df
--- /dev/null
+++ b/src/sqlancer/datafusion/server/datafusion_server/Cargo.lock
@@ -0,0 +1,3366 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+version = 3
+
+[[package]]
+name = "addr2line"
+version = "0.22.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6e4503c46a5c0c7844e948c9a4d6acd9f50cccb4de1c48eb9e291ea17470c678"
+dependencies = [
+ "gimli",
+]
+
+[[package]]
+name = "adler"
+version = "1.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
+
+[[package]]
+name = "adler2"
+version = "2.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627"
+
+[[package]]
+name = "ahash"
+version = "0.8.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011"
+dependencies = [
+ "cfg-if",
+ "const-random",
+ "getrandom",
+ "once_cell",
+ "version_check",
+ "zerocopy",
+]
+
+[[package]]
+name = "aho-corasick"
+version = "1.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916"
+dependencies = [
+ "memchr",
+]
+
+[[package]]
+name = "alloc-no-stdlib"
+version = "2.0.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cc7bb162ec39d46ab1ca8c77bf72e890535becd1751bb45f64c597edb4c8c6b3"
+
+[[package]]
+name = "alloc-stdlib"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "94fb8275041c72129eb51b7d0322c29b8387a0386127718b096429201a5d6ece"
+dependencies = [
+ "alloc-no-stdlib",
+]
+
+[[package]]
+name = "allocator-api2"
+version = "0.2.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f"
+
+[[package]]
+name = "android-tzdata"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0"
+
+[[package]]
+name = "android_system_properties"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311"
+dependencies = [
+ "libc",
+]
+
+[[package]]
+name = "anstream"
+version = "0.6.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "64e15c1ab1f89faffbf04a634d5e1962e9074f2741eef6d97f3c4e322426d526"
+dependencies = [
+ "anstyle",
+ "anstyle-parse",
+ "anstyle-query",
+ "anstyle-wincon",
+ "colorchoice",
+ "is_terminal_polyfill",
+ "utf8parse",
+]
+
+[[package]]
+name = "anstyle"
+version = "1.0.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1bec1de6f59aedf83baf9ff929c98f2ad654b97c9510f4e70cf6f661d49fd5b1"
+
+[[package]]
+name = "anstyle-parse"
+version = "0.2.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "eb47de1e80c2b463c735db5b217a0ddc39d612e7ac9e2e96a5aed1f57616c1cb"
+dependencies = [
+ "utf8parse",
+]
+
+[[package]]
+name = "anstyle-query"
+version = "1.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6d36fc52c7f6c869915e99412912f22093507da8d9e942ceaf66fe4b7c14422a"
+dependencies = [
+ "windows-sys 0.52.0",
+]
+
+[[package]]
+name = "anstyle-wincon"
+version = "3.0.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5bf74e1b6e971609db8ca7a9ce79fd5768ab6ae46441c572e46cf596f59e57f8"
+dependencies = [
+ "anstyle",
+ "windows-sys 0.52.0",
+]
+
+[[package]]
+name = "anyhow"
+version = "1.0.86"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da"
+
+[[package]]
+name = "arrayref"
+version = "0.3.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9d151e35f61089500b617991b791fc8bfd237ae50cd5950803758a179b41e67a"
+
+[[package]]
+name = "arrayvec"
+version = "0.7.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50"
+
+[[package]]
+name = "arrow"
+version = "53.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "45aef0d9cf9a039bf6cd1acc451b137aca819977b0928dece52bd92811b640ba"
+dependencies = [
+ "arrow-arith",
+ "arrow-array 53.0.0",
+ "arrow-buffer 53.0.0",
+ "arrow-cast 53.0.0",
+ "arrow-csv",
+ "arrow-data 53.0.0",
+ "arrow-ipc 53.0.0",
+ "arrow-json",
+ "arrow-ord",
+ "arrow-row",
+ "arrow-schema 53.0.0",
+ "arrow-select 53.0.0",
+ "arrow-string",
+]
+
+[[package]]
+name = "arrow-arith"
+version = "53.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "03675e42d1560790f3524800e41403b40d0da1c793fe9528929fde06d8c7649a"
+dependencies = [
+ "arrow-array 53.0.0",
+ "arrow-buffer 53.0.0",
+ "arrow-data 53.0.0",
+ "arrow-schema 53.0.0",
+ "chrono",
+ "half",
+ "num",
+]
+
+[[package]]
+name = "arrow-array"
+version = "52.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "16f4a9468c882dc66862cef4e1fd8423d47e67972377d85d80e022786427768c"
+dependencies = [
+ "ahash",
+ "arrow-buffer 52.2.0",
+ "arrow-data 52.2.0",
+ "arrow-schema 52.2.0",
+ "chrono",
+ "half",
+ "hashbrown 0.14.5",
+ "num",
+]
+
+[[package]]
+name = "arrow-array"
+version = "53.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cd2bf348cf9f02a5975c5962c7fa6dee107a2009a7b41ac5fb1a027e12dc033f"
+dependencies = [
+ "ahash",
+ "arrow-buffer 53.0.0",
+ "arrow-data 53.0.0",
+ "arrow-schema 53.0.0",
+ "chrono",
+ "chrono-tz",
+ "half",
+ "hashbrown 0.14.5",
+ "num",
+]
+
+[[package]]
+name = "arrow-buffer"
+version = "52.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c975484888fc95ec4a632cdc98be39c085b1bb518531b0c80c5d462063e5daa1"
+dependencies = [
+ "bytes",
+ "half",
+ "num",
+]
+
+[[package]]
+name = "arrow-buffer"
+version = "53.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3092e37715f168976012ce52273c3989b5793b0db5f06cbaa246be25e5f0924d"
+dependencies = [
+ "bytes",
+ "half",
+ "num",
+]
+
+[[package]]
+name = "arrow-cast"
+version = "52.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "da26719e76b81d8bc3faad1d4dbdc1bcc10d14704e63dc17fc9f3e7e1e567c8e"
+dependencies = [
+ "arrow-array 52.2.0",
+ "arrow-buffer 52.2.0",
+ "arrow-data 52.2.0",
+ "arrow-schema 52.2.0",
+ "arrow-select 52.2.0",
+ "atoi",
+ "base64",
+ "chrono",
+ "half",
+ "lexical-core",
+ "num",
+ "ryu",
+]
+
+[[package]]
+name = "arrow-cast"
+version = "53.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7ce1018bb710d502f9db06af026ed3561552e493e989a79d0d0f5d9cf267a785"
+dependencies = [
+ "arrow-array 53.0.0",
+ "arrow-buffer 53.0.0",
+ "arrow-data 53.0.0",
+ "arrow-schema 53.0.0",
+ "arrow-select 53.0.0",
+ "atoi",
+ "base64",
+ "chrono",
+ "comfy-table",
+ "half",
+ "lexical-core",
+ "num",
+ "ryu",
+]
+
+[[package]]
+name = "arrow-csv"
+version = "53.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fd178575f45624d045e4ebee714e246a05d9652e41363ee3f57ec18cca97f740"
+dependencies = [
+ "arrow-array 53.0.0",
+ "arrow-buffer 53.0.0",
+ "arrow-cast 53.0.0",
+ "arrow-data 53.0.0",
+ "arrow-schema 53.0.0",
+ "chrono",
+ "csv",
+ "csv-core",
+ "lazy_static",
+ "lexical-core",
+ "regex",
+]
+
+[[package]]
+name = "arrow-data"
+version = "52.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dd9d6f18c65ef7a2573ab498c374d8ae364b4a4edf67105357491c031f716ca5"
+dependencies = [
+ "arrow-buffer 52.2.0",
+ "arrow-schema 52.2.0",
+ "half",
+ "num",
+]
+
+[[package]]
+name = "arrow-data"
+version = "53.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4e4ac0c4ee79150afe067dc4857154b3ee9c1cd52b5f40d59a77306d0ed18d65"
+dependencies = [
+ "arrow-buffer 53.0.0",
+ "arrow-schema 53.0.0",
+ "half",
+ "num",
+]
+
+[[package]]
+name = "arrow-flight"
+version = "53.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b915fb36d935b969894d7909ad417c67ddeadebbbd57c3c168edf64721a37d31"
+dependencies = [
+ "arrow-arith",
+ "arrow-array 53.0.0",
+ "arrow-buffer 53.0.0",
+ "arrow-cast 53.0.0",
+ "arrow-data 53.0.0",
+ "arrow-ipc 53.0.0",
+ "arrow-ord",
+ "arrow-row",
+ "arrow-schema 53.0.0",
+ "arrow-select 53.0.0",
+ "arrow-string",
+ "base64",
+ "bytes",
+ "futures",
+ "once_cell",
+ "paste",
+ "prost",
+ "prost-types",
+ "tokio",
+ "tonic",
+]
+
+[[package]]
+name = "arrow-ipc"
+version = "52.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e786e1cdd952205d9a8afc69397b317cfbb6e0095e445c69cda7e8da5c1eeb0f"
+dependencies = [
+ "arrow-array 52.2.0",
+ "arrow-buffer 52.2.0",
+ "arrow-cast 52.2.0",
+ "arrow-data 52.2.0",
+ "arrow-schema 52.2.0",
+ "flatbuffers",
+]
+
+[[package]]
+name = "arrow-ipc"
+version = "53.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bb307482348a1267f91b0912e962cd53440e5de0f7fb24c5f7b10da70b38c94a"
+dependencies = [
+ "arrow-array 53.0.0",
+ "arrow-buffer 53.0.0",
+ "arrow-cast 53.0.0",
+ "arrow-data 53.0.0",
+ "arrow-schema 53.0.0",
+ "flatbuffers",
+ "lz4_flex",
+]
+
+[[package]]
+name = "arrow-json"
+version = "53.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d24805ba326758effdd6f2cbdd482fcfab749544f21b134701add25b33f474e6"
+dependencies = [
+ "arrow-array 53.0.0",
+ "arrow-buffer 53.0.0",
+ "arrow-cast 53.0.0",
+ "arrow-data 53.0.0",
+ "arrow-schema 53.0.0",
+ "chrono",
+ "half",
+ "indexmap 2.4.0",
+ "lexical-core",
+ "num",
+ "serde",
+ "serde_json",
+]
+
+[[package]]
+name = "arrow-ord"
+version = "53.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "644046c479d80ae8ed02a7f1e1399072ea344ca6a7b0e293ab2d5d9ed924aa3b"
+dependencies = [
+ "arrow-array 53.0.0",
+ "arrow-buffer 53.0.0",
+ "arrow-data 53.0.0",
+ "arrow-schema 53.0.0",
+ "arrow-select 53.0.0",
+ "half",
+ "num",
+]
+
+[[package]]
+name = "arrow-row"
+version = "53.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a29791f8eb13b340ce35525b723f5f0df17ecb955599e11f65c2a94ab34e2efb"
+dependencies = [
+ "ahash",
+ "arrow-array 53.0.0",
+ "arrow-buffer 53.0.0",
+ "arrow-data 53.0.0",
+ "arrow-schema 53.0.0",
+ "half",
+]
+
+[[package]]
+name = "arrow-schema"
+version = "52.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9e972cd1ff4a4ccd22f86d3e53e835c2ed92e0eea6a3e8eadb72b4f1ac802cf8"
+
+[[package]]
+name = "arrow-schema"
+version = "53.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c85320a3a2facf2b2822b57aa9d6d9d55edb8aee0b6b5d3b8df158e503d10858"
+
+[[package]]
+name = "arrow-select"
+version = "52.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "600bae05d43483d216fb3494f8c32fdbefd8aa4e1de237e790dbb3d9f44690a3"
+dependencies = [
+ "ahash",
+ "arrow-array 52.2.0",
+ "arrow-buffer 52.2.0",
+ "arrow-data 52.2.0",
+ "arrow-schema 52.2.0",
+ "num",
+]
+
+[[package]]
+name = "arrow-select"
+version = "53.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9cc7e6b582e23855fd1625ce46e51647aa440c20ea2e71b1d748e0839dd73cba"
+dependencies = [
+ "ahash",
+ "arrow-array 53.0.0",
+ "arrow-buffer 53.0.0",
+ "arrow-data 53.0.0",
+ "arrow-schema 53.0.0",
+ "num",
+]
+
+[[package]]
+name = "arrow-string"
+version = "53.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0775b6567c66e56ded19b87a954b6b1beffbdd784ef95a3a2b03f59570c1d230"
+dependencies = [
+ "arrow-array 53.0.0",
+ "arrow-buffer 53.0.0",
+ "arrow-data 53.0.0",
+ "arrow-schema 53.0.0",
+ "arrow-select 53.0.0",
+ "memchr",
+ "num",
+ "regex",
+ "regex-syntax",
+]
+
+[[package]]
+name = "async-compression"
+version = "0.4.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fec134f64e2bc57411226dfc4e52dec859ddfc7e711fc5e07b612584f000e4aa"
+dependencies = [
+ "bzip2",
+ "flate2",
+ "futures-core",
+ "futures-io",
+ "memchr",
+ "pin-project-lite",
+ "tokio",
+ "xz2",
+ "zstd",
+ "zstd-safe",
+]
+
+[[package]]
+name = "async-stream"
+version = "0.3.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cd56dd203fef61ac097dd65721a419ddccb106b2d2b70ba60a6b529f03961a51"
+dependencies = [
+ "async-stream-impl",
+ "futures-core",
+ "pin-project-lite",
+]
+
+[[package]]
+name = "async-stream-impl"
+version = "0.3.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.75",
+]
+
+[[package]]
+name = "async-trait"
+version = "0.1.81"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6e0c28dcc82d7c8ead5cb13beb15405b57b8546e93215673ff8ca0349a028107"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.75",
+]
+
+[[package]]
+name = "atoi"
+version = "2.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f28d99ec8bfea296261ca1af174f24225171fea9664ba9003cbebee704810528"
+dependencies = [
+ "num-traits",
+]
+
+[[package]]
+name = "atomic-waker"
+version = "1.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0"
+
+[[package]]
+name = "autocfg"
+version = "1.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0"
+
+[[package]]
+name = "axum"
+version = "0.7.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3a6c9af12842a67734c9a2e355436e5d03b22383ed60cf13cd0c18fbfe3dcbcf"
+dependencies = [
+ "async-trait",
+ "axum-core",
+ "bytes",
+ "futures-util",
+ "http",
+ "http-body",
+ "http-body-util",
+ "itoa",
+ "matchit",
+ "memchr",
+ "mime",
+ "percent-encoding",
+ "pin-project-lite",
+ "rustversion",
+ "serde",
+ "sync_wrapper 1.0.1",
+ "tower",
+ "tower-layer",
+ "tower-service",
+]
+
+[[package]]
+name = "axum-core"
+version = "0.4.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a15c63fd72d41492dc4f497196f5da1fb04fb7529e631d73630d1b491e47a2e3"
+dependencies = [
+ "async-trait",
+ "bytes",
+ "futures-util",
+ "http",
+ "http-body",
+ "http-body-util",
+ "mime",
+ "pin-project-lite",
+ "rustversion",
+ "sync_wrapper 0.1.2",
+ "tower-layer",
+ "tower-service",
+]
+
+[[package]]
+name = "backtrace"
+version = "0.3.73"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5cc23269a4f8976d0a4d2e7109211a419fe30e8d88d677cd60b6bc79c5732e0a"
+dependencies = [
+ "addr2line",
+ "cc",
+ "cfg-if",
+ "libc",
+ "miniz_oxide 0.7.4",
+ "object",
+ "rustc-demangle",
+]
+
+[[package]]
+name = "base64"
+version = "0.22.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6"
+
+[[package]]
+name = "bitflags"
+version = "1.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
+
+[[package]]
+name = "bitflags"
+version = "2.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de"
+
+[[package]]
+name = "blake2"
+version = "0.10.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "46502ad458c9a52b69d4d4d32775c788b7a1b85e8bc9d482d92250fc0e3f8efe"
+dependencies = [
+ "digest",
+]
+
+[[package]]
+name = "blake3"
+version = "1.5.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d82033247fd8e890df8f740e407ad4d038debb9eb1f40533fffb32e7d17dc6f7"
+dependencies = [
+ "arrayref",
+ "arrayvec",
+ "cc",
+ "cfg-if",
+ "constant_time_eq",
+]
+
+[[package]]
+name = "block-buffer"
+version = "0.10.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71"
+dependencies = [
+ "generic-array",
+]
+
+[[package]]
+name = "brotli"
+version = "6.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "74f7971dbd9326d58187408ab83117d8ac1bb9c17b085fdacd1cf2f598719b6b"
+dependencies = [
+ "alloc-no-stdlib",
+ "alloc-stdlib",
+ "brotli-decompressor",
+]
+
+[[package]]
+name = "brotli-decompressor"
+version = "4.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9a45bd2e4095a8b518033b128020dd4a55aab1c0a381ba4404a472630f4bc362"
+dependencies = [
+ "alloc-no-stdlib",
+ "alloc-stdlib",
+]
+
+[[package]]
+name = "bumpalo"
+version = "3.16.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c"
+
+[[package]]
+name = "byteorder"
+version = "1.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
+
+[[package]]
+name = "bytes"
+version = "1.7.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8318a53db07bb3f8dca91a600466bdb3f2eaadeedfdbcf02e1accbad9271ba50"
+
+[[package]]
+name = "bzip2"
+version = "0.4.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bdb116a6ef3f6c3698828873ad02c3014b3c85cadb88496095628e3ef1e347f8"
+dependencies = [
+ "bzip2-sys",
+ "libc",
+]
+
+[[package]]
+name = "bzip2-sys"
+version = "0.1.11+1.0.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "736a955f3fa7875102d57c82b8cac37ec45224a07fd32d58f9f7a186b6cd4cdc"
+dependencies = [
+ "cc",
+ "libc",
+ "pkg-config",
+]
+
+[[package]]
+name = "cc"
+version = "1.1.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "50d2eb3cd3d1bf4529e31c215ee6f93ec5a3d536d9f578f93d9d33ee19562932"
+dependencies = [
+ "jobserver",
+ "libc",
+ "shlex",
+]
+
+[[package]]
+name = "cfg-if"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
+
+[[package]]
+name = "chrono"
+version = "0.4.38"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401"
+dependencies = [
+ "android-tzdata",
+ "iana-time-zone",
+ "num-traits",
+ "windows-targets",
+]
+
+[[package]]
+name = "chrono-tz"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "93698b29de5e97ad0ae26447b344c482a7284c737d9ddc5f9e52b74a336671bb"
+dependencies = [
+ "chrono",
+ "chrono-tz-build",
+ "phf",
+]
+
+[[package]]
+name = "chrono-tz-build"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0c088aee841df9c3041febbb73934cfc39708749bf96dc827e3359cd39ef11b1"
+dependencies = [
+ "parse-zoneinfo",
+ "phf",
+ "phf_codegen",
+]
+
+[[package]]
+name = "colorchoice"
+version = "1.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d3fd119d74b830634cea2a0f58bbd0d54540518a14397557951e79340abc28c0"
+
+[[package]]
+name = "comfy-table"
+version = "7.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b34115915337defe99b2aff5c2ce6771e5fbc4079f4b506301f5cf394c8452f7"
+dependencies = [
+ "strum",
+ "strum_macros",
+ "unicode-width",
+]
+
+[[package]]
+name = "const-random"
+version = "0.1.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "87e00182fe74b066627d63b85fd550ac2998d4b0bd86bfed477a0ae4c7c71359"
+dependencies = [
+ "const-random-macro",
+]
+
+[[package]]
+name = "const-random-macro"
+version = "0.1.16"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f9d839f2a20b0aee515dc581a6172f2321f96cab76c1a38a4c584a194955390e"
+dependencies = [
+ "getrandom",
+ "once_cell",
+ "tiny-keccak",
+]
+
+[[package]]
+name = "constant_time_eq"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f7144d30dcf0fafbce74250a3963025d8d52177934239851c917d29f1df280c2"
+
+[[package]]
+name = "core-foundation-sys"
+version = "0.8.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b"
+
+[[package]]
+name = "cpufeatures"
+version = "0.2.13"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "51e852e6dc9a5bed1fae92dd2375037bf2b768725bf3be87811edee3249d09ad"
+dependencies = [
+ "libc",
+]
+
+[[package]]
+name = "crc32fast"
+version = "1.4.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3"
+dependencies = [
+ "cfg-if",
+]
+
+[[package]]
+name = "crossbeam-utils"
+version = "0.8.20"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80"
+
+[[package]]
+name = "crunchy"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7"
+
+[[package]]
+name = "crypto-common"
+version = "0.1.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3"
+dependencies = [
+ "generic-array",
+ "typenum",
+]
+
+[[package]]
+name = "csv"
+version = "1.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ac574ff4d437a7b5ad237ef331c17ccca63c46479e5b5453eb8e10bb99a759fe"
+dependencies = [
+ "csv-core",
+ "itoa",
+ "ryu",
+ "serde",
+]
+
+[[package]]
+name = "csv-core"
+version = "0.1.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5efa2b3d7902f4b634a20cae3c9c4e6209dc4779feb6863329607560143efa70"
+dependencies = [
+ "memchr",
+]
+
+[[package]]
+name = "dashmap"
+version = "5.5.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "978747c1d849a7d2ee5e8adc0159961c48fb7e5db2f06af6723b80123bb53856"
+dependencies = [
+ "cfg-if",
+ "hashbrown 0.14.5",
+ "lock_api",
+ "once_cell",
+ "parking_lot_core",
+]
+
+[[package]]
+name = "dashmap"
+version = "6.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "804c8821570c3f8b70230c2ba75ffa5c0f9a4189b9a432b6656c536712acae28"
+dependencies = [
+ "cfg-if",
+ "crossbeam-utils",
+ "hashbrown 0.14.5",
+ "lock_api",
+ "once_cell",
+ "parking_lot_core",
+]
+
+[[package]]
+name = "datafusion"
+version = "42.0.0"
+source = "git+https://github.com/apache/datafusion.git?branch=main#6f8c74ca873fe015b2e7ff4eeb2f76bf21ae9d0e"
+dependencies = [
+ "ahash",
+ "arrow",
+ "arrow-array 53.0.0",
+ "arrow-ipc 53.0.0",
+ "arrow-schema 53.0.0",
+ "async-compression",
+ "async-trait",
+ "bytes",
+ "bzip2",
+ "chrono",
+ "dashmap 6.0.1",
+ "datafusion-catalog",
+ "datafusion-common",
+ "datafusion-common-runtime",
+ "datafusion-execution",
+ "datafusion-expr",
+ "datafusion-functions",
+ "datafusion-functions-aggregate",
+ "datafusion-functions-nested",
+ "datafusion-functions-window",
+ "datafusion-optimizer",
+ "datafusion-physical-expr",
+ "datafusion-physical-expr-common",
+ "datafusion-physical-optimizer",
+ "datafusion-physical-plan",
+ "datafusion-sql",
+ "flate2",
+ "futures",
+ "glob",
+ "half",
+ "hashbrown 0.14.5",
+ "indexmap 2.4.0",
+ "itertools 0.13.0",
+ "log",
+ "num_cpus",
+ "object_store 0.11.0",
+ "parking_lot",
+ "parquet 53.0.0",
+ "paste",
+ "pin-project-lite",
+ "rand",
+ "sqlparser",
+ "tempfile",
+ "tokio",
+ "tokio-util",
+ "url",
+ "uuid",
+ "xz2",
+ "zstd",
+]
+
+[[package]]
+name = "datafusion-catalog"
+version = "42.0.0"
+source = "git+https://github.com/apache/datafusion.git?branch=main#6f8c74ca873fe015b2e7ff4eeb2f76bf21ae9d0e"
+dependencies = [
+ "arrow-schema 53.0.0",
+ "async-trait",
+ "datafusion-common",
+ "datafusion-execution",
+ "datafusion-expr",
+ "datafusion-physical-plan",
+ "parking_lot",
+]
+
+[[package]]
+name = "datafusion-common"
+version = "42.0.0"
+source = "git+https://github.com/apache/datafusion.git?branch=main#6f8c74ca873fe015b2e7ff4eeb2f76bf21ae9d0e"
+dependencies = [
+ "ahash",
+ "arrow",
+ "arrow-array 53.0.0",
+ "arrow-buffer 53.0.0",
+ "arrow-schema 53.0.0",
+ "chrono",
+ "half",
+ "hashbrown 0.14.5",
+ "instant",
+ "libc",
+ "num_cpus",
+ "object_store 0.11.0",
+ "parquet 53.0.0",
+ "paste",
+ "sqlparser",
+ "tokio",
+]
+
+[[package]]
+name = "datafusion-common-runtime"
+version = "42.0.0"
+source = "git+https://github.com/apache/datafusion.git?branch=main#6f8c74ca873fe015b2e7ff4eeb2f76bf21ae9d0e"
+dependencies = [
+ "log",
+ "tokio",
+]
+
+[[package]]
+name = "datafusion-execution"
+version = "42.0.0"
+source = "git+https://github.com/apache/datafusion.git?branch=main#6f8c74ca873fe015b2e7ff4eeb2f76bf21ae9d0e"
+dependencies = [
+ "arrow",
+ "chrono",
+ "dashmap 6.0.1",
+ "datafusion-common",
+ "datafusion-expr",
+ "futures",
+ "hashbrown 0.14.5",
+ "log",
+ "object_store 0.11.0",
+ "parking_lot",
+ "rand",
+ "tempfile",
+ "url",
+]
+
+[[package]]
+name = "datafusion-expr"
+version = "42.0.0"
+source = "git+https://github.com/apache/datafusion.git?branch=main#6f8c74ca873fe015b2e7ff4eeb2f76bf21ae9d0e"
+dependencies = [
+ "ahash",
+ "arrow",
+ "arrow-array 53.0.0",
+ "arrow-buffer 53.0.0",
+ "chrono",
+ "datafusion-common",
+ "datafusion-expr-common",
+ "datafusion-functions-aggregate-common",
+ "datafusion-functions-window-common",
+ "datafusion-physical-expr-common",
+ "indexmap 2.4.0",
+ "paste",
+ "serde_json",
+ "sqlparser",
+ "strum",
+ "strum_macros",
+]
+
+[[package]]
+name = "datafusion-expr-common"
+version = "42.0.0"
+source = "git+https://github.com/apache/datafusion.git?branch=main#6f8c74ca873fe015b2e7ff4eeb2f76bf21ae9d0e"
+dependencies = [
+ "arrow",
+ "datafusion-common",
+ "paste",
+]
+
+[[package]]
+name = "datafusion-functions"
+version = "42.0.0"
+source = "git+https://github.com/apache/datafusion.git?branch=main#6f8c74ca873fe015b2e7ff4eeb2f76bf21ae9d0e"
+dependencies = [
+ "arrow",
+ "arrow-buffer 53.0.0",
+ "base64",
+ "blake2",
+ "blake3",
+ "chrono",
+ "datafusion-common",
+ "datafusion-execution",
+ "datafusion-expr",
+ "hashbrown 0.14.5",
+ "hex",
+ "itertools 0.13.0",
+ "log",
+ "md-5",
+ "rand",
+ "regex",
+ "sha2",
+ "unicode-segmentation",
+ "uuid",
+]
+
+[[package]]
+name = "datafusion-functions-aggregate"
+version = "42.0.0"
+source = "git+https://github.com/apache/datafusion.git?branch=main#6f8c74ca873fe015b2e7ff4eeb2f76bf21ae9d0e"
+dependencies = [
+ "ahash",
+ "arrow",
+ "arrow-schema 53.0.0",
+ "datafusion-common",
+ "datafusion-execution",
+ "datafusion-expr",
+ "datafusion-functions-aggregate-common",
+ "datafusion-physical-expr",
+ "datafusion-physical-expr-common",
+ "half",
+ "indexmap 2.4.0",
+ "log",
+ "paste",
+]
+
+[[package]]
+name = "datafusion-functions-aggregate-common"
+version = "42.0.0"
+source = "git+https://github.com/apache/datafusion.git?branch=main#6f8c74ca873fe015b2e7ff4eeb2f76bf21ae9d0e"
+dependencies = [
+ "ahash",
+ "arrow",
+ "datafusion-common",
+ "datafusion-expr-common",
+ "datafusion-physical-expr-common",
+ "rand",
+]
+
+[[package]]
+name = "datafusion-functions-nested"
+version = "42.0.0"
+source = "git+https://github.com/apache/datafusion.git?branch=main#6f8c74ca873fe015b2e7ff4eeb2f76bf21ae9d0e"
+dependencies = [
+ "arrow",
+ "arrow-array 53.0.0",
+ "arrow-buffer 53.0.0",
+ "arrow-ord",
+ "arrow-schema 53.0.0",
+ "datafusion-common",
+ "datafusion-execution",
+ "datafusion-expr",
+ "datafusion-functions",
+ "datafusion-functions-aggregate",
+ "datafusion-physical-expr-common",
+ "itertools 0.13.0",
+ "log",
+ "paste",
+ "rand",
+]
+
+[[package]]
+name = "datafusion-functions-window"
+version = "42.0.0"
+source = "git+https://github.com/apache/datafusion.git?branch=main#6f8c74ca873fe015b2e7ff4eeb2f76bf21ae9d0e"
+dependencies = [
+ "datafusion-common",
+ "datafusion-expr",
+ "datafusion-functions-window-common",
+ "datafusion-physical-expr-common",
+ "log",
+ "paste",
+]
+
+[[package]]
+name = "datafusion-functions-window-common"
+version = "42.0.0"
+source = "git+https://github.com/apache/datafusion.git?branch=main#6f8c74ca873fe015b2e7ff4eeb2f76bf21ae9d0e"
+dependencies = [
+ "datafusion-common",
+]
+
+[[package]]
+name = "datafusion-optimizer"
+version = "42.0.0"
+source = "git+https://github.com/apache/datafusion.git?branch=main#6f8c74ca873fe015b2e7ff4eeb2f76bf21ae9d0e"
+dependencies = [
+ "arrow",
+ "async-trait",
+ "chrono",
+ "datafusion-common",
+ "datafusion-expr",
+ "datafusion-physical-expr",
+ "hashbrown 0.14.5",
+ "indexmap 2.4.0",
+ "itertools 0.13.0",
+ "log",
+ "paste",
+ "regex-syntax",
+]
+
+[[package]]
+name = "datafusion-physical-expr"
+version = "42.0.0"
+source = "git+https://github.com/apache/datafusion.git?branch=main#6f8c74ca873fe015b2e7ff4eeb2f76bf21ae9d0e"
+dependencies = [
+ "ahash",
+ "arrow",
+ "arrow-array 53.0.0",
+ "arrow-buffer 53.0.0",
+ "arrow-ord",
+ "arrow-schema 53.0.0",
+ "arrow-string",
+ "base64",
+ "chrono",
+ "datafusion-common",
+ "datafusion-execution",
+ "datafusion-expr",
+ "datafusion-expr-common",
+ "datafusion-functions-aggregate-common",
+ "datafusion-physical-expr-common",
+ "half",
+ "hashbrown 0.14.5",
+ "hex",
+ "indexmap 2.4.0",
+ "itertools 0.13.0",
+ "log",
+ "paste",
+ "petgraph",
+ "regex",
+]
+
+[[package]]
+name = "datafusion-physical-expr-common"
+version = "42.0.0"
+source = "git+https://github.com/apache/datafusion.git?branch=main#6f8c74ca873fe015b2e7ff4eeb2f76bf21ae9d0e"
+dependencies = [
+ "ahash",
+ "arrow",
+ "datafusion-common",
+ "datafusion-expr-common",
+ "hashbrown 0.14.5",
+ "rand",
+]
+
+[[package]]
+name = "datafusion-physical-optimizer"
+version = "42.0.0"
+source = "git+https://github.com/apache/datafusion.git?branch=main#6f8c74ca873fe015b2e7ff4eeb2f76bf21ae9d0e"
+dependencies = [
+ "arrow-schema 53.0.0",
+ "datafusion-common",
+ "datafusion-execution",
+ "datafusion-physical-expr",
+ "datafusion-physical-plan",
+ "itertools 0.13.0",
+]
+
+[[package]]
+name = "datafusion-physical-plan"
+version = "42.0.0"
+source = "git+https://github.com/apache/datafusion.git?branch=main#6f8c74ca873fe015b2e7ff4eeb2f76bf21ae9d0e"
+dependencies = [
+ "ahash",
+ "arrow",
+ "arrow-array 53.0.0",
+ "arrow-buffer 53.0.0",
+ "arrow-ord",
+ "arrow-schema 53.0.0",
+ "async-trait",
+ "chrono",
+ "datafusion-common",
+ "datafusion-common-runtime",
+ "datafusion-execution",
+ "datafusion-expr",
+ "datafusion-functions-aggregate",
+ "datafusion-functions-aggregate-common",
+ "datafusion-functions-window-common",
+ "datafusion-physical-expr",
+ "datafusion-physical-expr-common",
+ "futures",
+ "half",
+ "hashbrown 0.14.5",
+ "indexmap 2.4.0",
+ "itertools 0.13.0",
+ "log",
+ "once_cell",
+ "parking_lot",
+ "pin-project-lite",
+ "rand",
+ "tokio",
+]
+
+[[package]]
+name = "datafusion-server"
+version = "0.0.0"
+dependencies = [
+ "ahash",
+ "arrow",
+ "arrow-array 53.0.0",
+ "arrow-buffer 53.0.0",
+ "arrow-flight",
+ "arrow-ipc 53.0.0",
+ "arrow-ord",
+ "arrow-schema 53.0.0",
+ "arrow-string",
+ "async-trait",
+ "bytes",
+ "chrono",
+ "dashmap 5.5.3",
+ "datafusion",
+ "env_logger",
+ "futures",
+ "half",
+ "hashbrown 0.14.5",
+ "log",
+ "mimalloc",
+ "num_cpus",
+ "object_store 0.10.2",
+ "parking_lot",
+ "parquet 52.2.0",
+ "prost",
+ "prost-derive 0.12.6",
+ "rand",
+ "serde",
+ "serde_json",
+ "tokio",
+ "tonic",
+ "uuid",
+]
+
+[[package]]
+name = "datafusion-sql"
+version = "42.0.0"
+source = "git+https://github.com/apache/datafusion.git?branch=main#6f8c74ca873fe015b2e7ff4eeb2f76bf21ae9d0e"
+dependencies = [
+ "arrow",
+ "arrow-array 53.0.0",
+ "arrow-schema 53.0.0",
+ "datafusion-common",
+ "datafusion-expr",
+ "log",
+ "regex",
+ "sqlparser",
+ "strum",
+]
+
+[[package]]
+name = "digest"
+version = "0.10.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292"
+dependencies = [
+ "block-buffer",
+ "crypto-common",
+ "subtle",
+]
+
+[[package]]
+name = "doc-comment"
+version = "0.3.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10"
+
+[[package]]
+name = "either"
+version = "1.13.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0"
+
+[[package]]
+name = "env_filter"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4f2c92ceda6ceec50f43169f9ee8424fe2db276791afde7b2cd8bc084cb376ab"
+dependencies = [
+ "log",
+ "regex",
+]
+
+[[package]]
+name = "env_logger"
+version = "0.11.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e13fa619b91fb2381732789fc5de83b45675e882f66623b7d8cb4f643017018d"
+dependencies = [
+ "anstream",
+ "anstyle",
+ "env_filter",
+ "humantime",
+ "log",
+]
+
+[[package]]
+name = "equivalent"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
+
+[[package]]
+name = "errno"
+version = "0.3.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba"
+dependencies = [
+ "libc",
+ "windows-sys 0.52.0",
+]
+
+[[package]]
+name = "fastrand"
+version = "2.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9fc0510504f03c51ada170672ac806f1f105a88aa97a5281117e1ddc3368e51a"
+
+[[package]]
+name = "fixedbitset"
+version = "0.4.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80"
+
+[[package]]
+name = "flatbuffers"
+version = "24.3.25"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8add37afff2d4ffa83bc748a70b4b1370984f6980768554182424ef71447c35f"
+dependencies = [
+ "bitflags 1.3.2",
+ "rustc_version",
+]
+
+[[package]]
+name = "flate2"
+version = "1.0.32"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9c0596c1eac1f9e04ed902702e9878208b336edc9d6fddc8a48387349bab3666"
+dependencies = [
+ "crc32fast",
+ "miniz_oxide 0.8.0",
+]
+
+[[package]]
+name = "fnv"
+version = "1.0.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
+
+[[package]]
+name = "form_urlencoded"
+version = "1.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456"
+dependencies = [
+ "percent-encoding",
+]
+
+[[package]]
+name = "futures"
+version = "0.3.30"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0"
+dependencies = [
+ "futures-channel",
+ "futures-core",
+ "futures-executor",
+ "futures-io",
+ "futures-sink",
+ "futures-task",
+ "futures-util",
+]
+
+[[package]]
+name = "futures-channel"
+version = "0.3.30"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78"
+dependencies = [
+ "futures-core",
+ "futures-sink",
+]
+
+[[package]]
+name = "futures-core"
+version = "0.3.30"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d"
+
+[[package]]
+name = "futures-executor"
+version = "0.3.30"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d"
+dependencies = [
+ "futures-core",
+ "futures-task",
+ "futures-util",
+]
+
+[[package]]
+name = "futures-io"
+version = "0.3.30"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1"
+
+[[package]]
+name = "futures-macro"
+version = "0.3.30"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.75",
+]
+
+[[package]]
+name = "futures-sink"
+version = "0.3.30"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5"
+
+[[package]]
+name = "futures-task"
+version = "0.3.30"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004"
+
+[[package]]
+name = "futures-util"
+version = "0.3.30"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48"
+dependencies = [
+ "futures-channel",
+ "futures-core",
+ "futures-io",
+ "futures-macro",
+ "futures-sink",
+ "futures-task",
+ "memchr",
+ "pin-project-lite",
+ "pin-utils",
+ "slab",
+]
+
+[[package]]
+name = "generic-array"
+version = "0.14.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a"
+dependencies = [
+ "typenum",
+ "version_check",
+]
+
+[[package]]
+name = "getrandom"
+version = "0.2.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7"
+dependencies = [
+ "cfg-if",
+ "libc",
+ "wasi",
+]
+
+[[package]]
+name = "gimli"
+version = "0.29.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "40ecd4077b5ae9fd2e9e169b102c6c330d0605168eb0e8bf79952b256dbefffd"
+
+[[package]]
+name = "glob"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b"
+
+[[package]]
+name = "h2"
+version = "0.4.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "524e8ac6999421f49a846c2d4411f337e53497d8ec55d67753beffa43c5d9205"
+dependencies = [
+ "atomic-waker",
+ "bytes",
+ "fnv",
+ "futures-core",
+ "futures-sink",
+ "http",
+ "indexmap 2.4.0",
+ "slab",
+ "tokio",
+ "tokio-util",
+ "tracing",
+]
+
+[[package]]
+name = "half"
+version = "2.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6dd08c532ae367adf81c312a4580bc67f1d0fe8bc9c460520283f4c0ff277888"
+dependencies = [
+ "cfg-if",
+ "crunchy",
+ "num-traits",
+]
+
+[[package]]
+name = "hashbrown"
+version = "0.12.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
+
+[[package]]
+name = "hashbrown"
+version = "0.14.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1"
+dependencies = [
+ "ahash",
+ "allocator-api2",
+]
+
+[[package]]
+name = "heck"
+version = "0.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"
+
+[[package]]
+name = "heck"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
+
+[[package]]
+name = "hermit-abi"
+version = "0.3.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024"
+
+[[package]]
+name = "hex"
+version = "0.4.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
+
+[[package]]
+name = "http"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "21b9ddb458710bc376481b842f5da65cdf31522de232c1ca8146abce2a358258"
+dependencies = [
+ "bytes",
+ "fnv",
+ "itoa",
+]
+
+[[package]]
+name = "http-body"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184"
+dependencies = [
+ "bytes",
+ "http",
+]
+
+[[package]]
+name = "http-body-util"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "793429d76616a256bcb62c2a2ec2bed781c8307e797e2598c50010f2bee2544f"
+dependencies = [
+ "bytes",
+ "futures-util",
+ "http",
+ "http-body",
+ "pin-project-lite",
+]
+
+[[package]]
+name = "httparse"
+version = "1.9.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0fcc0b4a115bf80b728eb8ea024ad5bd707b615bfed49e0665b6e0f86fd082d9"
+
+[[package]]
+name = "httpdate"
+version = "1.0.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9"
+
+[[package]]
+name = "humantime"
+version = "2.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4"
+
+[[package]]
+name = "hyper"
+version = "1.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "50dfd22e0e76d0f662d429a5f80fcaf3855009297eab6a0a9f8543834744ba05"
+dependencies = [
+ "bytes",
+ "futures-channel",
+ "futures-util",
+ "h2",
+ "http",
+ "http-body",
+ "httparse",
+ "httpdate",
+ "itoa",
+ "pin-project-lite",
+ "smallvec",
+ "tokio",
+ "want",
+]
+
+[[package]]
+name = "hyper-timeout"
+version = "0.5.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3203a961e5c83b6f5498933e78b6b263e208c197b63e9c6c53cc82ffd3f63793"
+dependencies = [
+ "hyper",
+ "hyper-util",
+ "pin-project-lite",
+ "tokio",
+ "tower-service",
+]
+
+[[package]]
+name = "hyper-util"
+version = "0.1.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "da62f120a8a37763efb0cf8fdf264b884c7b8b9ac8660b900c8661030c00e6ba"
+dependencies = [
+ "bytes",
+ "futures-channel",
+ "futures-util",
+ "http",
+ "http-body",
+ "hyper",
+ "pin-project-lite",
+ "socket2",
+ "tokio",
+ "tower",
+ "tower-service",
+ "tracing",
+]
+
+[[package]]
+name = "iana-time-zone"
+version = "0.1.60"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e7ffbb5a1b541ea2561f8c41c087286cc091e21e556a4f09a8f6cbf17b69b141"
+dependencies = [
+ "android_system_properties",
+ "core-foundation-sys",
+ "iana-time-zone-haiku",
+ "js-sys",
+ "wasm-bindgen",
+ "windows-core",
+]
+
+[[package]]
+name = "iana-time-zone-haiku"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f"
+dependencies = [
+ "cc",
+]
+
+[[package]]
+name = "idna"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6"
+dependencies = [
+ "unicode-bidi",
+ "unicode-normalization",
+]
+
+[[package]]
+name = "indexmap"
+version = "1.9.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99"
+dependencies = [
+ "autocfg",
+ "hashbrown 0.12.3",
+]
+
+[[package]]
+name = "indexmap"
+version = "2.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "93ead53efc7ea8ed3cfb0c79fc8023fbb782a5432b52830b6518941cebe6505c"
+dependencies = [
+ "equivalent",
+ "hashbrown 0.14.5",
+]
+
+[[package]]
+name = "instant"
+version = "0.1.13"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e0242819d153cba4b4b05a5a8f2a7e9bbf97b6055b2a002b395c96b5ff3c0222"
+dependencies = [
+ "cfg-if",
+ "js-sys",
+ "wasm-bindgen",
+ "web-sys",
+]
+
+[[package]]
+name = "integer-encoding"
+version = "3.0.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8bb03732005da905c88227371639bf1ad885cc712789c011c31c5fb3ab3ccf02"
+
+[[package]]
+name = "is_terminal_polyfill"
+version = "1.70.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf"
+
+[[package]]
+name = "itertools"
+version = "0.12.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569"
+dependencies = [
+ "either",
+]
+
+[[package]]
+name = "itertools"
+version = "0.13.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186"
+dependencies = [
+ "either",
+]
+
+[[package]]
+name = "itoa"
+version = "1.0.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b"
+
+[[package]]
+name = "jobserver"
+version = "0.1.32"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "48d1dbcbbeb6a7fec7e059840aa538bd62aaccf972c7346c4d9d2059312853d0"
+dependencies = [
+ "libc",
+]
+
+[[package]]
+name = "js-sys"
+version = "0.3.70"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1868808506b929d7b0cfa8f75951347aa71bb21144b7791bae35d9bccfcfe37a"
+dependencies = [
+ "wasm-bindgen",
+]
+
+[[package]]
+name = "lazy_static"
+version = "1.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
+
+[[package]]
+name = "lexical-core"
+version = "0.8.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2cde5de06e8d4c2faabc400238f9ae1c74d5412d03a7bd067645ccbc47070e46"
+dependencies = [
+ "lexical-parse-float",
+ "lexical-parse-integer",
+ "lexical-util",
+ "lexical-write-float",
+ "lexical-write-integer",
+]
+
+[[package]]
+name = "lexical-parse-float"
+version = "0.8.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "683b3a5ebd0130b8fb52ba0bdc718cc56815b6a097e28ae5a6997d0ad17dc05f"
+dependencies = [
+ "lexical-parse-integer",
+ "lexical-util",
+ "static_assertions",
+]
+
+[[package]]
+name = "lexical-parse-integer"
+version = "0.8.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6d0994485ed0c312f6d965766754ea177d07f9c00c9b82a5ee62ed5b47945ee9"
+dependencies = [
+ "lexical-util",
+ "static_assertions",
+]
+
+[[package]]
+name = "lexical-util"
+version = "0.8.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5255b9ff16ff898710eb9eb63cb39248ea8a5bb036bea8085b1a767ff6c4e3fc"
+dependencies = [
+ "static_assertions",
+]
+
+[[package]]
+name = "lexical-write-float"
+version = "0.8.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "accabaa1c4581f05a3923d1b4cfd124c329352288b7b9da09e766b0668116862"
+dependencies = [
+ "lexical-util",
+ "lexical-write-integer",
+ "static_assertions",
+]
+
+[[package]]
+name = "lexical-write-integer"
+version = "0.8.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e1b6f3d1f4422866b68192d62f77bc5c700bee84f3069f2469d7bc8c77852446"
+dependencies = [
+ "lexical-util",
+ "static_assertions",
+]
+
+[[package]]
+name = "libc"
+version = "0.2.158"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d8adc4bb1803a324070e64a98ae98f38934d91957a99cfb3a43dcbc01bc56439"
+
+[[package]]
+name = "libm"
+version = "0.2.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058"
+
+[[package]]
+name = "libmimalloc-sys"
+version = "0.1.39"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "23aa6811d3bd4deb8a84dde645f943476d13b248d818edcf8ce0b2f37f036b44"
+dependencies = [
+ "cc",
+ "libc",
+]
+
+[[package]]
+name = "linux-raw-sys"
+version = "0.4.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89"
+
+[[package]]
+name = "lock_api"
+version = "0.4.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17"
+dependencies = [
+ "autocfg",
+ "scopeguard",
+]
+
+[[package]]
+name = "log"
+version = "0.4.22"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24"
+
+[[package]]
+name = "lz4_flex"
+version = "0.11.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "75761162ae2b0e580d7e7c390558127e5f01b4194debd6221fd8c207fc80e3f5"
+dependencies = [
+ "twox-hash",
+]
+
+[[package]]
+name = "lzma-sys"
+version = "0.1.20"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5fda04ab3764e6cde78b9974eec4f779acaba7c4e84b36eca3cf77c581b85d27"
+dependencies = [
+ "cc",
+ "libc",
+ "pkg-config",
+]
+
+[[package]]
+name = "matchit"
+version = "0.7.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0e7465ac9959cc2b1404e8e2367b43684a6d13790fe23056cc8c6c5a6b7bcb94"
+
+[[package]]
+name = "md-5"
+version = "0.10.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d89e7ee0cfbedfc4da3340218492196241d89eefb6dab27de5df917a6d2e78cf"
+dependencies = [
+ "cfg-if",
+ "digest",
+]
+
+[[package]]
+name = "memchr"
+version = "2.7.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
+
+[[package]]
+name = "mimalloc"
+version = "0.1.43"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "68914350ae34959d83f732418d51e2427a794055d0b9529f48259ac07af65633"
+dependencies = [
+ "libmimalloc-sys",
+]
+
+[[package]]
+name = "mime"
+version = "0.3.17"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a"
+
+[[package]]
+name = "miniz_oxide"
+version = "0.7.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08"
+dependencies = [
+ "adler",
+]
+
+[[package]]
+name = "miniz_oxide"
+version = "0.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e2d80299ef12ff69b16a84bb182e3b9df68b5a91574d3d4fa6e41b65deec4df1"
+dependencies = [
+ "adler2",
+]
+
+[[package]]
+name = "mio"
+version = "1.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "80e04d1dcff3aae0704555fe5fee3bcfaf3d1fdf8a7e521d5b9d2b42acb52cec"
+dependencies = [
+ "hermit-abi",
+ "libc",
+ "wasi",
+ "windows-sys 0.52.0",
+]
+
+[[package]]
+name = "num"
+version = "0.4.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "35bd024e8b2ff75562e5f34e7f4905839deb4b22955ef5e73d2fea1b9813cb23"
+dependencies = [
+ "num-bigint",
+ "num-complex",
+ "num-integer",
+ "num-iter",
+ "num-rational",
+ "num-traits",
+]
+
+[[package]]
+name = "num-bigint"
+version = "0.4.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9"
+dependencies = [
+ "num-integer",
+ "num-traits",
+]
+
+[[package]]
+name = "num-complex"
+version = "0.4.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495"
+dependencies = [
+ "num-traits",
+]
+
+[[package]]
+name = "num-integer"
+version = "0.1.46"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f"
+dependencies = [
+ "num-traits",
+]
+
+[[package]]
+name = "num-iter"
+version = "0.1.45"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf"
+dependencies = [
+ "autocfg",
+ "num-integer",
+ "num-traits",
+]
+
+[[package]]
+name = "num-rational"
+version = "0.4.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824"
+dependencies = [
+ "num-bigint",
+ "num-integer",
+ "num-traits",
+]
+
+[[package]]
+name = "num-traits"
+version = "0.2.19"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"
+dependencies = [
+ "autocfg",
+ "libm",
+]
+
+[[package]]
+name = "num_cpus"
+version = "1.16.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43"
+dependencies = [
+ "hermit-abi",
+ "libc",
+]
+
+[[package]]
+name = "object"
+version = "0.36.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "27b64972346851a39438c60b341ebc01bba47464ae329e55cf343eb93964efd9"
+dependencies = [
+ "memchr",
+]
+
+[[package]]
+name = "object_store"
+version = "0.10.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e6da452820c715ce78221e8202ccc599b4a52f3e1eb3eedb487b680c81a8e3f3"
+dependencies = [
+ "async-trait",
+ "bytes",
+ "chrono",
+ "futures",
+ "humantime",
+ "itertools 0.13.0",
+ "parking_lot",
+ "percent-encoding",
+ "snafu 0.7.5",
+ "tokio",
+ "tracing",
+ "url",
+ "walkdir",
+]
+
+[[package]]
+name = "object_store"
+version = "0.11.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "25a0c4b3a0e31f8b66f71ad8064521efa773910196e2cde791436f13409f3b45"
+dependencies = [
+ "async-trait",
+ "bytes",
+ "chrono",
+ "futures",
+ "humantime",
+ "itertools 0.13.0",
+ "parking_lot",
+ "percent-encoding",
+ "snafu 0.8.4",
+ "tokio",
+ "tracing",
+ "url",
+ "walkdir",
+]
+
+[[package]]
+name = "once_cell"
+version = "1.19.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
+
+[[package]]
+name = "ordered-float"
+version = "2.10.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "68f19d67e5a2795c94e73e0bb1cc1a7edeb2e28efd39e2e1c9b7a40c1108b11c"
+dependencies = [
+ "num-traits",
+]
+
+[[package]]
+name = "parking_lot"
+version = "0.12.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27"
+dependencies = [
+ "lock_api",
+ "parking_lot_core",
+]
+
+[[package]]
+name = "parking_lot_core"
+version = "0.9.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8"
+dependencies = [
+ "cfg-if",
+ "libc",
+ "redox_syscall",
+ "smallvec",
+ "windows-targets",
+]
+
+[[package]]
+name = "parquet"
+version = "52.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e977b9066b4d3b03555c22bdc442f3fadebd96a39111249113087d0edb2691cd"
+dependencies = [
+ "ahash",
+ "arrow-array 52.2.0",
+ "arrow-buffer 52.2.0",
+ "arrow-cast 52.2.0",
+ "arrow-data 52.2.0",
+ "arrow-ipc 52.2.0",
+ "arrow-schema 52.2.0",
+ "arrow-select 52.2.0",
+ "base64",
+ "bytes",
+ "chrono",
+ "futures",
+ "half",
+ "hashbrown 0.14.5",
+ "num",
+ "num-bigint",
+ "object_store 0.10.2",
+ "paste",
+ "seq-macro",
+ "thrift",
+ "tokio",
+ "twox-hash",
+]
+
+[[package]]
+name = "parquet"
+version = "53.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f0fbf928021131daaa57d334ca8e3904fe9ae22f73c56244fc7db9b04eedc3d8"
+dependencies = [
+ "ahash",
+ "arrow-array 53.0.0",
+ "arrow-buffer 53.0.0",
+ "arrow-cast 53.0.0",
+ "arrow-data 53.0.0",
+ "arrow-ipc 53.0.0",
+ "arrow-schema 53.0.0",
+ "arrow-select 53.0.0",
+ "base64",
+ "brotli",
+ "bytes",
+ "chrono",
+ "flate2",
+ "futures",
+ "half",
+ "hashbrown 0.14.5",
+ "lz4_flex",
+ "num",
+ "num-bigint",
+ "object_store 0.11.0",
+ "paste",
+ "seq-macro",
+ "snap",
+ "thrift",
+ "tokio",
+ "twox-hash",
+ "zstd",
+ "zstd-sys",
+]
+
+[[package]]
+name = "parse-zoneinfo"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1f2a05b18d44e2957b88f96ba460715e295bc1d7510468a2f3d3b44535d26c24"
+dependencies = [
+ "regex",
+]
+
+[[package]]
+name = "paste"
+version = "1.0.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a"
+
+[[package]]
+name = "percent-encoding"
+version = "2.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e"
+
+[[package]]
+name = "petgraph"
+version = "0.6.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b4c5cc86750666a3ed20bdaf5ca2a0344f9c67674cae0515bec2da16fbaa47db"
+dependencies = [
+ "fixedbitset",
+ "indexmap 2.4.0",
+]
+
+[[package]]
+name = "phf"
+version = "0.11.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ade2d8b8f33c7333b51bcf0428d37e217e9f32192ae4772156f65063b8ce03dc"
+dependencies = [
+ "phf_shared",
+]
+
+[[package]]
+name = "phf_codegen"
+version = "0.11.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e8d39688d359e6b34654d328e262234662d16cc0f60ec8dcbe5e718709342a5a"
+dependencies = [
+ "phf_generator",
+ "phf_shared",
+]
+
+[[package]]
+name = "phf_generator"
+version = "0.11.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "48e4cc64c2ad9ebe670cb8fd69dd50ae301650392e81c05f9bfcb2d5bdbc24b0"
+dependencies = [
+ "phf_shared",
+ "rand",
+]
+
+[[package]]
+name = "phf_shared"
+version = "0.11.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "90fcb95eef784c2ac79119d1dd819e162b5da872ce6f3c3abe1e8ca1c082f72b"
+dependencies = [
+ "siphasher",
+]
+
+[[package]]
+name = "pin-project"
+version = "1.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b6bf43b791c5b9e34c3d182969b4abb522f9343702850a2e57f460d00d09b4b3"
+dependencies = [
+ "pin-project-internal",
+]
+
+[[package]]
+name = "pin-project-internal"
+version = "1.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.75",
+]
+
+[[package]]
+name = "pin-project-lite"
+version = "0.2.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02"
+
+[[package]]
+name = "pin-utils"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
+
+[[package]]
+name = "pkg-config"
+version = "0.3.30"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec"
+
+[[package]]
+name = "ppv-lite86"
+version = "0.2.20"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04"
+dependencies = [
+ "zerocopy",
+]
+
+[[package]]
+name = "proc-macro2"
+version = "1.0.86"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77"
+dependencies = [
+ "unicode-ident",
+]
+
+[[package]]
+name = "prost"
+version = "0.13.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3b2ecbe40f08db5c006b5764a2645f7f3f141ce756412ac9e1dd6087e6d32995"
+dependencies = [
+ "bytes",
+ "prost-derive 0.13.2",
+]
+
+[[package]]
+name = "prost-derive"
+version = "0.12.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "81bddcdb20abf9501610992b6759a4c888aef7d1a7247ef75e2404275ac24af1"
+dependencies = [
+ "anyhow",
+ "itertools 0.12.1",
+ "proc-macro2",
+ "quote",
+ "syn 2.0.75",
+]
+
+[[package]]
+name = "prost-derive"
+version = "0.13.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "acf0c195eebb4af52c752bec4f52f645da98b6e92077a04110c7f349477ae5ac"
+dependencies = [
+ "anyhow",
+ "itertools 0.12.1",
+ "proc-macro2",
+ "quote",
+ "syn 2.0.75",
+]
+
+[[package]]
+name = "prost-types"
+version = "0.13.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "60caa6738c7369b940c3d49246a8d1749323674c65cb13010134f5c9bad5b519"
+dependencies = [
+ "prost",
+]
+
+[[package]]
+name = "quote"
+version = "1.0.37"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af"
+dependencies = [
+ "proc-macro2",
+]
+
+[[package]]
+name = "rand"
+version = "0.8.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
+dependencies = [
+ "libc",
+ "rand_chacha",
+ "rand_core",
+]
+
+[[package]]
+name = "rand_chacha"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
+dependencies = [
+ "ppv-lite86",
+ "rand_core",
+]
+
+[[package]]
+name = "rand_core"
+version = "0.6.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
+dependencies = [
+ "getrandom",
+]
+
+[[package]]
+name = "redox_syscall"
+version = "0.5.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2a908a6e00f1fdd0dfd9c0eb08ce85126f6d8bbda50017e74bc4a4b7d4a926a4"
+dependencies = [
+ "bitflags 2.6.0",
+]
+
+[[package]]
+name = "regex"
+version = "1.10.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4219d74c6b67a3654a9fbebc4b419e22126d13d2f3c4a07ee0cb61ff79a79619"
+dependencies = [
+ "aho-corasick",
+ "memchr",
+ "regex-automata",
+ "regex-syntax",
+]
+
+[[package]]
+name = "regex-automata"
+version = "0.4.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df"
+dependencies = [
+ "aho-corasick",
+ "memchr",
+ "regex-syntax",
+]
+
+[[package]]
+name = "regex-syntax"
+version = "0.8.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b"
+
+[[package]]
+name = "rustc-demangle"
+version = "0.1.24"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f"
+
+[[package]]
+name = "rustc_version"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366"
+dependencies = [
+ "semver",
+]
+
+[[package]]
+name = "rustix"
+version = "0.38.34"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f"
+dependencies = [
+ "bitflags 2.6.0",
+ "errno",
+ "libc",
+ "linux-raw-sys",
+ "windows-sys 0.52.0",
+]
+
+[[package]]
+name = "rustversion"
+version = "1.0.17"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "955d28af4278de8121b7ebeb796b6a45735dc01436d898801014aced2773a3d6"
+
+[[package]]
+name = "ryu"
+version = "1.0.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f"
+
+[[package]]
+name = "same-file"
+version = "1.0.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502"
+dependencies = [
+ "winapi-util",
+]
+
+[[package]]
+name = "scopeguard"
+version = "1.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
+
+[[package]]
+name = "semver"
+version = "1.0.23"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b"
+
+[[package]]
+name = "seq-macro"
+version = "0.3.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a3f0bf26fd526d2a95683cd0f87bf103b8539e2ca1ef48ce002d67aad59aa0b4"
+
+[[package]]
+name = "serde"
+version = "1.0.208"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cff085d2cb684faa248efb494c39b68e522822ac0de72ccf08109abde717cfb2"
+dependencies = [
+ "serde_derive",
+]
+
+[[package]]
+name = "serde_derive"
+version = "1.0.208"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "24008e81ff7613ed8e5ba0cfaf24e2c2f1e5b8a0495711e44fcd4882fca62bcf"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.75",
+]
+
+[[package]]
+name = "serde_json"
+version = "1.0.125"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "83c8e735a073ccf5be70aa8066aa984eaf2fa000db6c8d0100ae605b366d31ed"
+dependencies = [
+ "itoa",
+ "memchr",
+ "ryu",
+ "serde",
+]
+
+[[package]]
+name = "sha2"
+version = "0.10.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8"
+dependencies = [
+ "cfg-if",
+ "cpufeatures",
+ "digest",
+]
+
+[[package]]
+name = "shlex"
+version = "1.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
+
+[[package]]
+name = "siphasher"
+version = "0.3.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d"
+
+[[package]]
+name = "slab"
+version = "0.4.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67"
+dependencies = [
+ "autocfg",
+]
+
+[[package]]
+name = "smallvec"
+version = "1.13.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67"
+
+[[package]]
+name = "snafu"
+version = "0.7.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e4de37ad025c587a29e8f3f5605c00f70b98715ef90b9061a815b9e59e9042d6"
+dependencies = [
+ "doc-comment",
+ "snafu-derive 0.7.5",
+]
+
+[[package]]
+name = "snafu"
+version = "0.8.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2b835cb902660db3415a672d862905e791e54d306c6e8189168c7f3d9ae1c79d"
+dependencies = [
+ "snafu-derive 0.8.4",
+]
+
+[[package]]
+name = "snafu-derive"
+version = "0.7.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "990079665f075b699031e9c08fd3ab99be5029b96f3b78dc0709e8f77e4efebf"
+dependencies = [
+ "heck 0.4.1",
+ "proc-macro2",
+ "quote",
+ "syn 1.0.109",
+]
+
+[[package]]
+name = "snafu-derive"
+version = "0.8.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "38d1e02fca405f6280643174a50c942219f0bbf4dbf7d480f1dd864d6f211ae5"
+dependencies = [
+ "heck 0.5.0",
+ "proc-macro2",
+ "quote",
+ "syn 2.0.75",
+]
+
+[[package]]
+name = "snap"
+version = "1.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1b6b67fb9a61334225b5b790716f609cd58395f895b3fe8b328786812a40bc3b"
+
+[[package]]
+name = "socket2"
+version = "0.5.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c"
+dependencies = [
+ "libc",
+ "windows-sys 0.52.0",
+]
+
+[[package]]
+name = "sqlparser"
+version = "0.51.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5fe11944a61da0da3f592e19a45ebe5ab92dc14a779907ff1f08fbb797bfefc7"
+dependencies = [
+ "log",
+ "sqlparser_derive",
+]
+
+[[package]]
+name = "sqlparser_derive"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "01b2e185515564f15375f593fb966b5718bc624ba77fe49fa4616ad619690554"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.75",
+]
+
+[[package]]
+name = "static_assertions"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
+
+[[package]]
+name = "strum"
+version = "0.26.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8fec0f0aef304996cf250b31b5a10dee7980c85da9d759361292b8bca5a18f06"
+dependencies = [
+ "strum_macros",
+]
+
+[[package]]
+name = "strum_macros"
+version = "0.26.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4c6bee85a5a24955dc440386795aa378cd9cf82acd5f764469152d2270e581be"
+dependencies = [
+ "heck 0.5.0",
+ "proc-macro2",
+ "quote",
+ "rustversion",
+ "syn 2.0.75",
+]
+
+[[package]]
+name = "subtle"
+version = "2.6.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292"
+
+[[package]]
+name = "syn"
+version = "1.0.109"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-ident",
+]
+
+[[package]]
+name = "syn"
+version = "2.0.75"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f6af063034fc1935ede7be0122941bafa9bacb949334d090b77ca98b5817c7d9"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-ident",
+]
+
+[[package]]
+name = "sync_wrapper"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160"
+
+[[package]]
+name = "sync_wrapper"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a7065abeca94b6a8a577f9bd45aa0867a2238b74e8eb67cf10d492bc39351394"
+
+[[package]]
+name = "tempfile"
+version = "3.12.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "04cbcdd0c794ebb0d4cf35e88edd2f7d2c4c3e9a5a6dab322839b321c6a87a64"
+dependencies = [
+ "cfg-if",
+ "fastrand",
+ "once_cell",
+ "rustix",
+ "windows-sys 0.59.0",
+]
+
+[[package]]
+name = "thrift"
+version = "0.17.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7e54bc85fc7faa8bc175c4bab5b92ba8d9a3ce893d0e9f42cc455c8ab16a9e09"
+dependencies = [
+ "byteorder",
+ "integer-encoding",
+ "ordered-float",
+]
+
+[[package]]
+name = "tiny-keccak"
+version = "2.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237"
+dependencies = [
+ "crunchy",
+]
+
+[[package]]
+name = "tinyvec"
+version = "1.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "445e881f4f6d382d5f27c034e25eb92edd7c784ceab92a0937db7f2e9471b938"
+dependencies = [
+ "tinyvec_macros",
+]
+
+[[package]]
+name = "tinyvec_macros"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
+
+[[package]]
+name = "tokio"
+version = "1.39.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9babc99b9923bfa4804bd74722ff02c0381021eafa4db9949217e3be8e84fff5"
+dependencies = [
+ "backtrace",
+ "bytes",
+ "libc",
+ "mio",
+ "pin-project-lite",
+ "socket2",
+ "tokio-macros",
+ "windows-sys 0.52.0",
+]
+
+[[package]]
+name = "tokio-macros"
+version = "2.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.75",
+]
+
+[[package]]
+name = "tokio-stream"
+version = "0.1.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "267ac89e0bec6e691e5813911606935d77c476ff49024f98abcea3e7b15e37af"
+dependencies = [
+ "futures-core",
+ "pin-project-lite",
+ "tokio",
+]
+
+[[package]]
+name = "tokio-util"
+version = "0.7.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9cf6b47b3771c49ac75ad09a6162f53ad4b8088b76ac60e8ec1455b31a189fe1"
+dependencies = [
+ "bytes",
+ "futures-core",
+ "futures-sink",
+ "pin-project-lite",
+ "tokio",
+]
+
+[[package]]
+name = "tonic"
+version = "0.12.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c6f6ba989e4b2c58ae83d862d3a3e27690b6e3ae630d0deb59f3697f32aa88ad"
+dependencies = [
+ "async-stream",
+ "async-trait",
+ "axum",
+ "base64",
+ "bytes",
+ "h2",
+ "http",
+ "http-body",
+ "http-body-util",
+ "hyper",
+ "hyper-timeout",
+ "hyper-util",
+ "percent-encoding",
+ "pin-project",
+ "prost",
+ "socket2",
+ "tokio",
+ "tokio-stream",
+ "tower",
+ "tower-layer",
+ "tower-service",
+ "tracing",
+]
+
+[[package]]
+name = "tower"
+version = "0.4.13"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c"
+dependencies = [
+ "futures-core",
+ "futures-util",
+ "indexmap 1.9.3",
+ "pin-project",
+ "pin-project-lite",
+ "rand",
+ "slab",
+ "tokio",
+ "tokio-util",
+ "tower-layer",
+ "tower-service",
+ "tracing",
+]
+
+[[package]]
+name = "tower-layer"
+version = "0.3.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e"
+
+[[package]]
+name = "tower-service"
+version = "0.3.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3"
+
+[[package]]
+name = "tracing"
+version = "0.1.40"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef"
+dependencies = [
+ "pin-project-lite",
+ "tracing-attributes",
+ "tracing-core",
+]
+
+[[package]]
+name = "tracing-attributes"
+version = "0.1.27"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.75",
+]
+
+[[package]]
+name = "tracing-core"
+version = "0.1.32"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54"
+dependencies = [
+ "once_cell",
+]
+
+[[package]]
+name = "try-lock"
+version = "0.2.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b"
+
+[[package]]
+name = "twox-hash"
+version = "1.6.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "97fee6b57c6a41524a810daee9286c02d7752c4253064d0b05472833a438f675"
+dependencies = [
+ "cfg-if",
+ "static_assertions",
+]
+
+[[package]]
+name = "typenum"
+version = "1.17.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825"
+
+[[package]]
+name = "unicode-bidi"
+version = "0.3.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75"
+
+[[package]]
+name = "unicode-ident"
+version = "1.0.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
+
+[[package]]
+name = "unicode-normalization"
+version = "0.1.23"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a56d1686db2308d901306f92a263857ef59ea39678a5458e7cb17f01415101f5"
+dependencies = [
+ "tinyvec",
+]
+
+[[package]]
+name = "unicode-segmentation"
+version = "1.11.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d4c87d22b6e3f4a18d4d40ef354e97c90fcb14dd91d7dc0aa9d8a1172ebf7202"
+
+[[package]]
+name = "unicode-width"
+version = "0.1.13"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0336d538f7abc86d282a4189614dfaa90810dfc2c6f6427eaf88e16311dd225d"
+
+[[package]]
+name = "url"
+version = "2.5.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "22784dbdf76fdde8af1aeda5622b546b422b6fc585325248a2bf9f5e41e94d6c"
+dependencies = [
+ "form_urlencoded",
+ "idna",
+ "percent-encoding",
+]
+
+[[package]]
+name = "utf8parse"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
+
+[[package]]
+name = "uuid"
+version = "1.10.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "81dfa00651efa65069b0b6b651f4aaa31ba9e3c3ce0137aaad053604ee7e0314"
+dependencies = [
+ "getrandom",
+]
+
+[[package]]
+name = "version_check"
+version = "0.9.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
+
+[[package]]
+name = "walkdir"
+version = "2.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b"
+dependencies = [
+ "same-file",
+ "winapi-util",
+]
+
+[[package]]
+name = "want"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e"
+dependencies = [
+ "try-lock",
+]
+
+[[package]]
+name = "wasi"
+version = "0.11.0+wasi-snapshot-preview1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
+
+[[package]]
+name = "wasm-bindgen"
+version = "0.2.93"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a82edfc16a6c469f5f44dc7b571814045d60404b55a0ee849f9bcfa2e63dd9b5"
+dependencies = [
+ "cfg-if",
+ "once_cell",
+ "wasm-bindgen-macro",
+]
+
+[[package]]
+name = "wasm-bindgen-backend"
+version = "0.2.93"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9de396da306523044d3302746f1208fa71d7532227f15e347e2d93e4145dd77b"
+dependencies = [
+ "bumpalo",
+ "log",
+ "once_cell",
+ "proc-macro2",
+ "quote",
+ "syn 2.0.75",
+ "wasm-bindgen-shared",
+]
+
+[[package]]
+name = "wasm-bindgen-macro"
+version = "0.2.93"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "585c4c91a46b072c92e908d99cb1dcdf95c5218eeb6f3bf1efa991ee7a68cccf"
+dependencies = [
+ "quote",
+ "wasm-bindgen-macro-support",
+]
+
+[[package]]
+name = "wasm-bindgen-macro-support"
+version = "0.2.93"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "afc340c74d9005395cf9dd098506f7f44e38f2b4a21c6aaacf9a105ea5e1e836"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.75",
+ "wasm-bindgen-backend",
+ "wasm-bindgen-shared",
+]
+
+[[package]]
+name = "wasm-bindgen-shared"
+version = "0.2.93"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c62a0a307cb4a311d3a07867860911ca130c3494e8c2719593806c08bc5d0484"
+
+[[package]]
+name = "web-sys"
+version = "0.3.70"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "26fdeaafd9bd129f65e7c031593c24d62186301e0c72c8978fa1678be7d532c0"
+dependencies = [
+ "js-sys",
+ "wasm-bindgen",
+]
+
+[[package]]
+name = "winapi-util"
+version = "0.1.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb"
+dependencies = [
+ "windows-sys 0.59.0",
+]
+
+[[package]]
+name = "windows-core"
+version = "0.52.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9"
+dependencies = [
+ "windows-targets",
+]
+
+[[package]]
+name = "windows-sys"
+version = "0.52.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
+dependencies = [
+ "windows-targets",
+]
+
+[[package]]
+name = "windows-sys"
+version = "0.59.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b"
+dependencies = [
+ "windows-targets",
+]
+
+[[package]]
+name = "windows-targets"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
+dependencies = [
+ "windows_aarch64_gnullvm",
+ "windows_aarch64_msvc",
+ "windows_i686_gnu",
+ "windows_i686_gnullvm",
+ "windows_i686_msvc",
+ "windows_x86_64_gnu",
+ "windows_x86_64_gnullvm",
+ "windows_x86_64_msvc",
+]
+
+[[package]]
+name = "windows_aarch64_gnullvm"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
+
+[[package]]
+name = "windows_aarch64_msvc"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
+
+[[package]]
+name = "windows_i686_gnu"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
+
+[[package]]
+name = "windows_i686_gnullvm"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
+
+[[package]]
+name = "windows_i686_msvc"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
+
+[[package]]
+name = "windows_x86_64_gnu"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
+
+[[package]]
+name = "windows_x86_64_gnullvm"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
+
+[[package]]
+name = "windows_x86_64_msvc"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
+
+[[package]]
+name = "xz2"
+version = "0.1.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "388c44dc09d76f1536602ead6d325eb532f5c122f17782bd57fb47baeeb767e2"
+dependencies = [
+ "lzma-sys",
+]
+
+[[package]]
+name = "zerocopy"
+version = "0.7.35"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0"
+dependencies = [
+ "byteorder",
+ "zerocopy-derive",
+]
+
+[[package]]
+name = "zerocopy-derive"
+version = "0.7.35"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.75",
+]
+
+[[package]]
+name = "zstd"
+version = "0.13.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fcf2b778a664581e31e389454a7072dab1647606d44f7feea22cd5abb9c9f3f9"
+dependencies = [
+ "zstd-safe",
+]
+
+[[package]]
+name = "zstd-safe"
+version = "7.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "54a3ab4db68cea366acc5c897c7b4d4d1b8994a9cd6e6f841f8964566a419059"
+dependencies = [
+ "zstd-sys",
+]
+
+[[package]]
+name = "zstd-sys"
+version = "2.0.12+zstd.1.5.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0a4e40c320c3cb459d9a9ff6de98cff88f4751ee9275d140e2be94a2b74e4c13"
+dependencies = [
+ "cc",
+ "pkg-config",
+]
diff --git a/src/sqlancer/datafusion/server/datafusion_server/Cargo.toml b/src/sqlancer/datafusion/server/datafusion_server/Cargo.toml
index 6ee59f99..f690cb52 100644
--- a/src/sqlancer/datafusion/server/datafusion_server/Cargo.toml
+++ b/src/sqlancer/datafusion/server/datafusion_server/Cargo.toml
@@ -4,20 +4,26 @@ edition = "2021"
description = "Standalone DataFusion server"
license = "Apache-2.0"
+# TODO(datafusion): Figure out how to automatically manage arrow version
+# arrow version should be the same as the one used by datafusion
[dependencies]
-ahash = { version = "0.8", default-features = false, features = ["runtime-rng"] }
-arrow = { version = "53.0.0", features = ["prettyprint"] }
-arrow-array = { version = "53.0.0", default-features = false, features = ["chrono-tz"] }
-arrow-buffer = { version = "53.0.0", default-features = false }
-arrow-flight = { version = "53.0.0", features = ["flight-sql-experimental"] }
-arrow-ipc = { version = "53.0.0", default-features = false, features = ["lz4"] }
-arrow-ord = { version = "53.0.0", default-features = false }
-arrow-schema = { version = "53.0.0", default-features = false }
-arrow-string = { version = "53.0.0", default-features = false }
+ahash = { version = "0.8", default-features = false, features = [
+ "runtime-rng",
+] }
+arrow = { version = "53.3.0", features = ["prettyprint"] }
+arrow-array = { version = "53.3.0", default-features = false, features = [
+ "chrono-tz",
+] }
+arrow-buffer = { version = "53.3.0", default-features = false }
+arrow-flight = { version = "53.3.0", features = ["flight-sql-experimental"] }
+arrow-ipc = { version = "53.3.0", default-features = false, features = ["lz4"] }
+arrow-ord = { version = "53.3.0", default-features = false }
+arrow-schema = { version = "53.3.0", default-features = false }
+arrow-string = { version = "53.3.0", default-features = false }
async-trait = "0.1.73"
bytes = "1.4"
-chrono = { version = "0.4.34", default-features = false }
-dashmap = "5.5.0"
+chrono = { version = "0.4.38", default-features = false }
+dashmap = "6.0.1"
# This version is for SQLancer CI run (disabled temporary for multiple newly fixed bugs)
# datafusion = { version = "41.0.0" }
# Use following line if you want to test against the latest main branch of DataFusion
@@ -28,9 +34,13 @@ half = { version = "2.2.1", default-features = false }
hashbrown = { version = "0.14.5", features = ["raw"] }
log = "0.4"
num_cpus = "1.13.0"
-object_store = { version = "0.10.1", default-features = false }
+object_store = { version = "0.11.0", default-features = false }
parking_lot = "0.12"
-parquet = { version = "52.0.0", default-features = false, features = ["arrow", "async", "object_store"] }
+parquet = { version = "53.3.0", default-features = false, features = [
+ "arrow",
+ "async",
+ "object_store",
+] }
rand = "0.8"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1"
@@ -38,7 +48,7 @@ tokio = { version = "1.36", features = ["macros", "rt", "sync"] }
tonic = "0.12.1"
uuid = "1.0"
prost = { version = "0.13.1" }
-prost-derive = { version = "0.12", default-features = false }
+prost-derive = "0.13.1"
mimalloc = { version = "0.1", default-features = false }
[[bin]]
diff --git a/src/sqlancer/datafusion/test/DataFusionNoRECOracle.java b/src/sqlancer/datafusion/test/DataFusionNoRECOracle.java
index a4c69a0b..a7d876e8 100644
--- a/src/sqlancer/datafusion/test/DataFusionNoRECOracle.java
+++ b/src/sqlancer/datafusion/test/DataFusionNoRECOracle.java
@@ -109,5 +109,6 @@ public void check() throws SQLException {
throw new AssertionError("\n\n" + indentedErrorLog);
}
+ // System.out.println("NOREC passed: \n" + q1String + "\n" + q2String);
}
}
diff --git a/src/sqlancer/datafusion/test/DataFusionPQS.java b/src/sqlancer/datafusion/test/DataFusionPQS.java
new file mode 100644
index 00000000..00bd9f2a
--- /dev/null
+++ b/src/sqlancer/datafusion/test/DataFusionPQS.java
@@ -0,0 +1,344 @@
+package sqlancer.datafusion.test;
+
+import static sqlancer.datafusion.DataFusionUtil.dfAssert;
+import static sqlancer.datafusion.ast.DataFusionSelect.getRandomSelect;
+
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Optional;
+import java.util.stream.Collectors;
+import java.util.stream.IntStream;
+
+import sqlancer.IgnoreMeException;
+import sqlancer.common.ast.newast.Node;
+import sqlancer.common.oracle.NoRECBase;
+import sqlancer.common.oracle.TestOracle;
+import sqlancer.common.query.SQLQueryAdapter;
+import sqlancer.common.query.SQLancerResultSet;
+import sqlancer.datafusion.DataFusionErrors;
+import sqlancer.datafusion.DataFusionProvider.DataFusionGlobalState;
+import sqlancer.datafusion.DataFusionSchema.DataFusionColumn;
+import sqlancer.datafusion.DataFusionSchema.DataFusionTable;
+import sqlancer.datafusion.DataFusionToStringVisitor;
+import sqlancer.datafusion.DataFusionUtil;
+import sqlancer.datafusion.DataFusionUtil.DataFusionLogger;
+import sqlancer.datafusion.ast.DataFusionExpression;
+import sqlancer.datafusion.ast.DataFusionSelect;
+import sqlancer.datafusion.ast.DataFusionSelect.DataFusionFrom;
+
+public class DataFusionPQS extends NoRECBase implements TestOracle {
+
+ private final DataFusionGlobalState state;
+
+ // Table references in a randomly generated SELECT query
+ // used for current PQS check.
+ // To construct queries ONLY used in PQS
+ // columns will be temporarily aliased
+ // Rember to reset them when PQS check is done
+ private List pqsTables;
+
+ private StringBuilder currentCheckLog; // Each append should end with '\n'
+
+ public DataFusionPQS(DataFusionGlobalState globalState) {
+ super(globalState);
+ this.state = globalState;
+
+ DataFusionErrors.registerExpectedExecutionErrors(errors);
+ }
+
+ private void setColumnAlias(List tables) {
+ List allColumns = tables.stream().flatMap(t -> t.getColumns().stream())
+ .collect(Collectors.toList());
+ for (int i = 0; i < allColumns.size(); i++) {
+ String alias = "cc" + i;
+ allColumns.get(i).alias = Optional.of(alias);
+ }
+ }
+
+ private void resetColumnAlias(List tables) {
+ tables.stream().flatMap(t -> t.getColumns().stream()).forEach(c -> c.alias = Optional.empty());
+ }
+
+ private void pqsCleanUp() throws SQLException {
+ if (pqsTables == null) {
+ return;
+ }
+ resetColumnAlias(pqsTables);
+
+ // Drop temp tables used in PQS check
+ SQLQueryAdapter tttCleanUp = new SQLQueryAdapter("drop table if exists ttt", errors);
+ tttCleanUp.execute(state);
+ SQLQueryAdapter ttCleanUp = new SQLQueryAdapter("drop table if exists tt", errors);
+ ttCleanUp.execute(state);
+ }
+
+ @Override
+ public void check() throws SQLException {
+ this.currentCheckLog = new StringBuilder();
+ String replay = DataFusionUtil.getReplay(state.getDatabaseName());
+ currentCheckLog.append(replay);
+ pqsCleanUp();
+
+ try {
+ checkImpl();
+ } catch (Exception | AssertionError e) {
+ pqsCleanUp();
+ throw e;
+ }
+ pqsCleanUp();
+ }
+
+ public void checkImpl() throws SQLException {
+ // ======================================================
+ // Step 1:
+ // select tt0.c0 as cc0, tt0.c1 as cc1, tt1.c0 as cc2
+ // from t0 as tt0, t1 as tt1
+ // where tt0.c0 = tt1.c0;
+ // ======================================================
+ DataFusionSelect randomSelect = getRandomSelect(state);
+ randomSelect.from.joinConditionList = new ArrayList<>();
+ randomSelect.from.joinTypeList = new ArrayList<>();
+ randomSelect.mutateEquivalentTableName();
+ pqsTables = randomSelect.tableList;
+
+ // Reset fetch columns
+ List allColumns = randomSelect.tableList.stream().flatMap(t -> t.getColumns().stream())
+ .collect(Collectors.toList());
+ setColumnAlias(pqsTables);
+ List aliasedColumns = allColumns.stream().map(c -> c.getOrignalName() + " AS " + c.alias.get())
+ .collect(Collectors.toList());
+ String fetchColumnsString = String.join(", ", aliasedColumns);
+ randomSelect.setFetchColumnsString(fetchColumnsString);
+
+ // ======================================================
+ // Step 2:
+ // create table tt as
+ // with cte0 as (select tt0.c0 as cc0, tt0.c1 as cc1 from t0 as tt0 order by
+ // random() limit 1),
+ // with cte1 as (select tt1.c0 as cc2 from t1 as tt1 order by random() limit 1)
+ // select * from cte0, cte1;
+ // ======================================================
+ List cteSelects = new ArrayList<>();
+ for (DataFusionTable table : randomSelect.tableList) {
+ DataFusionSelect cteSelect = new DataFusionSelect();
+ DataFusionFrom cteFrom = new DataFusionFrom(Arrays.asList(table));
+ cteSelect.from = cteFrom;
+
+ List columns = table.getColumns();
+ List cteAliasedColumns = columns.stream().map(c -> c.getOrignalName() + " AS " + c.alias.get())
+ .collect(Collectors.toList());
+ String cteFetchColumnsString = String.join(", ", cteAliasedColumns);
+ cteSelect.setFetchColumnsString(cteFetchColumnsString);
+ cteSelects.add(cteSelect);
+ }
+
+ // select tt0.c0 as cc0, tt0.c1 as cc1 from tt0 order by random()
+ List cteSelectsPickOneRow = cteSelects.stream()
+ .map(cteSelect -> DataFusionToStringVisitor.asString(cteSelect) + " ORDER BY RANDOM() LIMIT 1")
+ .collect(Collectors.toList());
+ int ncte = cteSelectsPickOneRow.size();
+
+ List ctes = new ArrayList<>();
+ for (int i = 0; i < ncte; i++) {
+ String cte = "cte" + i + " AS (" + cteSelectsPickOneRow.get(i) + ")";
+ ctes.add(cte);
+ }
+
+ // cte0, cte1, cte2
+ List ctesInFrom = IntStream.range(0, ncte).mapToObj(i -> "cte" + i).collect(Collectors.toList());
+ String ctesInFromString = String.join(", ", ctesInFrom);
+
+ // Create tt (Table with one pivot row)
+ String ttCreate = "CREATE TABLE tt AS\n WITH\n " + String.join(",\n ", ctes) + "\n" + "SELECT * FROM "
+ + ctesInFromString;
+
+ currentCheckLog.append("==== Create tt (Table with one pivot row):\n").append(ttCreate).append("\n");
+
+ // ======================================================
+ // Step3:
+ // Find the predicate that can select the predicate row
+ // can be {p, NOT p, p is NULL}
+ // Note 'p' is 'cc0 = cc2' in Step 1
+ // ======================================================
+ Node whereExpr = randomSelect.getWhereClause(); // must be valid
+ Node notWhereExpr = randomSelect.exprGenAll.negatePredicate(whereExpr);
+ Node isNullWhereExpr = randomSelect.exprGenAll.isNull(whereExpr);
+ List> candidatePredicates = Arrays.asList(whereExpr, notWhereExpr, isNullWhereExpr);
+
+ String pivotQ1 = "select * from tt where " + DataFusionToStringVisitor.asString(whereExpr);
+ String pivotQ2 = "select * from tt where " + DataFusionToStringVisitor.asString(notWhereExpr);
+ String pivotQ3 = "select * from tt where " + DataFusionToStringVisitor.asString(isNullWhereExpr);
+
+ List pivotQs = Arrays.asList(pivotQ1, pivotQ2, pivotQ3);
+
+ // Execute "crete tt" (table with one pivot row)
+ SQLQueryAdapter q = new SQLQueryAdapter(ttCreate, errors);
+ q.execute(state);
+
+ SQLancerResultSet ttResult = null;
+ SQLQueryAdapter ttSelect = new SQLQueryAdapter("select * from tt", errors);
+ int nrow = 0;
+ try {
+ ttResult = ttSelect.executeAndGetLogged(state);
+
+ if (ttResult == null) {
+ // Possible bug here, investigate later
+ throw new IgnoreMeException();
+ }
+
+ while (ttResult.next()) {
+ nrow++;
+ }
+ } catch (Exception e) {
+ // Possible bug here, investigate later
+ throw new IgnoreMeException();
+ } finally {
+ if (ttResult != null && !ttResult.isClosed()) {
+ ttResult.close();
+ }
+ }
+
+ if (nrow == 0) {
+ // If empty table is picked, we can't find a pivot row
+ // Give up current check
+ // TODO(datafusion): support empty tables
+ throw new IgnoreMeException("Empty table is picked");
+ }
+
+ Node pivotPredicate = null;
+ String pivotRow = "";
+ for (int i = 0; i < pivotQs.size(); i++) {
+ String pivotQ = pivotQs.get(i);
+ SQLQueryAdapter qSelect = new SQLQueryAdapter(pivotQ, errors);
+ SQLancerResultSet rs = null;
+ try {
+ rs = qSelect.executeAndGetLogged(state);
+ if (rs == null) {
+ // Only one in 3 pivot query will return 1 row
+ continue;
+ }
+
+ int rowCount = 0;
+ while (rs.next()) {
+ rowCount += 1;
+ for (int ii = 1; ii <= rs.rs.getMetaData().getColumnCount(); ii++) {
+ pivotRow += "[" + rs.getString(ii) + "]";
+ }
+ pivotPredicate = candidatePredicates.get(i);
+ }
+
+ dfAssert(rowCount <= 1, "Pivot row should be length of 1, got " + rowCount);
+
+ if (rowCount == 1) {
+ break;
+ }
+ } catch (Exception e) {
+ currentCheckLog.append(pivotQ).append("\n");
+ currentCheckLog.append(e.getMessage()).append("\n").append(e.getCause()).append("\n");
+
+ String fullErrorMessage = currentCheckLog.toString();
+ state.dfLogger.appendToLog(DataFusionLogger.DataFusionLogType.ERROR, fullErrorMessage);
+
+ throw new AssertionError(fullErrorMessage);
+ } finally {
+ if (rs != null && !rs.isClosed()) {
+ rs.close();
+ }
+ }
+ }
+
+ if (pivotPredicate == null) {
+ // Sometimes all valid pivot queries failed
+ // Potential bug, investigate later
+ currentCheckLog.append("ALl pivot q failed! ").append(pivotQs).append("\n");
+ throw new IgnoreMeException("All pivot queries failed " + pivotQs);
+ }
+
+ // ======================================================
+ // Step 4:
+ // Let's say in Step 3 we found the predicate is "Not (cc0 = cc2)"
+ // Check if the pivot row can be find in
+ // "select * from tt0, tt1 where Not(cc0 = cc2)"
+ // Then we construct table ttt with above query
+ // Finally join 'tt' and 'ttt' make sure one pivot row will be output
+ // ======================================================
+ DataFusionSelect selectAllRows = new DataFusionSelect();
+ DataFusionFrom selectAllRowsFrom = new DataFusionFrom(randomSelect.tableList);
+ selectAllRows.from = selectAllRowsFrom;
+ selectAllRows.setWhereClause(pivotPredicate);
+
+ List allSelectColumns = randomSelect.tableList.stream().flatMap(t -> t.getColumns().stream())
+ .collect(Collectors.toList());
+ // tt0.v0 as cc0, tt0.v1 as cc1, tt1.v0 as cc2
+ List allSelectExprs = allSelectColumns.stream().map(c -> c.getOrignalName() + " AS " + c.alias.get())
+ .collect(Collectors.toList());
+ resetColumnAlias(randomSelect.tableList);
+ String selectAllRowsFetchColStr = String.join(", ", allSelectExprs);
+ selectAllRows.setFetchColumnsString(selectAllRowsFetchColStr);
+
+ String selectAllRowsString = DataFusionToStringVisitor.asString(selectAllRows);
+ String tttCreate = "CREATE TABLE ttt AS\n" + selectAllRowsString;
+
+ SQLQueryAdapter tttCreateStmt = new SQLQueryAdapter(tttCreate, errors);
+ tttCreateStmt.execute(state);
+ setColumnAlias(randomSelect.tableList);
+
+ // ======================================================
+ // Step 5:
+ // Make sure the following query return 1 pivot row
+ // Otherwise PQS oracle is violated
+ // select * from tt join ttt
+ // on
+ // tt.cc0 is not distinct from ttt.cc0
+ // and tt.cc1 is not distinct from ttt.cc1
+ // and tt.cc2 is not distinct from ttt.cc2
+ // ======================================================
+ List onConditions = allSelectColumns.stream()
+ .map(c -> "(tt." + c.alias.get() + " IS NOT DISTINCT FROM ttt." + c.alias.get() + ")")
+ .collect(Collectors.toList());
+ String onCond = String.join("\nAND ", onConditions);
+ String joinQuery = "SELECT COUNT(*) FROM tt JOIN ttt ON\n" + onCond;
+
+ SQLQueryAdapter qJoin = new SQLQueryAdapter(joinQuery, errors);
+
+ SQLancerResultSet rsFull = null;
+ try {
+ rsFull = qJoin.executeAndGetLogged(state);
+
+ if (rsFull == null) {
+ throw new IgnoreMeException("Join query returned no results: " + joinQuery);
+ }
+
+ String joinCount = "invalid";
+ while (rsFull.next()) {
+ joinCount = rsFull.getString(1);
+ }
+
+ if (joinCount.equals("0")) {
+ String replay = DataFusionUtil.getReplay(state.getDatabaseName());
+ StringBuilder errorLog = new StringBuilder().append("PQS oracle violated:\n").append("Found ")
+ .append(joinCount).append(" pivot rows:\n").append(" Pivot row: ").append(pivotRow).append("\n")
+ .append("Query to select pivot row: ").append(ttCreate).append("\n")
+ .append("Query to select all rows: ").append(tttCreate).append("\n").append("Join: ")
+ .append(joinQuery).append("\n").append(replay).append("\n");
+
+ String errorString = errorLog.toString();
+ String indentedErrorLog = errorString.replaceAll("(?m)^", " ");
+ state.dfLogger.appendToLog(DataFusionLogger.DataFusionLogType.ERROR, errorString);
+
+ throw new AssertionError("\n\n" + indentedErrorLog);
+ } else if (!joinCount.matches("\\d+")) {
+ // If joinCount is not a integer > 0, throw exception
+ throw new IgnoreMeException("Join query returned invalid result: " + joinCount);
+ }
+ } catch (Exception e) {
+ throw new IgnoreMeException("Failed to execute join query: " + joinQuery);
+ } finally {
+ if (rsFull != null && !rsFull.isClosed()) {
+ rsFull.close();
+ }
+ }
+ }
+}
diff --git a/src/sqlancer/datafusion/test/DataFusionQueryPartitioningWhereTester.java b/src/sqlancer/datafusion/test/DataFusionQueryPartitioningWhereTester.java
index b604cbc9..31f90d0f 100644
--- a/src/sqlancer/datafusion/test/DataFusionQueryPartitioningWhereTester.java
+++ b/src/sqlancer/datafusion/test/DataFusionQueryPartitioningWhereTester.java
@@ -8,6 +8,7 @@
import java.util.List;
import sqlancer.ComparatorHelper;
+import sqlancer.IgnoreMeException;
import sqlancer.Randomly;
import sqlancer.common.ast.newast.NewBinaryOperatorNode;
import sqlancer.common.ast.newast.Node;
@@ -127,6 +128,13 @@ public void check() throws SQLException {
ComparatorHelper.assumeResultSetsAreEqual(qResultSet, qpResultSet, qString, combinedString, state,
ComparatorHelper::canonicalizeResultValue);
} catch (AssertionError e) {
+ // whitelist
+ // ---------
+ // https://github.com/apache/datafusion/issues/12468
+ if (qp1String.contains("NATURAL JOIN")) {
+ throw new IgnoreMeException();
+ }
+
// Append more error message
String replay = DataFusionUtil.getReplay(state.getDatabaseName());
String newMessage = e.getMessage() + "\n" + e.getCause() + "\n" + replay + "\n";
From 3024255dfb22eff85f831600f62dd5998ed08399 Mon Sep 17 00:00:00 2001
From: Yongting You <2010youy01@gmail.com>
Date: Mon, 6 Jan 2025 17:47:16 +0800
Subject: [PATCH 3/3] rm Cargo.lock
---
.../server/datafusion_server/Cargo.lock | 3366 -----------------
1 file changed, 3366 deletions(-)
delete mode 100644 src/sqlancer/datafusion/server/datafusion_server/Cargo.lock
diff --git a/src/sqlancer/datafusion/server/datafusion_server/Cargo.lock b/src/sqlancer/datafusion/server/datafusion_server/Cargo.lock
deleted file mode 100644
index 2d7286df..00000000
--- a/src/sqlancer/datafusion/server/datafusion_server/Cargo.lock
+++ /dev/null
@@ -1,3366 +0,0 @@
-# This file is automatically @generated by Cargo.
-# It is not intended for manual editing.
-version = 3
-
-[[package]]
-name = "addr2line"
-version = "0.22.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6e4503c46a5c0c7844e948c9a4d6acd9f50cccb4de1c48eb9e291ea17470c678"
-dependencies = [
- "gimli",
-]
-
-[[package]]
-name = "adler"
-version = "1.0.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
-
-[[package]]
-name = "adler2"
-version = "2.0.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627"
-
-[[package]]
-name = "ahash"
-version = "0.8.11"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011"
-dependencies = [
- "cfg-if",
- "const-random",
- "getrandom",
- "once_cell",
- "version_check",
- "zerocopy",
-]
-
-[[package]]
-name = "aho-corasick"
-version = "1.1.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916"
-dependencies = [
- "memchr",
-]
-
-[[package]]
-name = "alloc-no-stdlib"
-version = "2.0.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cc7bb162ec39d46ab1ca8c77bf72e890535becd1751bb45f64c597edb4c8c6b3"
-
-[[package]]
-name = "alloc-stdlib"
-version = "0.2.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "94fb8275041c72129eb51b7d0322c29b8387a0386127718b096429201a5d6ece"
-dependencies = [
- "alloc-no-stdlib",
-]
-
-[[package]]
-name = "allocator-api2"
-version = "0.2.18"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f"
-
-[[package]]
-name = "android-tzdata"
-version = "0.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0"
-
-[[package]]
-name = "android_system_properties"
-version = "0.1.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311"
-dependencies = [
- "libc",
-]
-
-[[package]]
-name = "anstream"
-version = "0.6.15"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "64e15c1ab1f89faffbf04a634d5e1962e9074f2741eef6d97f3c4e322426d526"
-dependencies = [
- "anstyle",
- "anstyle-parse",
- "anstyle-query",
- "anstyle-wincon",
- "colorchoice",
- "is_terminal_polyfill",
- "utf8parse",
-]
-
-[[package]]
-name = "anstyle"
-version = "1.0.8"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1bec1de6f59aedf83baf9ff929c98f2ad654b97c9510f4e70cf6f661d49fd5b1"
-
-[[package]]
-name = "anstyle-parse"
-version = "0.2.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "eb47de1e80c2b463c735db5b217a0ddc39d612e7ac9e2e96a5aed1f57616c1cb"
-dependencies = [
- "utf8parse",
-]
-
-[[package]]
-name = "anstyle-query"
-version = "1.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6d36fc52c7f6c869915e99412912f22093507da8d9e942ceaf66fe4b7c14422a"
-dependencies = [
- "windows-sys 0.52.0",
-]
-
-[[package]]
-name = "anstyle-wincon"
-version = "3.0.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5bf74e1b6e971609db8ca7a9ce79fd5768ab6ae46441c572e46cf596f59e57f8"
-dependencies = [
- "anstyle",
- "windows-sys 0.52.0",
-]
-
-[[package]]
-name = "anyhow"
-version = "1.0.86"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da"
-
-[[package]]
-name = "arrayref"
-version = "0.3.8"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9d151e35f61089500b617991b791fc8bfd237ae50cd5950803758a179b41e67a"
-
-[[package]]
-name = "arrayvec"
-version = "0.7.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50"
-
-[[package]]
-name = "arrow"
-version = "53.0.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "45aef0d9cf9a039bf6cd1acc451b137aca819977b0928dece52bd92811b640ba"
-dependencies = [
- "arrow-arith",
- "arrow-array 53.0.0",
- "arrow-buffer 53.0.0",
- "arrow-cast 53.0.0",
- "arrow-csv",
- "arrow-data 53.0.0",
- "arrow-ipc 53.0.0",
- "arrow-json",
- "arrow-ord",
- "arrow-row",
- "arrow-schema 53.0.0",
- "arrow-select 53.0.0",
- "arrow-string",
-]
-
-[[package]]
-name = "arrow-arith"
-version = "53.0.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "03675e42d1560790f3524800e41403b40d0da1c793fe9528929fde06d8c7649a"
-dependencies = [
- "arrow-array 53.0.0",
- "arrow-buffer 53.0.0",
- "arrow-data 53.0.0",
- "arrow-schema 53.0.0",
- "chrono",
- "half",
- "num",
-]
-
-[[package]]
-name = "arrow-array"
-version = "52.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "16f4a9468c882dc66862cef4e1fd8423d47e67972377d85d80e022786427768c"
-dependencies = [
- "ahash",
- "arrow-buffer 52.2.0",
- "arrow-data 52.2.0",
- "arrow-schema 52.2.0",
- "chrono",
- "half",
- "hashbrown 0.14.5",
- "num",
-]
-
-[[package]]
-name = "arrow-array"
-version = "53.0.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cd2bf348cf9f02a5975c5962c7fa6dee107a2009a7b41ac5fb1a027e12dc033f"
-dependencies = [
- "ahash",
- "arrow-buffer 53.0.0",
- "arrow-data 53.0.0",
- "arrow-schema 53.0.0",
- "chrono",
- "chrono-tz",
- "half",
- "hashbrown 0.14.5",
- "num",
-]
-
-[[package]]
-name = "arrow-buffer"
-version = "52.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c975484888fc95ec4a632cdc98be39c085b1bb518531b0c80c5d462063e5daa1"
-dependencies = [
- "bytes",
- "half",
- "num",
-]
-
-[[package]]
-name = "arrow-buffer"
-version = "53.0.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3092e37715f168976012ce52273c3989b5793b0db5f06cbaa246be25e5f0924d"
-dependencies = [
- "bytes",
- "half",
- "num",
-]
-
-[[package]]
-name = "arrow-cast"
-version = "52.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "da26719e76b81d8bc3faad1d4dbdc1bcc10d14704e63dc17fc9f3e7e1e567c8e"
-dependencies = [
- "arrow-array 52.2.0",
- "arrow-buffer 52.2.0",
- "arrow-data 52.2.0",
- "arrow-schema 52.2.0",
- "arrow-select 52.2.0",
- "atoi",
- "base64",
- "chrono",
- "half",
- "lexical-core",
- "num",
- "ryu",
-]
-
-[[package]]
-name = "arrow-cast"
-version = "53.0.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7ce1018bb710d502f9db06af026ed3561552e493e989a79d0d0f5d9cf267a785"
-dependencies = [
- "arrow-array 53.0.0",
- "arrow-buffer 53.0.0",
- "arrow-data 53.0.0",
- "arrow-schema 53.0.0",
- "arrow-select 53.0.0",
- "atoi",
- "base64",
- "chrono",
- "comfy-table",
- "half",
- "lexical-core",
- "num",
- "ryu",
-]
-
-[[package]]
-name = "arrow-csv"
-version = "53.0.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fd178575f45624d045e4ebee714e246a05d9652e41363ee3f57ec18cca97f740"
-dependencies = [
- "arrow-array 53.0.0",
- "arrow-buffer 53.0.0",
- "arrow-cast 53.0.0",
- "arrow-data 53.0.0",
- "arrow-schema 53.0.0",
- "chrono",
- "csv",
- "csv-core",
- "lazy_static",
- "lexical-core",
- "regex",
-]
-
-[[package]]
-name = "arrow-data"
-version = "52.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dd9d6f18c65ef7a2573ab498c374d8ae364b4a4edf67105357491c031f716ca5"
-dependencies = [
- "arrow-buffer 52.2.0",
- "arrow-schema 52.2.0",
- "half",
- "num",
-]
-
-[[package]]
-name = "arrow-data"
-version = "53.0.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4e4ac0c4ee79150afe067dc4857154b3ee9c1cd52b5f40d59a77306d0ed18d65"
-dependencies = [
- "arrow-buffer 53.0.0",
- "arrow-schema 53.0.0",
- "half",
- "num",
-]
-
-[[package]]
-name = "arrow-flight"
-version = "53.0.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b915fb36d935b969894d7909ad417c67ddeadebbbd57c3c168edf64721a37d31"
-dependencies = [
- "arrow-arith",
- "arrow-array 53.0.0",
- "arrow-buffer 53.0.0",
- "arrow-cast 53.0.0",
- "arrow-data 53.0.0",
- "arrow-ipc 53.0.0",
- "arrow-ord",
- "arrow-row",
- "arrow-schema 53.0.0",
- "arrow-select 53.0.0",
- "arrow-string",
- "base64",
- "bytes",
- "futures",
- "once_cell",
- "paste",
- "prost",
- "prost-types",
- "tokio",
- "tonic",
-]
-
-[[package]]
-name = "arrow-ipc"
-version = "52.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e786e1cdd952205d9a8afc69397b317cfbb6e0095e445c69cda7e8da5c1eeb0f"
-dependencies = [
- "arrow-array 52.2.0",
- "arrow-buffer 52.2.0",
- "arrow-cast 52.2.0",
- "arrow-data 52.2.0",
- "arrow-schema 52.2.0",
- "flatbuffers",
-]
-
-[[package]]
-name = "arrow-ipc"
-version = "53.0.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bb307482348a1267f91b0912e962cd53440e5de0f7fb24c5f7b10da70b38c94a"
-dependencies = [
- "arrow-array 53.0.0",
- "arrow-buffer 53.0.0",
- "arrow-cast 53.0.0",
- "arrow-data 53.0.0",
- "arrow-schema 53.0.0",
- "flatbuffers",
- "lz4_flex",
-]
-
-[[package]]
-name = "arrow-json"
-version = "53.0.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d24805ba326758effdd6f2cbdd482fcfab749544f21b134701add25b33f474e6"
-dependencies = [
- "arrow-array 53.0.0",
- "arrow-buffer 53.0.0",
- "arrow-cast 53.0.0",
- "arrow-data 53.0.0",
- "arrow-schema 53.0.0",
- "chrono",
- "half",
- "indexmap 2.4.0",
- "lexical-core",
- "num",
- "serde",
- "serde_json",
-]
-
-[[package]]
-name = "arrow-ord"
-version = "53.0.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "644046c479d80ae8ed02a7f1e1399072ea344ca6a7b0e293ab2d5d9ed924aa3b"
-dependencies = [
- "arrow-array 53.0.0",
- "arrow-buffer 53.0.0",
- "arrow-data 53.0.0",
- "arrow-schema 53.0.0",
- "arrow-select 53.0.0",
- "half",
- "num",
-]
-
-[[package]]
-name = "arrow-row"
-version = "53.0.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a29791f8eb13b340ce35525b723f5f0df17ecb955599e11f65c2a94ab34e2efb"
-dependencies = [
- "ahash",
- "arrow-array 53.0.0",
- "arrow-buffer 53.0.0",
- "arrow-data 53.0.0",
- "arrow-schema 53.0.0",
- "half",
-]
-
-[[package]]
-name = "arrow-schema"
-version = "52.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9e972cd1ff4a4ccd22f86d3e53e835c2ed92e0eea6a3e8eadb72b4f1ac802cf8"
-
-[[package]]
-name = "arrow-schema"
-version = "53.0.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c85320a3a2facf2b2822b57aa9d6d9d55edb8aee0b6b5d3b8df158e503d10858"
-
-[[package]]
-name = "arrow-select"
-version = "52.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "600bae05d43483d216fb3494f8c32fdbefd8aa4e1de237e790dbb3d9f44690a3"
-dependencies = [
- "ahash",
- "arrow-array 52.2.0",
- "arrow-buffer 52.2.0",
- "arrow-data 52.2.0",
- "arrow-schema 52.2.0",
- "num",
-]
-
-[[package]]
-name = "arrow-select"
-version = "53.0.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9cc7e6b582e23855fd1625ce46e51647aa440c20ea2e71b1d748e0839dd73cba"
-dependencies = [
- "ahash",
- "arrow-array 53.0.0",
- "arrow-buffer 53.0.0",
- "arrow-data 53.0.0",
- "arrow-schema 53.0.0",
- "num",
-]
-
-[[package]]
-name = "arrow-string"
-version = "53.0.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0775b6567c66e56ded19b87a954b6b1beffbdd784ef95a3a2b03f59570c1d230"
-dependencies = [
- "arrow-array 53.0.0",
- "arrow-buffer 53.0.0",
- "arrow-data 53.0.0",
- "arrow-schema 53.0.0",
- "arrow-select 53.0.0",
- "memchr",
- "num",
- "regex",
- "regex-syntax",
-]
-
-[[package]]
-name = "async-compression"
-version = "0.4.12"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fec134f64e2bc57411226dfc4e52dec859ddfc7e711fc5e07b612584f000e4aa"
-dependencies = [
- "bzip2",
- "flate2",
- "futures-core",
- "futures-io",
- "memchr",
- "pin-project-lite",
- "tokio",
- "xz2",
- "zstd",
- "zstd-safe",
-]
-
-[[package]]
-name = "async-stream"
-version = "0.3.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cd56dd203fef61ac097dd65721a419ddccb106b2d2b70ba60a6b529f03961a51"
-dependencies = [
- "async-stream-impl",
- "futures-core",
- "pin-project-lite",
-]
-
-[[package]]
-name = "async-stream-impl"
-version = "0.3.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn 2.0.75",
-]
-
-[[package]]
-name = "async-trait"
-version = "0.1.81"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6e0c28dcc82d7c8ead5cb13beb15405b57b8546e93215673ff8ca0349a028107"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn 2.0.75",
-]
-
-[[package]]
-name = "atoi"
-version = "2.0.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f28d99ec8bfea296261ca1af174f24225171fea9664ba9003cbebee704810528"
-dependencies = [
- "num-traits",
-]
-
-[[package]]
-name = "atomic-waker"
-version = "1.1.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0"
-
-[[package]]
-name = "autocfg"
-version = "1.3.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0"
-
-[[package]]
-name = "axum"
-version = "0.7.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3a6c9af12842a67734c9a2e355436e5d03b22383ed60cf13cd0c18fbfe3dcbcf"
-dependencies = [
- "async-trait",
- "axum-core",
- "bytes",
- "futures-util",
- "http",
- "http-body",
- "http-body-util",
- "itoa",
- "matchit",
- "memchr",
- "mime",
- "percent-encoding",
- "pin-project-lite",
- "rustversion",
- "serde",
- "sync_wrapper 1.0.1",
- "tower",
- "tower-layer",
- "tower-service",
-]
-
-[[package]]
-name = "axum-core"
-version = "0.4.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a15c63fd72d41492dc4f497196f5da1fb04fb7529e631d73630d1b491e47a2e3"
-dependencies = [
- "async-trait",
- "bytes",
- "futures-util",
- "http",
- "http-body",
- "http-body-util",
- "mime",
- "pin-project-lite",
- "rustversion",
- "sync_wrapper 0.1.2",
- "tower-layer",
- "tower-service",
-]
-
-[[package]]
-name = "backtrace"
-version = "0.3.73"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5cc23269a4f8976d0a4d2e7109211a419fe30e8d88d677cd60b6bc79c5732e0a"
-dependencies = [
- "addr2line",
- "cc",
- "cfg-if",
- "libc",
- "miniz_oxide 0.7.4",
- "object",
- "rustc-demangle",
-]
-
-[[package]]
-name = "base64"
-version = "0.22.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6"
-
-[[package]]
-name = "bitflags"
-version = "1.3.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
-
-[[package]]
-name = "bitflags"
-version = "2.6.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de"
-
-[[package]]
-name = "blake2"
-version = "0.10.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "46502ad458c9a52b69d4d4d32775c788b7a1b85e8bc9d482d92250fc0e3f8efe"
-dependencies = [
- "digest",
-]
-
-[[package]]
-name = "blake3"
-version = "1.5.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d82033247fd8e890df8f740e407ad4d038debb9eb1f40533fffb32e7d17dc6f7"
-dependencies = [
- "arrayref",
- "arrayvec",
- "cc",
- "cfg-if",
- "constant_time_eq",
-]
-
-[[package]]
-name = "block-buffer"
-version = "0.10.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71"
-dependencies = [
- "generic-array",
-]
-
-[[package]]
-name = "brotli"
-version = "6.0.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "74f7971dbd9326d58187408ab83117d8ac1bb9c17b085fdacd1cf2f598719b6b"
-dependencies = [
- "alloc-no-stdlib",
- "alloc-stdlib",
- "brotli-decompressor",
-]
-
-[[package]]
-name = "brotli-decompressor"
-version = "4.0.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9a45bd2e4095a8b518033b128020dd4a55aab1c0a381ba4404a472630f4bc362"
-dependencies = [
- "alloc-no-stdlib",
- "alloc-stdlib",
-]
-
-[[package]]
-name = "bumpalo"
-version = "3.16.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c"
-
-[[package]]
-name = "byteorder"
-version = "1.5.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
-
-[[package]]
-name = "bytes"
-version = "1.7.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8318a53db07bb3f8dca91a600466bdb3f2eaadeedfdbcf02e1accbad9271ba50"
-
-[[package]]
-name = "bzip2"
-version = "0.4.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bdb116a6ef3f6c3698828873ad02c3014b3c85cadb88496095628e3ef1e347f8"
-dependencies = [
- "bzip2-sys",
- "libc",
-]
-
-[[package]]
-name = "bzip2-sys"
-version = "0.1.11+1.0.8"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "736a955f3fa7875102d57c82b8cac37ec45224a07fd32d58f9f7a186b6cd4cdc"
-dependencies = [
- "cc",
- "libc",
- "pkg-config",
-]
-
-[[package]]
-name = "cc"
-version = "1.1.14"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "50d2eb3cd3d1bf4529e31c215ee6f93ec5a3d536d9f578f93d9d33ee19562932"
-dependencies = [
- "jobserver",
- "libc",
- "shlex",
-]
-
-[[package]]
-name = "cfg-if"
-version = "1.0.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
-
-[[package]]
-name = "chrono"
-version = "0.4.38"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401"
-dependencies = [
- "android-tzdata",
- "iana-time-zone",
- "num-traits",
- "windows-targets",
-]
-
-[[package]]
-name = "chrono-tz"
-version = "0.9.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "93698b29de5e97ad0ae26447b344c482a7284c737d9ddc5f9e52b74a336671bb"
-dependencies = [
- "chrono",
- "chrono-tz-build",
- "phf",
-]
-
-[[package]]
-name = "chrono-tz-build"
-version = "0.3.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0c088aee841df9c3041febbb73934cfc39708749bf96dc827e3359cd39ef11b1"
-dependencies = [
- "parse-zoneinfo",
- "phf",
- "phf_codegen",
-]
-
-[[package]]
-name = "colorchoice"
-version = "1.0.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d3fd119d74b830634cea2a0f58bbd0d54540518a14397557951e79340abc28c0"
-
-[[package]]
-name = "comfy-table"
-version = "7.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b34115915337defe99b2aff5c2ce6771e5fbc4079f4b506301f5cf394c8452f7"
-dependencies = [
- "strum",
- "strum_macros",
- "unicode-width",
-]
-
-[[package]]
-name = "const-random"
-version = "0.1.18"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "87e00182fe74b066627d63b85fd550ac2998d4b0bd86bfed477a0ae4c7c71359"
-dependencies = [
- "const-random-macro",
-]
-
-[[package]]
-name = "const-random-macro"
-version = "0.1.16"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f9d839f2a20b0aee515dc581a6172f2321f96cab76c1a38a4c584a194955390e"
-dependencies = [
- "getrandom",
- "once_cell",
- "tiny-keccak",
-]
-
-[[package]]
-name = "constant_time_eq"
-version = "0.3.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f7144d30dcf0fafbce74250a3963025d8d52177934239851c917d29f1df280c2"
-
-[[package]]
-name = "core-foundation-sys"
-version = "0.8.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b"
-
-[[package]]
-name = "cpufeatures"
-version = "0.2.13"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "51e852e6dc9a5bed1fae92dd2375037bf2b768725bf3be87811edee3249d09ad"
-dependencies = [
- "libc",
-]
-
-[[package]]
-name = "crc32fast"
-version = "1.4.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3"
-dependencies = [
- "cfg-if",
-]
-
-[[package]]
-name = "crossbeam-utils"
-version = "0.8.20"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80"
-
-[[package]]
-name = "crunchy"
-version = "0.2.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7"
-
-[[package]]
-name = "crypto-common"
-version = "0.1.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3"
-dependencies = [
- "generic-array",
- "typenum",
-]
-
-[[package]]
-name = "csv"
-version = "1.3.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ac574ff4d437a7b5ad237ef331c17ccca63c46479e5b5453eb8e10bb99a759fe"
-dependencies = [
- "csv-core",
- "itoa",
- "ryu",
- "serde",
-]
-
-[[package]]
-name = "csv-core"
-version = "0.1.11"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5efa2b3d7902f4b634a20cae3c9c4e6209dc4779feb6863329607560143efa70"
-dependencies = [
- "memchr",
-]
-
-[[package]]
-name = "dashmap"
-version = "5.5.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "978747c1d849a7d2ee5e8adc0159961c48fb7e5db2f06af6723b80123bb53856"
-dependencies = [
- "cfg-if",
- "hashbrown 0.14.5",
- "lock_api",
- "once_cell",
- "parking_lot_core",
-]
-
-[[package]]
-name = "dashmap"
-version = "6.0.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "804c8821570c3f8b70230c2ba75ffa5c0f9a4189b9a432b6656c536712acae28"
-dependencies = [
- "cfg-if",
- "crossbeam-utils",
- "hashbrown 0.14.5",
- "lock_api",
- "once_cell",
- "parking_lot_core",
-]
-
-[[package]]
-name = "datafusion"
-version = "42.0.0"
-source = "git+https://github.com/apache/datafusion.git?branch=main#6f8c74ca873fe015b2e7ff4eeb2f76bf21ae9d0e"
-dependencies = [
- "ahash",
- "arrow",
- "arrow-array 53.0.0",
- "arrow-ipc 53.0.0",
- "arrow-schema 53.0.0",
- "async-compression",
- "async-trait",
- "bytes",
- "bzip2",
- "chrono",
- "dashmap 6.0.1",
- "datafusion-catalog",
- "datafusion-common",
- "datafusion-common-runtime",
- "datafusion-execution",
- "datafusion-expr",
- "datafusion-functions",
- "datafusion-functions-aggregate",
- "datafusion-functions-nested",
- "datafusion-functions-window",
- "datafusion-optimizer",
- "datafusion-physical-expr",
- "datafusion-physical-expr-common",
- "datafusion-physical-optimizer",
- "datafusion-physical-plan",
- "datafusion-sql",
- "flate2",
- "futures",
- "glob",
- "half",
- "hashbrown 0.14.5",
- "indexmap 2.4.0",
- "itertools 0.13.0",
- "log",
- "num_cpus",
- "object_store 0.11.0",
- "parking_lot",
- "parquet 53.0.0",
- "paste",
- "pin-project-lite",
- "rand",
- "sqlparser",
- "tempfile",
- "tokio",
- "tokio-util",
- "url",
- "uuid",
- "xz2",
- "zstd",
-]
-
-[[package]]
-name = "datafusion-catalog"
-version = "42.0.0"
-source = "git+https://github.com/apache/datafusion.git?branch=main#6f8c74ca873fe015b2e7ff4eeb2f76bf21ae9d0e"
-dependencies = [
- "arrow-schema 53.0.0",
- "async-trait",
- "datafusion-common",
- "datafusion-execution",
- "datafusion-expr",
- "datafusion-physical-plan",
- "parking_lot",
-]
-
-[[package]]
-name = "datafusion-common"
-version = "42.0.0"
-source = "git+https://github.com/apache/datafusion.git?branch=main#6f8c74ca873fe015b2e7ff4eeb2f76bf21ae9d0e"
-dependencies = [
- "ahash",
- "arrow",
- "arrow-array 53.0.0",
- "arrow-buffer 53.0.0",
- "arrow-schema 53.0.0",
- "chrono",
- "half",
- "hashbrown 0.14.5",
- "instant",
- "libc",
- "num_cpus",
- "object_store 0.11.0",
- "parquet 53.0.0",
- "paste",
- "sqlparser",
- "tokio",
-]
-
-[[package]]
-name = "datafusion-common-runtime"
-version = "42.0.0"
-source = "git+https://github.com/apache/datafusion.git?branch=main#6f8c74ca873fe015b2e7ff4eeb2f76bf21ae9d0e"
-dependencies = [
- "log",
- "tokio",
-]
-
-[[package]]
-name = "datafusion-execution"
-version = "42.0.0"
-source = "git+https://github.com/apache/datafusion.git?branch=main#6f8c74ca873fe015b2e7ff4eeb2f76bf21ae9d0e"
-dependencies = [
- "arrow",
- "chrono",
- "dashmap 6.0.1",
- "datafusion-common",
- "datafusion-expr",
- "futures",
- "hashbrown 0.14.5",
- "log",
- "object_store 0.11.0",
- "parking_lot",
- "rand",
- "tempfile",
- "url",
-]
-
-[[package]]
-name = "datafusion-expr"
-version = "42.0.0"
-source = "git+https://github.com/apache/datafusion.git?branch=main#6f8c74ca873fe015b2e7ff4eeb2f76bf21ae9d0e"
-dependencies = [
- "ahash",
- "arrow",
- "arrow-array 53.0.0",
- "arrow-buffer 53.0.0",
- "chrono",
- "datafusion-common",
- "datafusion-expr-common",
- "datafusion-functions-aggregate-common",
- "datafusion-functions-window-common",
- "datafusion-physical-expr-common",
- "indexmap 2.4.0",
- "paste",
- "serde_json",
- "sqlparser",
- "strum",
- "strum_macros",
-]
-
-[[package]]
-name = "datafusion-expr-common"
-version = "42.0.0"
-source = "git+https://github.com/apache/datafusion.git?branch=main#6f8c74ca873fe015b2e7ff4eeb2f76bf21ae9d0e"
-dependencies = [
- "arrow",
- "datafusion-common",
- "paste",
-]
-
-[[package]]
-name = "datafusion-functions"
-version = "42.0.0"
-source = "git+https://github.com/apache/datafusion.git?branch=main#6f8c74ca873fe015b2e7ff4eeb2f76bf21ae9d0e"
-dependencies = [
- "arrow",
- "arrow-buffer 53.0.0",
- "base64",
- "blake2",
- "blake3",
- "chrono",
- "datafusion-common",
- "datafusion-execution",
- "datafusion-expr",
- "hashbrown 0.14.5",
- "hex",
- "itertools 0.13.0",
- "log",
- "md-5",
- "rand",
- "regex",
- "sha2",
- "unicode-segmentation",
- "uuid",
-]
-
-[[package]]
-name = "datafusion-functions-aggregate"
-version = "42.0.0"
-source = "git+https://github.com/apache/datafusion.git?branch=main#6f8c74ca873fe015b2e7ff4eeb2f76bf21ae9d0e"
-dependencies = [
- "ahash",
- "arrow",
- "arrow-schema 53.0.0",
- "datafusion-common",
- "datafusion-execution",
- "datafusion-expr",
- "datafusion-functions-aggregate-common",
- "datafusion-physical-expr",
- "datafusion-physical-expr-common",
- "half",
- "indexmap 2.4.0",
- "log",
- "paste",
-]
-
-[[package]]
-name = "datafusion-functions-aggregate-common"
-version = "42.0.0"
-source = "git+https://github.com/apache/datafusion.git?branch=main#6f8c74ca873fe015b2e7ff4eeb2f76bf21ae9d0e"
-dependencies = [
- "ahash",
- "arrow",
- "datafusion-common",
- "datafusion-expr-common",
- "datafusion-physical-expr-common",
- "rand",
-]
-
-[[package]]
-name = "datafusion-functions-nested"
-version = "42.0.0"
-source = "git+https://github.com/apache/datafusion.git?branch=main#6f8c74ca873fe015b2e7ff4eeb2f76bf21ae9d0e"
-dependencies = [
- "arrow",
- "arrow-array 53.0.0",
- "arrow-buffer 53.0.0",
- "arrow-ord",
- "arrow-schema 53.0.0",
- "datafusion-common",
- "datafusion-execution",
- "datafusion-expr",
- "datafusion-functions",
- "datafusion-functions-aggregate",
- "datafusion-physical-expr-common",
- "itertools 0.13.0",
- "log",
- "paste",
- "rand",
-]
-
-[[package]]
-name = "datafusion-functions-window"
-version = "42.0.0"
-source = "git+https://github.com/apache/datafusion.git?branch=main#6f8c74ca873fe015b2e7ff4eeb2f76bf21ae9d0e"
-dependencies = [
- "datafusion-common",
- "datafusion-expr",
- "datafusion-functions-window-common",
- "datafusion-physical-expr-common",
- "log",
- "paste",
-]
-
-[[package]]
-name = "datafusion-functions-window-common"
-version = "42.0.0"
-source = "git+https://github.com/apache/datafusion.git?branch=main#6f8c74ca873fe015b2e7ff4eeb2f76bf21ae9d0e"
-dependencies = [
- "datafusion-common",
-]
-
-[[package]]
-name = "datafusion-optimizer"
-version = "42.0.0"
-source = "git+https://github.com/apache/datafusion.git?branch=main#6f8c74ca873fe015b2e7ff4eeb2f76bf21ae9d0e"
-dependencies = [
- "arrow",
- "async-trait",
- "chrono",
- "datafusion-common",
- "datafusion-expr",
- "datafusion-physical-expr",
- "hashbrown 0.14.5",
- "indexmap 2.4.0",
- "itertools 0.13.0",
- "log",
- "paste",
- "regex-syntax",
-]
-
-[[package]]
-name = "datafusion-physical-expr"
-version = "42.0.0"
-source = "git+https://github.com/apache/datafusion.git?branch=main#6f8c74ca873fe015b2e7ff4eeb2f76bf21ae9d0e"
-dependencies = [
- "ahash",
- "arrow",
- "arrow-array 53.0.0",
- "arrow-buffer 53.0.0",
- "arrow-ord",
- "arrow-schema 53.0.0",
- "arrow-string",
- "base64",
- "chrono",
- "datafusion-common",
- "datafusion-execution",
- "datafusion-expr",
- "datafusion-expr-common",
- "datafusion-functions-aggregate-common",
- "datafusion-physical-expr-common",
- "half",
- "hashbrown 0.14.5",
- "hex",
- "indexmap 2.4.0",
- "itertools 0.13.0",
- "log",
- "paste",
- "petgraph",
- "regex",
-]
-
-[[package]]
-name = "datafusion-physical-expr-common"
-version = "42.0.0"
-source = "git+https://github.com/apache/datafusion.git?branch=main#6f8c74ca873fe015b2e7ff4eeb2f76bf21ae9d0e"
-dependencies = [
- "ahash",
- "arrow",
- "datafusion-common",
- "datafusion-expr-common",
- "hashbrown 0.14.5",
- "rand",
-]
-
-[[package]]
-name = "datafusion-physical-optimizer"
-version = "42.0.0"
-source = "git+https://github.com/apache/datafusion.git?branch=main#6f8c74ca873fe015b2e7ff4eeb2f76bf21ae9d0e"
-dependencies = [
- "arrow-schema 53.0.0",
- "datafusion-common",
- "datafusion-execution",
- "datafusion-physical-expr",
- "datafusion-physical-plan",
- "itertools 0.13.0",
-]
-
-[[package]]
-name = "datafusion-physical-plan"
-version = "42.0.0"
-source = "git+https://github.com/apache/datafusion.git?branch=main#6f8c74ca873fe015b2e7ff4eeb2f76bf21ae9d0e"
-dependencies = [
- "ahash",
- "arrow",
- "arrow-array 53.0.0",
- "arrow-buffer 53.0.0",
- "arrow-ord",
- "arrow-schema 53.0.0",
- "async-trait",
- "chrono",
- "datafusion-common",
- "datafusion-common-runtime",
- "datafusion-execution",
- "datafusion-expr",
- "datafusion-functions-aggregate",
- "datafusion-functions-aggregate-common",
- "datafusion-functions-window-common",
- "datafusion-physical-expr",
- "datafusion-physical-expr-common",
- "futures",
- "half",
- "hashbrown 0.14.5",
- "indexmap 2.4.0",
- "itertools 0.13.0",
- "log",
- "once_cell",
- "parking_lot",
- "pin-project-lite",
- "rand",
- "tokio",
-]
-
-[[package]]
-name = "datafusion-server"
-version = "0.0.0"
-dependencies = [
- "ahash",
- "arrow",
- "arrow-array 53.0.0",
- "arrow-buffer 53.0.0",
- "arrow-flight",
- "arrow-ipc 53.0.0",
- "arrow-ord",
- "arrow-schema 53.0.0",
- "arrow-string",
- "async-trait",
- "bytes",
- "chrono",
- "dashmap 5.5.3",
- "datafusion",
- "env_logger",
- "futures",
- "half",
- "hashbrown 0.14.5",
- "log",
- "mimalloc",
- "num_cpus",
- "object_store 0.10.2",
- "parking_lot",
- "parquet 52.2.0",
- "prost",
- "prost-derive 0.12.6",
- "rand",
- "serde",
- "serde_json",
- "tokio",
- "tonic",
- "uuid",
-]
-
-[[package]]
-name = "datafusion-sql"
-version = "42.0.0"
-source = "git+https://github.com/apache/datafusion.git?branch=main#6f8c74ca873fe015b2e7ff4eeb2f76bf21ae9d0e"
-dependencies = [
- "arrow",
- "arrow-array 53.0.0",
- "arrow-schema 53.0.0",
- "datafusion-common",
- "datafusion-expr",
- "log",
- "regex",
- "sqlparser",
- "strum",
-]
-
-[[package]]
-name = "digest"
-version = "0.10.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292"
-dependencies = [
- "block-buffer",
- "crypto-common",
- "subtle",
-]
-
-[[package]]
-name = "doc-comment"
-version = "0.3.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10"
-
-[[package]]
-name = "either"
-version = "1.13.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0"
-
-[[package]]
-name = "env_filter"
-version = "0.1.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4f2c92ceda6ceec50f43169f9ee8424fe2db276791afde7b2cd8bc084cb376ab"
-dependencies = [
- "log",
- "regex",
-]
-
-[[package]]
-name = "env_logger"
-version = "0.11.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e13fa619b91fb2381732789fc5de83b45675e882f66623b7d8cb4f643017018d"
-dependencies = [
- "anstream",
- "anstyle",
- "env_filter",
- "humantime",
- "log",
-]
-
-[[package]]
-name = "equivalent"
-version = "1.0.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
-
-[[package]]
-name = "errno"
-version = "0.3.9"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba"
-dependencies = [
- "libc",
- "windows-sys 0.52.0",
-]
-
-[[package]]
-name = "fastrand"
-version = "2.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9fc0510504f03c51ada170672ac806f1f105a88aa97a5281117e1ddc3368e51a"
-
-[[package]]
-name = "fixedbitset"
-version = "0.4.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80"
-
-[[package]]
-name = "flatbuffers"
-version = "24.3.25"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8add37afff2d4ffa83bc748a70b4b1370984f6980768554182424ef71447c35f"
-dependencies = [
- "bitflags 1.3.2",
- "rustc_version",
-]
-
-[[package]]
-name = "flate2"
-version = "1.0.32"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9c0596c1eac1f9e04ed902702e9878208b336edc9d6fddc8a48387349bab3666"
-dependencies = [
- "crc32fast",
- "miniz_oxide 0.8.0",
-]
-
-[[package]]
-name = "fnv"
-version = "1.0.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
-
-[[package]]
-name = "form_urlencoded"
-version = "1.2.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456"
-dependencies = [
- "percent-encoding",
-]
-
-[[package]]
-name = "futures"
-version = "0.3.30"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0"
-dependencies = [
- "futures-channel",
- "futures-core",
- "futures-executor",
- "futures-io",
- "futures-sink",
- "futures-task",
- "futures-util",
-]
-
-[[package]]
-name = "futures-channel"
-version = "0.3.30"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78"
-dependencies = [
- "futures-core",
- "futures-sink",
-]
-
-[[package]]
-name = "futures-core"
-version = "0.3.30"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d"
-
-[[package]]
-name = "futures-executor"
-version = "0.3.30"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d"
-dependencies = [
- "futures-core",
- "futures-task",
- "futures-util",
-]
-
-[[package]]
-name = "futures-io"
-version = "0.3.30"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1"
-
-[[package]]
-name = "futures-macro"
-version = "0.3.30"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn 2.0.75",
-]
-
-[[package]]
-name = "futures-sink"
-version = "0.3.30"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5"
-
-[[package]]
-name = "futures-task"
-version = "0.3.30"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004"
-
-[[package]]
-name = "futures-util"
-version = "0.3.30"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48"
-dependencies = [
- "futures-channel",
- "futures-core",
- "futures-io",
- "futures-macro",
- "futures-sink",
- "futures-task",
- "memchr",
- "pin-project-lite",
- "pin-utils",
- "slab",
-]
-
-[[package]]
-name = "generic-array"
-version = "0.14.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a"
-dependencies = [
- "typenum",
- "version_check",
-]
-
-[[package]]
-name = "getrandom"
-version = "0.2.15"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7"
-dependencies = [
- "cfg-if",
- "libc",
- "wasi",
-]
-
-[[package]]
-name = "gimli"
-version = "0.29.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "40ecd4077b5ae9fd2e9e169b102c6c330d0605168eb0e8bf79952b256dbefffd"
-
-[[package]]
-name = "glob"
-version = "0.3.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b"
-
-[[package]]
-name = "h2"
-version = "0.4.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "524e8ac6999421f49a846c2d4411f337e53497d8ec55d67753beffa43c5d9205"
-dependencies = [
- "atomic-waker",
- "bytes",
- "fnv",
- "futures-core",
- "futures-sink",
- "http",
- "indexmap 2.4.0",
- "slab",
- "tokio",
- "tokio-util",
- "tracing",
-]
-
-[[package]]
-name = "half"
-version = "2.4.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6dd08c532ae367adf81c312a4580bc67f1d0fe8bc9c460520283f4c0ff277888"
-dependencies = [
- "cfg-if",
- "crunchy",
- "num-traits",
-]
-
-[[package]]
-name = "hashbrown"
-version = "0.12.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
-
-[[package]]
-name = "hashbrown"
-version = "0.14.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1"
-dependencies = [
- "ahash",
- "allocator-api2",
-]
-
-[[package]]
-name = "heck"
-version = "0.4.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"
-
-[[package]]
-name = "heck"
-version = "0.5.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
-
-[[package]]
-name = "hermit-abi"
-version = "0.3.9"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024"
-
-[[package]]
-name = "hex"
-version = "0.4.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
-
-[[package]]
-name = "http"
-version = "1.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "21b9ddb458710bc376481b842f5da65cdf31522de232c1ca8146abce2a358258"
-dependencies = [
- "bytes",
- "fnv",
- "itoa",
-]
-
-[[package]]
-name = "http-body"
-version = "1.0.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184"
-dependencies = [
- "bytes",
- "http",
-]
-
-[[package]]
-name = "http-body-util"
-version = "0.1.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "793429d76616a256bcb62c2a2ec2bed781c8307e797e2598c50010f2bee2544f"
-dependencies = [
- "bytes",
- "futures-util",
- "http",
- "http-body",
- "pin-project-lite",
-]
-
-[[package]]
-name = "httparse"
-version = "1.9.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0fcc0b4a115bf80b728eb8ea024ad5bd707b615bfed49e0665b6e0f86fd082d9"
-
-[[package]]
-name = "httpdate"
-version = "1.0.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9"
-
-[[package]]
-name = "humantime"
-version = "2.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4"
-
-[[package]]
-name = "hyper"
-version = "1.4.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "50dfd22e0e76d0f662d429a5f80fcaf3855009297eab6a0a9f8543834744ba05"
-dependencies = [
- "bytes",
- "futures-channel",
- "futures-util",
- "h2",
- "http",
- "http-body",
- "httparse",
- "httpdate",
- "itoa",
- "pin-project-lite",
- "smallvec",
- "tokio",
- "want",
-]
-
-[[package]]
-name = "hyper-timeout"
-version = "0.5.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3203a961e5c83b6f5498933e78b6b263e208c197b63e9c6c53cc82ffd3f63793"
-dependencies = [
- "hyper",
- "hyper-util",
- "pin-project-lite",
- "tokio",
- "tower-service",
-]
-
-[[package]]
-name = "hyper-util"
-version = "0.1.8"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "da62f120a8a37763efb0cf8fdf264b884c7b8b9ac8660b900c8661030c00e6ba"
-dependencies = [
- "bytes",
- "futures-channel",
- "futures-util",
- "http",
- "http-body",
- "hyper",
- "pin-project-lite",
- "socket2",
- "tokio",
- "tower",
- "tower-service",
- "tracing",
-]
-
-[[package]]
-name = "iana-time-zone"
-version = "0.1.60"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e7ffbb5a1b541ea2561f8c41c087286cc091e21e556a4f09a8f6cbf17b69b141"
-dependencies = [
- "android_system_properties",
- "core-foundation-sys",
- "iana-time-zone-haiku",
- "js-sys",
- "wasm-bindgen",
- "windows-core",
-]
-
-[[package]]
-name = "iana-time-zone-haiku"
-version = "0.1.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f"
-dependencies = [
- "cc",
-]
-
-[[package]]
-name = "idna"
-version = "0.5.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6"
-dependencies = [
- "unicode-bidi",
- "unicode-normalization",
-]
-
-[[package]]
-name = "indexmap"
-version = "1.9.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99"
-dependencies = [
- "autocfg",
- "hashbrown 0.12.3",
-]
-
-[[package]]
-name = "indexmap"
-version = "2.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "93ead53efc7ea8ed3cfb0c79fc8023fbb782a5432b52830b6518941cebe6505c"
-dependencies = [
- "equivalent",
- "hashbrown 0.14.5",
-]
-
-[[package]]
-name = "instant"
-version = "0.1.13"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e0242819d153cba4b4b05a5a8f2a7e9bbf97b6055b2a002b395c96b5ff3c0222"
-dependencies = [
- "cfg-if",
- "js-sys",
- "wasm-bindgen",
- "web-sys",
-]
-
-[[package]]
-name = "integer-encoding"
-version = "3.0.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8bb03732005da905c88227371639bf1ad885cc712789c011c31c5fb3ab3ccf02"
-
-[[package]]
-name = "is_terminal_polyfill"
-version = "1.70.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf"
-
-[[package]]
-name = "itertools"
-version = "0.12.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569"
-dependencies = [
- "either",
-]
-
-[[package]]
-name = "itertools"
-version = "0.13.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186"
-dependencies = [
- "either",
-]
-
-[[package]]
-name = "itoa"
-version = "1.0.11"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b"
-
-[[package]]
-name = "jobserver"
-version = "0.1.32"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "48d1dbcbbeb6a7fec7e059840aa538bd62aaccf972c7346c4d9d2059312853d0"
-dependencies = [
- "libc",
-]
-
-[[package]]
-name = "js-sys"
-version = "0.3.70"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1868808506b929d7b0cfa8f75951347aa71bb21144b7791bae35d9bccfcfe37a"
-dependencies = [
- "wasm-bindgen",
-]
-
-[[package]]
-name = "lazy_static"
-version = "1.5.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
-
-[[package]]
-name = "lexical-core"
-version = "0.8.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2cde5de06e8d4c2faabc400238f9ae1c74d5412d03a7bd067645ccbc47070e46"
-dependencies = [
- "lexical-parse-float",
- "lexical-parse-integer",
- "lexical-util",
- "lexical-write-float",
- "lexical-write-integer",
-]
-
-[[package]]
-name = "lexical-parse-float"
-version = "0.8.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "683b3a5ebd0130b8fb52ba0bdc718cc56815b6a097e28ae5a6997d0ad17dc05f"
-dependencies = [
- "lexical-parse-integer",
- "lexical-util",
- "static_assertions",
-]
-
-[[package]]
-name = "lexical-parse-integer"
-version = "0.8.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6d0994485ed0c312f6d965766754ea177d07f9c00c9b82a5ee62ed5b47945ee9"
-dependencies = [
- "lexical-util",
- "static_assertions",
-]
-
-[[package]]
-name = "lexical-util"
-version = "0.8.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5255b9ff16ff898710eb9eb63cb39248ea8a5bb036bea8085b1a767ff6c4e3fc"
-dependencies = [
- "static_assertions",
-]
-
-[[package]]
-name = "lexical-write-float"
-version = "0.8.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "accabaa1c4581f05a3923d1b4cfd124c329352288b7b9da09e766b0668116862"
-dependencies = [
- "lexical-util",
- "lexical-write-integer",
- "static_assertions",
-]
-
-[[package]]
-name = "lexical-write-integer"
-version = "0.8.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e1b6f3d1f4422866b68192d62f77bc5c700bee84f3069f2469d7bc8c77852446"
-dependencies = [
- "lexical-util",
- "static_assertions",
-]
-
-[[package]]
-name = "libc"
-version = "0.2.158"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d8adc4bb1803a324070e64a98ae98f38934d91957a99cfb3a43dcbc01bc56439"
-
-[[package]]
-name = "libm"
-version = "0.2.8"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058"
-
-[[package]]
-name = "libmimalloc-sys"
-version = "0.1.39"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "23aa6811d3bd4deb8a84dde645f943476d13b248d818edcf8ce0b2f37f036b44"
-dependencies = [
- "cc",
- "libc",
-]
-
-[[package]]
-name = "linux-raw-sys"
-version = "0.4.14"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89"
-
-[[package]]
-name = "lock_api"
-version = "0.4.12"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17"
-dependencies = [
- "autocfg",
- "scopeguard",
-]
-
-[[package]]
-name = "log"
-version = "0.4.22"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24"
-
-[[package]]
-name = "lz4_flex"
-version = "0.11.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "75761162ae2b0e580d7e7c390558127e5f01b4194debd6221fd8c207fc80e3f5"
-dependencies = [
- "twox-hash",
-]
-
-[[package]]
-name = "lzma-sys"
-version = "0.1.20"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5fda04ab3764e6cde78b9974eec4f779acaba7c4e84b36eca3cf77c581b85d27"
-dependencies = [
- "cc",
- "libc",
- "pkg-config",
-]
-
-[[package]]
-name = "matchit"
-version = "0.7.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0e7465ac9959cc2b1404e8e2367b43684a6d13790fe23056cc8c6c5a6b7bcb94"
-
-[[package]]
-name = "md-5"
-version = "0.10.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d89e7ee0cfbedfc4da3340218492196241d89eefb6dab27de5df917a6d2e78cf"
-dependencies = [
- "cfg-if",
- "digest",
-]
-
-[[package]]
-name = "memchr"
-version = "2.7.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
-
-[[package]]
-name = "mimalloc"
-version = "0.1.43"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "68914350ae34959d83f732418d51e2427a794055d0b9529f48259ac07af65633"
-dependencies = [
- "libmimalloc-sys",
-]
-
-[[package]]
-name = "mime"
-version = "0.3.17"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a"
-
-[[package]]
-name = "miniz_oxide"
-version = "0.7.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08"
-dependencies = [
- "adler",
-]
-
-[[package]]
-name = "miniz_oxide"
-version = "0.8.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e2d80299ef12ff69b16a84bb182e3b9df68b5a91574d3d4fa6e41b65deec4df1"
-dependencies = [
- "adler2",
-]
-
-[[package]]
-name = "mio"
-version = "1.0.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "80e04d1dcff3aae0704555fe5fee3bcfaf3d1fdf8a7e521d5b9d2b42acb52cec"
-dependencies = [
- "hermit-abi",
- "libc",
- "wasi",
- "windows-sys 0.52.0",
-]
-
-[[package]]
-name = "num"
-version = "0.4.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "35bd024e8b2ff75562e5f34e7f4905839deb4b22955ef5e73d2fea1b9813cb23"
-dependencies = [
- "num-bigint",
- "num-complex",
- "num-integer",
- "num-iter",
- "num-rational",
- "num-traits",
-]
-
-[[package]]
-name = "num-bigint"
-version = "0.4.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9"
-dependencies = [
- "num-integer",
- "num-traits",
-]
-
-[[package]]
-name = "num-complex"
-version = "0.4.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495"
-dependencies = [
- "num-traits",
-]
-
-[[package]]
-name = "num-integer"
-version = "0.1.46"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f"
-dependencies = [
- "num-traits",
-]
-
-[[package]]
-name = "num-iter"
-version = "0.1.45"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf"
-dependencies = [
- "autocfg",
- "num-integer",
- "num-traits",
-]
-
-[[package]]
-name = "num-rational"
-version = "0.4.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824"
-dependencies = [
- "num-bigint",
- "num-integer",
- "num-traits",
-]
-
-[[package]]
-name = "num-traits"
-version = "0.2.19"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"
-dependencies = [
- "autocfg",
- "libm",
-]
-
-[[package]]
-name = "num_cpus"
-version = "1.16.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43"
-dependencies = [
- "hermit-abi",
- "libc",
-]
-
-[[package]]
-name = "object"
-version = "0.36.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "27b64972346851a39438c60b341ebc01bba47464ae329e55cf343eb93964efd9"
-dependencies = [
- "memchr",
-]
-
-[[package]]
-name = "object_store"
-version = "0.10.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e6da452820c715ce78221e8202ccc599b4a52f3e1eb3eedb487b680c81a8e3f3"
-dependencies = [
- "async-trait",
- "bytes",
- "chrono",
- "futures",
- "humantime",
- "itertools 0.13.0",
- "parking_lot",
- "percent-encoding",
- "snafu 0.7.5",
- "tokio",
- "tracing",
- "url",
- "walkdir",
-]
-
-[[package]]
-name = "object_store"
-version = "0.11.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "25a0c4b3a0e31f8b66f71ad8064521efa773910196e2cde791436f13409f3b45"
-dependencies = [
- "async-trait",
- "bytes",
- "chrono",
- "futures",
- "humantime",
- "itertools 0.13.0",
- "parking_lot",
- "percent-encoding",
- "snafu 0.8.4",
- "tokio",
- "tracing",
- "url",
- "walkdir",
-]
-
-[[package]]
-name = "once_cell"
-version = "1.19.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
-
-[[package]]
-name = "ordered-float"
-version = "2.10.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "68f19d67e5a2795c94e73e0bb1cc1a7edeb2e28efd39e2e1c9b7a40c1108b11c"
-dependencies = [
- "num-traits",
-]
-
-[[package]]
-name = "parking_lot"
-version = "0.12.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27"
-dependencies = [
- "lock_api",
- "parking_lot_core",
-]
-
-[[package]]
-name = "parking_lot_core"
-version = "0.9.10"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8"
-dependencies = [
- "cfg-if",
- "libc",
- "redox_syscall",
- "smallvec",
- "windows-targets",
-]
-
-[[package]]
-name = "parquet"
-version = "52.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e977b9066b4d3b03555c22bdc442f3fadebd96a39111249113087d0edb2691cd"
-dependencies = [
- "ahash",
- "arrow-array 52.2.0",
- "arrow-buffer 52.2.0",
- "arrow-cast 52.2.0",
- "arrow-data 52.2.0",
- "arrow-ipc 52.2.0",
- "arrow-schema 52.2.0",
- "arrow-select 52.2.0",
- "base64",
- "bytes",
- "chrono",
- "futures",
- "half",
- "hashbrown 0.14.5",
- "num",
- "num-bigint",
- "object_store 0.10.2",
- "paste",
- "seq-macro",
- "thrift",
- "tokio",
- "twox-hash",
-]
-
-[[package]]
-name = "parquet"
-version = "53.0.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f0fbf928021131daaa57d334ca8e3904fe9ae22f73c56244fc7db9b04eedc3d8"
-dependencies = [
- "ahash",
- "arrow-array 53.0.0",
- "arrow-buffer 53.0.0",
- "arrow-cast 53.0.0",
- "arrow-data 53.0.0",
- "arrow-ipc 53.0.0",
- "arrow-schema 53.0.0",
- "arrow-select 53.0.0",
- "base64",
- "brotli",
- "bytes",
- "chrono",
- "flate2",
- "futures",
- "half",
- "hashbrown 0.14.5",
- "lz4_flex",
- "num",
- "num-bigint",
- "object_store 0.11.0",
- "paste",
- "seq-macro",
- "snap",
- "thrift",
- "tokio",
- "twox-hash",
- "zstd",
- "zstd-sys",
-]
-
-[[package]]
-name = "parse-zoneinfo"
-version = "0.3.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1f2a05b18d44e2957b88f96ba460715e295bc1d7510468a2f3d3b44535d26c24"
-dependencies = [
- "regex",
-]
-
-[[package]]
-name = "paste"
-version = "1.0.15"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a"
-
-[[package]]
-name = "percent-encoding"
-version = "2.3.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e"
-
-[[package]]
-name = "petgraph"
-version = "0.6.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b4c5cc86750666a3ed20bdaf5ca2a0344f9c67674cae0515bec2da16fbaa47db"
-dependencies = [
- "fixedbitset",
- "indexmap 2.4.0",
-]
-
-[[package]]
-name = "phf"
-version = "0.11.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ade2d8b8f33c7333b51bcf0428d37e217e9f32192ae4772156f65063b8ce03dc"
-dependencies = [
- "phf_shared",
-]
-
-[[package]]
-name = "phf_codegen"
-version = "0.11.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e8d39688d359e6b34654d328e262234662d16cc0f60ec8dcbe5e718709342a5a"
-dependencies = [
- "phf_generator",
- "phf_shared",
-]
-
-[[package]]
-name = "phf_generator"
-version = "0.11.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "48e4cc64c2ad9ebe670cb8fd69dd50ae301650392e81c05f9bfcb2d5bdbc24b0"
-dependencies = [
- "phf_shared",
- "rand",
-]
-
-[[package]]
-name = "phf_shared"
-version = "0.11.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "90fcb95eef784c2ac79119d1dd819e162b5da872ce6f3c3abe1e8ca1c082f72b"
-dependencies = [
- "siphasher",
-]
-
-[[package]]
-name = "pin-project"
-version = "1.1.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b6bf43b791c5b9e34c3d182969b4abb522f9343702850a2e57f460d00d09b4b3"
-dependencies = [
- "pin-project-internal",
-]
-
-[[package]]
-name = "pin-project-internal"
-version = "1.1.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn 2.0.75",
-]
-
-[[package]]
-name = "pin-project-lite"
-version = "0.2.14"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02"
-
-[[package]]
-name = "pin-utils"
-version = "0.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
-
-[[package]]
-name = "pkg-config"
-version = "0.3.30"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec"
-
-[[package]]
-name = "ppv-lite86"
-version = "0.2.20"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04"
-dependencies = [
- "zerocopy",
-]
-
-[[package]]
-name = "proc-macro2"
-version = "1.0.86"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77"
-dependencies = [
- "unicode-ident",
-]
-
-[[package]]
-name = "prost"
-version = "0.13.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3b2ecbe40f08db5c006b5764a2645f7f3f141ce756412ac9e1dd6087e6d32995"
-dependencies = [
- "bytes",
- "prost-derive 0.13.2",
-]
-
-[[package]]
-name = "prost-derive"
-version = "0.12.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "81bddcdb20abf9501610992b6759a4c888aef7d1a7247ef75e2404275ac24af1"
-dependencies = [
- "anyhow",
- "itertools 0.12.1",
- "proc-macro2",
- "quote",
- "syn 2.0.75",
-]
-
-[[package]]
-name = "prost-derive"
-version = "0.13.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "acf0c195eebb4af52c752bec4f52f645da98b6e92077a04110c7f349477ae5ac"
-dependencies = [
- "anyhow",
- "itertools 0.12.1",
- "proc-macro2",
- "quote",
- "syn 2.0.75",
-]
-
-[[package]]
-name = "prost-types"
-version = "0.13.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "60caa6738c7369b940c3d49246a8d1749323674c65cb13010134f5c9bad5b519"
-dependencies = [
- "prost",
-]
-
-[[package]]
-name = "quote"
-version = "1.0.37"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af"
-dependencies = [
- "proc-macro2",
-]
-
-[[package]]
-name = "rand"
-version = "0.8.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
-dependencies = [
- "libc",
- "rand_chacha",
- "rand_core",
-]
-
-[[package]]
-name = "rand_chacha"
-version = "0.3.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
-dependencies = [
- "ppv-lite86",
- "rand_core",
-]
-
-[[package]]
-name = "rand_core"
-version = "0.6.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
-dependencies = [
- "getrandom",
-]
-
-[[package]]
-name = "redox_syscall"
-version = "0.5.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2a908a6e00f1fdd0dfd9c0eb08ce85126f6d8bbda50017e74bc4a4b7d4a926a4"
-dependencies = [
- "bitflags 2.6.0",
-]
-
-[[package]]
-name = "regex"
-version = "1.10.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4219d74c6b67a3654a9fbebc4b419e22126d13d2f3c4a07ee0cb61ff79a79619"
-dependencies = [
- "aho-corasick",
- "memchr",
- "regex-automata",
- "regex-syntax",
-]
-
-[[package]]
-name = "regex-automata"
-version = "0.4.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df"
-dependencies = [
- "aho-corasick",
- "memchr",
- "regex-syntax",
-]
-
-[[package]]
-name = "regex-syntax"
-version = "0.8.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b"
-
-[[package]]
-name = "rustc-demangle"
-version = "0.1.24"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f"
-
-[[package]]
-name = "rustc_version"
-version = "0.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366"
-dependencies = [
- "semver",
-]
-
-[[package]]
-name = "rustix"
-version = "0.38.34"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f"
-dependencies = [
- "bitflags 2.6.0",
- "errno",
- "libc",
- "linux-raw-sys",
- "windows-sys 0.52.0",
-]
-
-[[package]]
-name = "rustversion"
-version = "1.0.17"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "955d28af4278de8121b7ebeb796b6a45735dc01436d898801014aced2773a3d6"
-
-[[package]]
-name = "ryu"
-version = "1.0.18"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f"
-
-[[package]]
-name = "same-file"
-version = "1.0.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502"
-dependencies = [
- "winapi-util",
-]
-
-[[package]]
-name = "scopeguard"
-version = "1.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
-
-[[package]]
-name = "semver"
-version = "1.0.23"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b"
-
-[[package]]
-name = "seq-macro"
-version = "0.3.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a3f0bf26fd526d2a95683cd0f87bf103b8539e2ca1ef48ce002d67aad59aa0b4"
-
-[[package]]
-name = "serde"
-version = "1.0.208"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cff085d2cb684faa248efb494c39b68e522822ac0de72ccf08109abde717cfb2"
-dependencies = [
- "serde_derive",
-]
-
-[[package]]
-name = "serde_derive"
-version = "1.0.208"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "24008e81ff7613ed8e5ba0cfaf24e2c2f1e5b8a0495711e44fcd4882fca62bcf"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn 2.0.75",
-]
-
-[[package]]
-name = "serde_json"
-version = "1.0.125"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "83c8e735a073ccf5be70aa8066aa984eaf2fa000db6c8d0100ae605b366d31ed"
-dependencies = [
- "itoa",
- "memchr",
- "ryu",
- "serde",
-]
-
-[[package]]
-name = "sha2"
-version = "0.10.8"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8"
-dependencies = [
- "cfg-if",
- "cpufeatures",
- "digest",
-]
-
-[[package]]
-name = "shlex"
-version = "1.3.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
-
-[[package]]
-name = "siphasher"
-version = "0.3.11"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d"
-
-[[package]]
-name = "slab"
-version = "0.4.9"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67"
-dependencies = [
- "autocfg",
-]
-
-[[package]]
-name = "smallvec"
-version = "1.13.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67"
-
-[[package]]
-name = "snafu"
-version = "0.7.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e4de37ad025c587a29e8f3f5605c00f70b98715ef90b9061a815b9e59e9042d6"
-dependencies = [
- "doc-comment",
- "snafu-derive 0.7.5",
-]
-
-[[package]]
-name = "snafu"
-version = "0.8.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2b835cb902660db3415a672d862905e791e54d306c6e8189168c7f3d9ae1c79d"
-dependencies = [
- "snafu-derive 0.8.4",
-]
-
-[[package]]
-name = "snafu-derive"
-version = "0.7.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "990079665f075b699031e9c08fd3ab99be5029b96f3b78dc0709e8f77e4efebf"
-dependencies = [
- "heck 0.4.1",
- "proc-macro2",
- "quote",
- "syn 1.0.109",
-]
-
-[[package]]
-name = "snafu-derive"
-version = "0.8.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "38d1e02fca405f6280643174a50c942219f0bbf4dbf7d480f1dd864d6f211ae5"
-dependencies = [
- "heck 0.5.0",
- "proc-macro2",
- "quote",
- "syn 2.0.75",
-]
-
-[[package]]
-name = "snap"
-version = "1.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1b6b67fb9a61334225b5b790716f609cd58395f895b3fe8b328786812a40bc3b"
-
-[[package]]
-name = "socket2"
-version = "0.5.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c"
-dependencies = [
- "libc",
- "windows-sys 0.52.0",
-]
-
-[[package]]
-name = "sqlparser"
-version = "0.51.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5fe11944a61da0da3f592e19a45ebe5ab92dc14a779907ff1f08fbb797bfefc7"
-dependencies = [
- "log",
- "sqlparser_derive",
-]
-
-[[package]]
-name = "sqlparser_derive"
-version = "0.2.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "01b2e185515564f15375f593fb966b5718bc624ba77fe49fa4616ad619690554"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn 2.0.75",
-]
-
-[[package]]
-name = "static_assertions"
-version = "1.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
-
-[[package]]
-name = "strum"
-version = "0.26.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8fec0f0aef304996cf250b31b5a10dee7980c85da9d759361292b8bca5a18f06"
-dependencies = [
- "strum_macros",
-]
-
-[[package]]
-name = "strum_macros"
-version = "0.26.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4c6bee85a5a24955dc440386795aa378cd9cf82acd5f764469152d2270e581be"
-dependencies = [
- "heck 0.5.0",
- "proc-macro2",
- "quote",
- "rustversion",
- "syn 2.0.75",
-]
-
-[[package]]
-name = "subtle"
-version = "2.6.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292"
-
-[[package]]
-name = "syn"
-version = "1.0.109"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
-dependencies = [
- "proc-macro2",
- "quote",
- "unicode-ident",
-]
-
-[[package]]
-name = "syn"
-version = "2.0.75"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f6af063034fc1935ede7be0122941bafa9bacb949334d090b77ca98b5817c7d9"
-dependencies = [
- "proc-macro2",
- "quote",
- "unicode-ident",
-]
-
-[[package]]
-name = "sync_wrapper"
-version = "0.1.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160"
-
-[[package]]
-name = "sync_wrapper"
-version = "1.0.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a7065abeca94b6a8a577f9bd45aa0867a2238b74e8eb67cf10d492bc39351394"
-
-[[package]]
-name = "tempfile"
-version = "3.12.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "04cbcdd0c794ebb0d4cf35e88edd2f7d2c4c3e9a5a6dab322839b321c6a87a64"
-dependencies = [
- "cfg-if",
- "fastrand",
- "once_cell",
- "rustix",
- "windows-sys 0.59.0",
-]
-
-[[package]]
-name = "thrift"
-version = "0.17.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7e54bc85fc7faa8bc175c4bab5b92ba8d9a3ce893d0e9f42cc455c8ab16a9e09"
-dependencies = [
- "byteorder",
- "integer-encoding",
- "ordered-float",
-]
-
-[[package]]
-name = "tiny-keccak"
-version = "2.0.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237"
-dependencies = [
- "crunchy",
-]
-
-[[package]]
-name = "tinyvec"
-version = "1.8.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "445e881f4f6d382d5f27c034e25eb92edd7c784ceab92a0937db7f2e9471b938"
-dependencies = [
- "tinyvec_macros",
-]
-
-[[package]]
-name = "tinyvec_macros"
-version = "0.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
-
-[[package]]
-name = "tokio"
-version = "1.39.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9babc99b9923bfa4804bd74722ff02c0381021eafa4db9949217e3be8e84fff5"
-dependencies = [
- "backtrace",
- "bytes",
- "libc",
- "mio",
- "pin-project-lite",
- "socket2",
- "tokio-macros",
- "windows-sys 0.52.0",
-]
-
-[[package]]
-name = "tokio-macros"
-version = "2.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn 2.0.75",
-]
-
-[[package]]
-name = "tokio-stream"
-version = "0.1.15"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "267ac89e0bec6e691e5813911606935d77c476ff49024f98abcea3e7b15e37af"
-dependencies = [
- "futures-core",
- "pin-project-lite",
- "tokio",
-]
-
-[[package]]
-name = "tokio-util"
-version = "0.7.11"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9cf6b47b3771c49ac75ad09a6162f53ad4b8088b76ac60e8ec1455b31a189fe1"
-dependencies = [
- "bytes",
- "futures-core",
- "futures-sink",
- "pin-project-lite",
- "tokio",
-]
-
-[[package]]
-name = "tonic"
-version = "0.12.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c6f6ba989e4b2c58ae83d862d3a3e27690b6e3ae630d0deb59f3697f32aa88ad"
-dependencies = [
- "async-stream",
- "async-trait",
- "axum",
- "base64",
- "bytes",
- "h2",
- "http",
- "http-body",
- "http-body-util",
- "hyper",
- "hyper-timeout",
- "hyper-util",
- "percent-encoding",
- "pin-project",
- "prost",
- "socket2",
- "tokio",
- "tokio-stream",
- "tower",
- "tower-layer",
- "tower-service",
- "tracing",
-]
-
-[[package]]
-name = "tower"
-version = "0.4.13"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c"
-dependencies = [
- "futures-core",
- "futures-util",
- "indexmap 1.9.3",
- "pin-project",
- "pin-project-lite",
- "rand",
- "slab",
- "tokio",
- "tokio-util",
- "tower-layer",
- "tower-service",
- "tracing",
-]
-
-[[package]]
-name = "tower-layer"
-version = "0.3.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e"
-
-[[package]]
-name = "tower-service"
-version = "0.3.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3"
-
-[[package]]
-name = "tracing"
-version = "0.1.40"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef"
-dependencies = [
- "pin-project-lite",
- "tracing-attributes",
- "tracing-core",
-]
-
-[[package]]
-name = "tracing-attributes"
-version = "0.1.27"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn 2.0.75",
-]
-
-[[package]]
-name = "tracing-core"
-version = "0.1.32"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54"
-dependencies = [
- "once_cell",
-]
-
-[[package]]
-name = "try-lock"
-version = "0.2.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b"
-
-[[package]]
-name = "twox-hash"
-version = "1.6.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "97fee6b57c6a41524a810daee9286c02d7752c4253064d0b05472833a438f675"
-dependencies = [
- "cfg-if",
- "static_assertions",
-]
-
-[[package]]
-name = "typenum"
-version = "1.17.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825"
-
-[[package]]
-name = "unicode-bidi"
-version = "0.3.15"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75"
-
-[[package]]
-name = "unicode-ident"
-version = "1.0.12"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
-
-[[package]]
-name = "unicode-normalization"
-version = "0.1.23"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a56d1686db2308d901306f92a263857ef59ea39678a5458e7cb17f01415101f5"
-dependencies = [
- "tinyvec",
-]
-
-[[package]]
-name = "unicode-segmentation"
-version = "1.11.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d4c87d22b6e3f4a18d4d40ef354e97c90fcb14dd91d7dc0aa9d8a1172ebf7202"
-
-[[package]]
-name = "unicode-width"
-version = "0.1.13"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0336d538f7abc86d282a4189614dfaa90810dfc2c6f6427eaf88e16311dd225d"
-
-[[package]]
-name = "url"
-version = "2.5.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "22784dbdf76fdde8af1aeda5622b546b422b6fc585325248a2bf9f5e41e94d6c"
-dependencies = [
- "form_urlencoded",
- "idna",
- "percent-encoding",
-]
-
-[[package]]
-name = "utf8parse"
-version = "0.2.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
-
-[[package]]
-name = "uuid"
-version = "1.10.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "81dfa00651efa65069b0b6b651f4aaa31ba9e3c3ce0137aaad053604ee7e0314"
-dependencies = [
- "getrandom",
-]
-
-[[package]]
-name = "version_check"
-version = "0.9.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
-
-[[package]]
-name = "walkdir"
-version = "2.5.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b"
-dependencies = [
- "same-file",
- "winapi-util",
-]
-
-[[package]]
-name = "want"
-version = "0.3.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e"
-dependencies = [
- "try-lock",
-]
-
-[[package]]
-name = "wasi"
-version = "0.11.0+wasi-snapshot-preview1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
-
-[[package]]
-name = "wasm-bindgen"
-version = "0.2.93"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a82edfc16a6c469f5f44dc7b571814045d60404b55a0ee849f9bcfa2e63dd9b5"
-dependencies = [
- "cfg-if",
- "once_cell",
- "wasm-bindgen-macro",
-]
-
-[[package]]
-name = "wasm-bindgen-backend"
-version = "0.2.93"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9de396da306523044d3302746f1208fa71d7532227f15e347e2d93e4145dd77b"
-dependencies = [
- "bumpalo",
- "log",
- "once_cell",
- "proc-macro2",
- "quote",
- "syn 2.0.75",
- "wasm-bindgen-shared",
-]
-
-[[package]]
-name = "wasm-bindgen-macro"
-version = "0.2.93"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "585c4c91a46b072c92e908d99cb1dcdf95c5218eeb6f3bf1efa991ee7a68cccf"
-dependencies = [
- "quote",
- "wasm-bindgen-macro-support",
-]
-
-[[package]]
-name = "wasm-bindgen-macro-support"
-version = "0.2.93"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "afc340c74d9005395cf9dd098506f7f44e38f2b4a21c6aaacf9a105ea5e1e836"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn 2.0.75",
- "wasm-bindgen-backend",
- "wasm-bindgen-shared",
-]
-
-[[package]]
-name = "wasm-bindgen-shared"
-version = "0.2.93"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c62a0a307cb4a311d3a07867860911ca130c3494e8c2719593806c08bc5d0484"
-
-[[package]]
-name = "web-sys"
-version = "0.3.70"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "26fdeaafd9bd129f65e7c031593c24d62186301e0c72c8978fa1678be7d532c0"
-dependencies = [
- "js-sys",
- "wasm-bindgen",
-]
-
-[[package]]
-name = "winapi-util"
-version = "0.1.9"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb"
-dependencies = [
- "windows-sys 0.59.0",
-]
-
-[[package]]
-name = "windows-core"
-version = "0.52.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9"
-dependencies = [
- "windows-targets",
-]
-
-[[package]]
-name = "windows-sys"
-version = "0.52.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
-dependencies = [
- "windows-targets",
-]
-
-[[package]]
-name = "windows-sys"
-version = "0.59.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b"
-dependencies = [
- "windows-targets",
-]
-
-[[package]]
-name = "windows-targets"
-version = "0.52.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
-dependencies = [
- "windows_aarch64_gnullvm",
- "windows_aarch64_msvc",
- "windows_i686_gnu",
- "windows_i686_gnullvm",
- "windows_i686_msvc",
- "windows_x86_64_gnu",
- "windows_x86_64_gnullvm",
- "windows_x86_64_msvc",
-]
-
-[[package]]
-name = "windows_aarch64_gnullvm"
-version = "0.52.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
-
-[[package]]
-name = "windows_aarch64_msvc"
-version = "0.52.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
-
-[[package]]
-name = "windows_i686_gnu"
-version = "0.52.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
-
-[[package]]
-name = "windows_i686_gnullvm"
-version = "0.52.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
-
-[[package]]
-name = "windows_i686_msvc"
-version = "0.52.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
-
-[[package]]
-name = "windows_x86_64_gnu"
-version = "0.52.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
-
-[[package]]
-name = "windows_x86_64_gnullvm"
-version = "0.52.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
-
-[[package]]
-name = "windows_x86_64_msvc"
-version = "0.52.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
-
-[[package]]
-name = "xz2"
-version = "0.1.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "388c44dc09d76f1536602ead6d325eb532f5c122f17782bd57fb47baeeb767e2"
-dependencies = [
- "lzma-sys",
-]
-
-[[package]]
-name = "zerocopy"
-version = "0.7.35"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0"
-dependencies = [
- "byteorder",
- "zerocopy-derive",
-]
-
-[[package]]
-name = "zerocopy-derive"
-version = "0.7.35"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn 2.0.75",
-]
-
-[[package]]
-name = "zstd"
-version = "0.13.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fcf2b778a664581e31e389454a7072dab1647606d44f7feea22cd5abb9c9f3f9"
-dependencies = [
- "zstd-safe",
-]
-
-[[package]]
-name = "zstd-safe"
-version = "7.2.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "54a3ab4db68cea366acc5c897c7b4d4d1b8994a9cd6e6f841f8964566a419059"
-dependencies = [
- "zstd-sys",
-]
-
-[[package]]
-name = "zstd-sys"
-version = "2.0.12+zstd.1.5.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0a4e40c320c3cb459d9a9ff6de98cff88f4751ee9275d140e2be94a2b74e4c13"
-dependencies = [
- "cc",
- "pkg-config",
-]