-
Notifications
You must be signed in to change notification settings - Fork 1.9k
(#4462) Postgres compatibility tests using sqllogictest #4834
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
236bdc8
d00a1de
8150314
d5369d0
d06ef0f
f8c122b
ff1e089
55a49af
1a78bc6
ad4acb5
fa7866a
70aa1c9
9bee2a3
4de00da
de741df
44bb1de
b7b9e70
8453ed1
5c2fc55
4c7734d
81500c8
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,21 @@ | ||
| CREATE TABLE aggregate_test_100_by_sql | ||
| ( | ||
| c1 character varying NOT NULL, | ||
| c2 smallint NOT NULL, | ||
| c3 smallint NOT NULL, | ||
| c4 smallint, | ||
| c5 integer, | ||
| c6 bigint NOT NULL, | ||
| c7 smallint NOT NULL, | ||
| c8 integer NOT NULL, | ||
| c9 bigint NOT NULL, | ||
| c10 character varying NOT NULL, | ||
| c11 real NOT NULL, | ||
| c12 double precision NOT NULL, | ||
| c13 character varying NOT NULL | ||
| ); | ||
|
|
||
| COPY aggregate_test_100_by_sql | ||
| FROM '/opt/data/csv/aggregate_test_100.csv' | ||
| DELIMITER ',' | ||
| CSV HEADER; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,90 @@ | ||
| // Licensed to the Apache Software Foundation (ASF) under one | ||
| // or more contributor license agreements. See the NOTICE file | ||
| // distributed with this work for additional information | ||
| // regarding copyright ownership. The ASF licenses this file | ||
| // to you under the Apache License, Version 2.0 (the | ||
| // "License"); you may not use this file except in compliance | ||
| // with the License. You may obtain a copy of the License at | ||
| // | ||
| // http://www.apache.org/licenses/LICENSE-2.0 | ||
| // | ||
| // Unless required by applicable law or agreed to in writing, | ||
| // software distributed under the License is distributed on an | ||
| // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | ||
| // KIND, either express or implied. See the License for the | ||
| // specific language governing permissions and limitations | ||
| // under the License. | ||
|
|
||
| use bigdecimal::BigDecimal; | ||
| use half::f16; | ||
| use rust_decimal::prelude::*; | ||
| use rust_decimal::Decimal; | ||
|
|
||
| pub const NULL_STR: &str = "NULL"; | ||
|
|
||
| pub fn bool_to_str(value: bool) -> String { | ||
| if value { | ||
| "true".to_string() | ||
| } else { | ||
| "false".to_string() | ||
| } | ||
| } | ||
|
|
||
| pub fn varchar_to_str(value: &str) -> String { | ||
| if value.is_empty() { | ||
| "(empty)".to_string() | ||
| } else { | ||
| value.to_string() | ||
| } | ||
| } | ||
|
|
||
| pub fn f16_to_str(value: f16) -> String { | ||
| if value.is_nan() { | ||
| "NaN".to_string() | ||
| } else if value == f16::INFINITY { | ||
| "Infinity".to_string() | ||
| } else if value == f16::NEG_INFINITY { | ||
| "-Infinity".to_string() | ||
| } else { | ||
| big_decimal_to_str(BigDecimal::from_str(&value.to_string()).unwrap()) | ||
| } | ||
| } | ||
|
|
||
| pub fn f32_to_str(value: f32) -> String { | ||
| if value.is_nan() { | ||
| "NaN".to_string() | ||
| } else if value == f32::INFINITY { | ||
| "Infinity".to_string() | ||
| } else if value == f32::NEG_INFINITY { | ||
| "-Infinity".to_string() | ||
| } else { | ||
| big_decimal_to_str(BigDecimal::from_str(&value.to_string()).unwrap()) | ||
| } | ||
| } | ||
|
|
||
| pub fn f64_to_str(value: f64) -> String { | ||
| if value.is_nan() { | ||
| "NaN".to_string() | ||
| } else if value == f64::INFINITY { | ||
| "Infinity".to_string() | ||
| } else if value == f64::NEG_INFINITY { | ||
| "-Infinity".to_string() | ||
| } else { | ||
| big_decimal_to_str(BigDecimal::from_str(&value.to_string()).unwrap()) | ||
| } | ||
| } | ||
|
|
||
| pub fn i128_to_str(value: i128, scale: u32) -> String { | ||
| big_decimal_to_str( | ||
| BigDecimal::from_str(&Decimal::from_i128_with_scale(value, scale).to_string()) | ||
| .unwrap(), | ||
| ) | ||
| } | ||
|
|
||
| pub fn decimal_to_str(value: Decimal) -> String { | ||
| big_decimal_to_str(BigDecimal::from_str(&value.to_string()).unwrap()) | ||
| } | ||
|
|
||
| pub fn big_decimal_to_str(value: BigDecimal) -> String { | ||
| value.round(12).normalized().to_string() | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. All numbers are rounded to
|
||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,100 @@ | ||
| // Licensed to the Apache Software Foundation (ASF) under one | ||
| // or more contributor license agreements. See the NOTICE file | ||
| // distributed with this work for additional information | ||
| // regarding copyright ownership. The ASF licenses this file | ||
| // to you under the Apache License, Version 2.0 (the | ||
| // "License"); you may not use this file except in compliance | ||
| // with the License. You may obtain a copy of the License at | ||
| // | ||
| // http://www.apache.org/licenses/LICENSE-2.0 | ||
| // | ||
| // Unless required by applicable law or agreed to in writing, | ||
| // software distributed under the License is distributed on an | ||
| // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | ||
| // KIND, either express or implied. See the License for the | ||
| // specific language governing permissions and limitations | ||
| // under the License. | ||
|
|
||
| use std::time::Duration; | ||
|
|
||
| use sqllogictest::DBOutput; | ||
|
|
||
| use self::error::{DFSqlLogicTestError, Result}; | ||
| use async_trait::async_trait; | ||
| use datafusion::arrow::record_batch::RecordBatch; | ||
| use datafusion::prelude::SessionContext; | ||
| use datafusion_sql::parser::{DFParser, Statement}; | ||
| use insert::insert; | ||
| use sqlparser::ast::Statement as SQLStatement; | ||
|
|
||
| mod error; | ||
| mod insert; | ||
| mod normalize; | ||
|
|
||
| pub struct DataFusion { | ||
melgenek marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| ctx: SessionContext, | ||
| file_name: String, | ||
| is_pg_compatibility_test: bool, | ||
| } | ||
|
|
||
| impl DataFusion { | ||
| pub fn new( | ||
| ctx: SessionContext, | ||
| file_name: String, | ||
| postgres_compatible: bool, | ||
| ) -> Self { | ||
| Self { | ||
| ctx, | ||
| file_name, | ||
| is_pg_compatibility_test: postgres_compatible, | ||
| } | ||
| } | ||
| } | ||
|
|
||
| #[async_trait] | ||
| impl sqllogictest::AsyncDB for DataFusion { | ||
| type Error = DFSqlLogicTestError; | ||
|
|
||
| async fn run(&mut self, sql: &str) -> Result<DBOutput> { | ||
| println!("[{}] Running query: \"{}\"", self.file_name, sql); | ||
| let result = run_query(&self.ctx, sql, self.is_pg_compatibility_test).await?; | ||
| Ok(result) | ||
| } | ||
|
|
||
| /// Engine name of current database. | ||
| fn engine_name(&self) -> &str { | ||
| "DataFusion" | ||
| } | ||
|
|
||
| /// [`Runner`] calls this function to perform sleep. | ||
| /// | ||
| /// The default implementation is `std::thread::sleep`, which is universial to any async runtime | ||
| /// but would block the current thread. If you are running in tokio runtime, you should override | ||
| /// this by `tokio::time::sleep`. | ||
| async fn sleep(dur: Duration) { | ||
| tokio::time::sleep(dur).await; | ||
| } | ||
| } | ||
|
|
||
| async fn run_query( | ||
| ctx: &SessionContext, | ||
| sql: impl Into<String>, | ||
| is_pg_compatibility_test: bool, | ||
| ) -> Result<DBOutput> { | ||
| let sql = sql.into(); | ||
| // Check if the sql is `insert` | ||
| if let Ok(mut statements) = DFParser::parse_sql(&sql) { | ||
| let statement0 = statements.pop_front().expect("at least one SQL statement"); | ||
| if let Statement::Statement(statement) = statement0 { | ||
| let statement = *statement; | ||
| if matches!(&statement, SQLStatement::Insert { .. }) { | ||
| return insert(ctx, statement).await; | ||
| } | ||
| } | ||
| } | ||
| let df = ctx.sql(sql.as_str()).await?; | ||
| let results: Vec<RecordBatch> = df.collect().await?; | ||
| let formatted_batches = | ||
| normalize::convert_batches(results, is_pg_compatibility_test)?; | ||
| Ok(formatted_batches) | ||
| } | ||
Uh oh!
There was an error while loading. Please reload this page.