This is an automated email from the ASF dual-hosted git repository. hsun pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/incubator-teaclave.git
commit 229c09f28928e4c06fcbce3874b5f7603d757e52 Author: GeminiCarrie <[email protected]> AuthorDate: Wed Jun 14 08:01:13 2023 +0000 Add function builtin-ordered-set-join --- .licenserc.yaml | 1 + cmake/tomls/Cargo.sgx_trusted_lib.lock | 60 ++++--- cmake/tomls/Cargo.sgx_trusted_lib.toml | 1 + cmake/tomls/Cargo.sgx_untrusted_app.lock | 22 +++ executor/Cargo.toml | 2 + executor/src/builtin.rs | 4 +- function/Cargo.toml | 1 + function/README.md | 3 + function/src/lib.rs | 3 + function/src/ordered_set_join.rs | 190 +++++++++++++++++++++ .../fixtures/functions/ordered_set_join/join0.csv | 120 +++++++++++++ .../fixtures/functions/ordered_set_join/join1.csv | 125 ++++++++++++++ 12 files changed, 511 insertions(+), 21 deletions(-) diff --git a/.licenserc.yaml b/.licenserc.yaml index ee44f763..8379656b 100644 --- a/.licenserc.yaml +++ b/.licenserc.yaml @@ -21,6 +21,7 @@ header: copyright-owner: Apache Software Foundation paths-ignore: + - '**/*.csv' - '**/*.txt' - '**/*.md' - '**/*.pem' diff --git a/cmake/tomls/Cargo.sgx_trusted_lib.lock b/cmake/tomls/Cargo.sgx_trusted_lib.lock index 0a0856fd..7dfa342d 100644 --- a/cmake/tomls/Cargo.sgx_trusted_lib.lock +++ b/cmake/tomls/Cargo.sgx_trusted_lib.lock @@ -285,6 +285,25 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" +[[package]] +name = "csv" +version = "1.2.2" +source = "git+https://github.com/apache/incubator-teaclave-crates#f29426149751440e96479d2d8f6698a14228ecd9" +dependencies = [ + "csv-core", + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "csv-core" +version = "0.1.10" +source = "git+https://github.com/apache/incubator-teaclave-crates#f29426149751440e96479d2d8f6698a14228ecd9" +dependencies = [ + "memchr", +] + [[package]] name = "ctor" version = "0.1.26" @@ -375,7 +394,7 @@ checksum = "25c7df09945d65ea8d70b3321547ed414bbc540aad5bac6883d021b970f35b04" [[package]] name = "fastfield_codecs" version = "0.3.1" -source = "git+https://github.com/apache/incubator-teaclave-crates#c979a7afdb748716696ce683a250fbb50a98a23f" +source = "git+https://github.com/apache/incubator-teaclave-crates#f29426149751440e96479d2d8f6698a14228ecd9" dependencies = [ "fastdivide", "itertools 0.10.5", @@ -532,7 +551,7 @@ dependencies = [ [[package]] name = "gbdt" version = "0.1.1" -source = "git+https://github.com/apache/incubator-teaclave-crates#ede1f68d891798fe6cf995e33281f01d59be9320" +source = "git+https://github.com/apache/incubator-teaclave-crates#f29426149751440e96479d2d8f6698a14228ecd9" dependencies = [ "cfg-if 0.1.10", "rand", @@ -558,7 +577,7 @@ dependencies = [ [[package]] name = "getrandom" version = "0.2.6" -source = "git+https://github.com/apache/incubator-teaclave-crates#ede1f68d891798fe6cf995e33281f01d59be9320" +source = "git+https://github.com/apache/incubator-teaclave-crates#f29426149751440e96479d2d8f6698a14228ecd9" dependencies = [ "cfg-if 1.0.0", "libc", @@ -741,7 +760,7 @@ dependencies = [ [[package]] name = "image" version = "0.23.14" -source = "git+https://github.com/apache/incubator-teaclave-crates#ede1f68d891798fe6cf995e33281f01d59be9320" +source = "git+https://github.com/apache/incubator-teaclave-crates#f29426149751440e96479d2d8f6698a14228ecd9" dependencies = [ "bytemuck", "byteorder", @@ -995,7 +1014,7 @@ dependencies = [ [[package]] name = "mio" version = "0.8.6" -source = "git+https://github.com/apache/incubator-teaclave-crates#ede1f68d891798fe6cf995e33281f01d59be9320" +source = "git+https://github.com/apache/incubator-teaclave-crates#f29426149751440e96479d2d8f6698a14228ecd9" dependencies = [ "libc", "log", @@ -1148,7 +1167,7 @@ dependencies = [ [[package]] name = "num_cpus" version = "1.14.0" -source = "git+https://github.com/apache/incubator-teaclave-crates#ede1f68d891798fe6cf995e33281f01d59be9320" +source = "git+https://github.com/apache/incubator-teaclave-crates#f29426149751440e96479d2d8f6698a14228ecd9" dependencies = [ "hermit-abi 0.1.19", "libc", @@ -1222,7 +1241,7 @@ checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" [[package]] name = "ownedbytes" version = "0.4.0" -source = "git+https://github.com/apache/incubator-teaclave-crates#c979a7afdb748716696ce683a250fbb50a98a23f" +source = "git+https://github.com/apache/incubator-teaclave-crates#f29426149751440e96479d2d8f6698a14228ecd9" dependencies = [ "stable_deref_trait", ] @@ -1390,7 +1409,7 @@ dependencies = [ [[package]] name = "rand" version = "0.8.5" -source = "git+https://github.com/apache/incubator-teaclave-crates#ede1f68d891798fe6cf995e33281f01d59be9320" +source = "git+https://github.com/apache/incubator-teaclave-crates#f29426149751440e96479d2d8f6698a14228ecd9" dependencies = [ "libc", "rand_chacha", @@ -1400,7 +1419,7 @@ dependencies = [ [[package]] name = "rand_chacha" version = "0.3.1" -source = "git+https://github.com/apache/incubator-teaclave-crates#ede1f68d891798fe6cf995e33281f01d59be9320" +source = "git+https://github.com/apache/incubator-teaclave-crates#f29426149751440e96479d2d8f6698a14228ecd9" dependencies = [ "ppv-lite86", "rand_core 0.6.4 (git+https://github.com/apache/incubator-teaclave-crates)", @@ -1418,7 +1437,7 @@ dependencies = [ [[package]] name = "rand_core" version = "0.6.4" -source = "git+https://github.com/apache/incubator-teaclave-crates#ede1f68d891798fe6cf995e33281f01d59be9320" +source = "git+https://github.com/apache/incubator-teaclave-crates#f29426149751440e96479d2d8f6698a14228ecd9" dependencies = [ "getrandom", ] @@ -1442,7 +1461,7 @@ checksum = "ebac11a9d2e11f2af219b8b8d833b76b1ea0e054aa0e8d8e9e4cbde353bdf019" [[package]] name = "rayon" version = "1.7.0" -source = "git+https://github.com/apache/incubator-teaclave-crates#c979a7afdb748716696ce683a250fbb50a98a23f" +source = "git+https://github.com/apache/incubator-teaclave-crates#f29426149751440e96479d2d8f6698a14228ecd9" dependencies = [ "either", "rayon-core", @@ -1451,7 +1470,7 @@ dependencies = [ [[package]] name = "rayon-core" version = "1.11.0" -source = "git+https://github.com/apache/incubator-teaclave-crates#c979a7afdb748716696ce683a250fbb50a98a23f" +source = "git+https://github.com/apache/incubator-teaclave-crates#f29426149751440e96479d2d8f6698a14228ecd9" dependencies = [ "crossbeam-channel", "crossbeam-deque", @@ -1551,7 +1570,7 @@ dependencies = [ [[package]] name = "ring" version = "0.16.20" -source = "git+https://github.com/apache/incubator-teaclave-crates#ede1f68d891798fe6cf995e33281f01d59be9320" +source = "git+https://github.com/apache/incubator-teaclave-crates#f29426149751440e96479d2d8f6698a14228ecd9" dependencies = [ "cc", "libc", @@ -1590,7 +1609,7 @@ checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" [[package]] name = "rustface" version = "0.1.7" -source = "git+https://github.com/apache/incubator-teaclave-crates#ede1f68d891798fe6cf995e33281f01d59be9320" +source = "git+https://github.com/apache/incubator-teaclave-crates#f29426149751440e96479d2d8f6698a14228ecd9" dependencies = [ "byteorder", "image", @@ -1616,7 +1635,7 @@ dependencies = [ [[package]] name = "rustls" version = "0.19.1" -source = "git+https://github.com/apache/incubator-teaclave-crates#ede1f68d891798fe6cf995e33281f01d59be9320" +source = "git+https://github.com/apache/incubator-teaclave-crates#f29426149751440e96479d2d8f6698a14228ecd9" dependencies = [ "base64 0.13.1", "log", @@ -1647,7 +1666,7 @@ dependencies = [ [[package]] name = "rusty-machine" version = "0.5.4" -source = "git+https://github.com/apache/incubator-teaclave-crates#ede1f68d891798fe6cf995e33281f01d59be9320" +source = "git+https://github.com/apache/incubator-teaclave-crates#f29426149751440e96479d2d8f6698a14228ecd9" dependencies = [ "num 0.1.42", "rand", @@ -2146,7 +2165,7 @@ dependencies = [ [[package]] name = "tantivy" version = "0.19.2" -source = "git+https://github.com/apache/incubator-teaclave-crates#c979a7afdb748716696ce683a250fbb50a98a23f" +source = "git+https://github.com/apache/incubator-teaclave-crates#f29426149751440e96479d2d8f6698a14228ecd9" dependencies = [ "aho-corasick 0.7.20", "arc-swap", @@ -2193,12 +2212,12 @@ dependencies = [ [[package]] name = "tantivy-bitpacker" version = "0.3.0" -source = "git+https://github.com/apache/incubator-teaclave-crates#c979a7afdb748716696ce683a250fbb50a98a23f" +source = "git+https://github.com/apache/incubator-teaclave-crates#f29426149751440e96479d2d8f6698a14228ecd9" [[package]] name = "tantivy-common" version = "0.4.0" -source = "git+https://github.com/apache/incubator-teaclave-crates#c979a7afdb748716696ce683a250fbb50a98a23f" +source = "git+https://github.com/apache/incubator-teaclave-crates#f29426149751440e96479d2d8f6698a14228ecd9" dependencies = [ "byteorder", "ownedbytes", @@ -2218,7 +2237,7 @@ dependencies = [ [[package]] name = "tantivy-query-grammar" version = "0.19.0" -source = "git+https://github.com/apache/incubator-teaclave-crates#c979a7afdb748716696ce683a250fbb50a98a23f" +source = "git+https://github.com/apache/incubator-teaclave-crates#f29426149751440e96479d2d8f6698a14228ecd9" dependencies = [ "combine", "once_cell", @@ -2482,6 +2501,7 @@ version = "0.6.0" dependencies = [ "anyhow", "base64 0.13.1", + "csv", "gbdt", "hex", "image", diff --git a/cmake/tomls/Cargo.sgx_trusted_lib.toml b/cmake/tomls/Cargo.sgx_trusted_lib.toml index 39c2ced7..f22d8229 100644 --- a/cmake/tomls/Cargo.sgx_trusted_lib.toml +++ b/cmake/tomls/Cargo.sgx_trusted_lib.toml @@ -55,6 +55,7 @@ crc = { git = "https://github.com/mrhooray/crc-rs", rev = "86696be simple_asn1 = { git = "https://github.com/acw/simple_asn1", rev = "7db7a48" } # SGX crates +csv = { git = "https://github.com/apache/incubator-teaclave-crates" } gbdt = { git = "https://github.com/apache/incubator-teaclave-crates" } getrandom = { git = "https://github.com/apache/incubator-teaclave-crates" } image = { git = "https://github.com/apache/incubator-teaclave-crates" } diff --git a/cmake/tomls/Cargo.sgx_untrusted_app.lock b/cmake/tomls/Cargo.sgx_untrusted_app.lock index 935c8877..3dba2cd6 100644 --- a/cmake/tomls/Cargo.sgx_untrusted_app.lock +++ b/cmake/tomls/Cargo.sgx_untrusted_app.lock @@ -228,6 +228,27 @@ dependencies = [ "cfg-if 1.0.0", ] +[[package]] +name = "csv" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "626ae34994d3d8d668f4269922248239db4ae42d538b14c398b74a52208e8086" +dependencies = [ + "csv-core", + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "csv-core" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b2466559f260f48ad25fe6317b3c8dac77b5bdb5763ac7d9d6103530663bc90" +dependencies = [ + "memchr", +] + [[package]] name = "ctor" version = "0.1.26" @@ -2259,6 +2280,7 @@ version = "0.6.0" dependencies = [ "anyhow", "base64 0.13.1", + "csv", "gbdt", "hex", "image", diff --git a/executor/Cargo.toml b/executor/Cargo.toml index 44caaa21..5b392004 100644 --- a/executor/Cargo.toml +++ b/executor/Cargo.toml @@ -60,6 +60,7 @@ full_builtin_function = [ "builtin_logistic_regression_train", "builtin_password_check", "builtin_online_decrypt", + "builtin_ordered_set_join", "builtin_ordered_set_intersect", "builtin_principal_components_analysis", "builtin_private_join_and_compute", @@ -74,6 +75,7 @@ builtin_logistic_regression_predict = [] builtin_logistic_regression_train = [] builtin_password_check = [] builtin_online_decrypt = [] +builtin_ordered_set_join = [] builtin_ordered_set_intersect = [] builtin_principal_components_analysis = [] builtin_private_join_and_compute = [] diff --git a/executor/src/builtin.rs b/executor/src/builtin.rs index b0f03605..9f836b14 100644 --- a/executor/src/builtin.rs +++ b/executor/src/builtin.rs @@ -17,7 +17,7 @@ use teaclave_function::{ Echo, FaceDetection, GbdtPredict, GbdtTrain, LogisticRegressionPredict, - LogisticRegressionTrain, OnlineDecrypt, OrderedSetIntersect, PasswordCheck, + LogisticRegressionTrain, OnlineDecrypt, OrderedSetIntersect, OrderedSetJoin, PasswordCheck, PrincipalComponentsAnalysis, PrivateJoinAndCompute, RsaSign, }; use teaclave_types::{FunctionArguments, FunctionRuntime, TeaclaveExecutor}; @@ -52,6 +52,8 @@ impl TeaclaveExecutor for BuiltinFunctionExecutor { OnlineDecrypt::NAME => OnlineDecrypt::new().run(arguments, runtime), #[cfg(feature = "builtin_private_join_and_compute")] PrivateJoinAndCompute::NAME => PrivateJoinAndCompute::new().run(arguments, runtime), + #[cfg(feature = "builtin_ordered_set_join")] + OrderedSetJoin::NAME => OrderedSetJoin::new().run(arguments, runtime), #[cfg(feature = "builtin_ordered_set_intersect")] OrderedSetIntersect::NAME => OrderedSetIntersect::new().run(arguments, runtime), #[cfg(feature = "builtin_rsa_sign")] diff --git a/function/Cargo.toml b/function/Cargo.toml index bb2a1839..64e1ad71 100644 --- a/function/Cargo.toml +++ b/function/Cargo.toml @@ -50,6 +50,7 @@ enclave_unit_test = [ [dependencies] log = { version = "0.4.17", features = ["release_max_level_info"] } anyhow = { version = "1.0.26" } +csv = { version = "1" } serde_json = { version = "1.0.39" } serde = { version = "1.0.92", features = ["derive"] } thiserror = { version = "1.0.9" } diff --git a/function/README.md b/function/README.md index c27adc0f..a89cac7c 100644 --- a/function/README.md +++ b/function/README.md @@ -24,6 +24,9 @@ Currently, we have these built-in functions: intersection of their ordered sets without revealing anything except for the elements in the intersection. Users should calculate hash values of each item and upload them as a sorted list. + - `builtin-ordered-set-join`: Allow two parties to combine their CSV files in a unique + and sorted column. The CSV files uploaded by users should be sorted by the specified + column. - `builtin-rsa-sign`: Signing data with RSA key. - `builtin-face-detection`: An implementation of Funnel-Structured cascade, which is designed for real-time multi-view face detection. diff --git a/function/src/lib.rs b/function/src/lib.rs index 789b4a68..1f77b2e5 100644 --- a/function/src/lib.rs +++ b/function/src/lib.rs @@ -25,6 +25,7 @@ mod logistic_regression_predict; mod logistic_regression_train; mod online_decrypt; mod ordered_set_intersect; +mod ordered_set_join; mod password_check; mod principal_components_analysis; mod private_join_and_compute; @@ -38,6 +39,7 @@ pub use logistic_regression_predict::LogisticRegressionPredict; pub use logistic_regression_train::LogisticRegressionTrain; pub use online_decrypt::OnlineDecrypt; pub use ordered_set_intersect::OrderedSetIntersect; +pub use ordered_set_join::OrderedSetJoin; pub use password_check::PasswordCheck; pub use principal_components_analysis::PrincipalComponentsAnalysis; pub use private_join_and_compute::PrivateJoinAndCompute; @@ -58,6 +60,7 @@ pub mod tests { logistic_regression_train::tests::run_tests(), password_check::tests::run_tests(), online_decrypt::tests::run_tests(), + ordered_set_join::tests::run_tests(), ordered_set_intersect::tests::run_tests(), principal_components_analysis::tests::run_tests(), private_join_and_compute::tests::run_tests(), diff --git a/function/src/ordered_set_join.rs b/function/src/ordered_set_join.rs new file mode 100644 index 00000000..9650eb96 --- /dev/null +++ b/function/src/ordered_set_join.rs @@ -0,0 +1,190 @@ +// 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 anyhow::{anyhow, ensure}; +use csv::{ReaderBuilder, StringRecord, Writer}; +use std::cmp; +use std::convert::TryFrom; +use teaclave_types::{FunctionArguments, FunctionRuntime}; + +// Input data should be sorted by the specified index column. +const IN_DATA1: &str = "input_data1"; +const IN_DATA2: &str = "input_data2"; +// fusion output data +const OUT_RESULT: &str = "output_result"; + +#[derive(Default)] +pub struct OrderedSetJoin; + +#[derive(serde::Deserialize)] +pub struct OrderedSetJoinArguments { + // Start from 0. + left_column: usize, + right_column: usize, + ascending: bool, + // If it is set to true, drop the selected column of all files from the results. + // If it is set to false, only keep the selected column of the first file. + drop: bool, +} + +impl TryFrom<FunctionArguments> for OrderedSetJoinArguments { + type Error = anyhow::Error; + + fn try_from(arguments: FunctionArguments) -> Result<Self, Self::Error> { + use anyhow::Context; + serde_json::from_str(&arguments.into_string()).context("Cannot deserialize arguments") + } +} + +impl OrderedSetJoin { + pub const NAME: &'static str = "builtin-ordered-set-join"; + + pub fn new() -> Self { + Default::default() + } + + pub fn run( + &self, + arguments: FunctionArguments, + runtime: FunctionRuntime, + ) -> anyhow::Result<String> { + let args = OrderedSetJoinArguments::try_from(arguments)?; + let mut rdr1 = ReaderBuilder::new() + .has_headers(false) + .from_reader(runtime.open_input(IN_DATA1)?); + let mut rdr2 = ReaderBuilder::new() + .has_headers(false) + .from_reader(runtime.open_input(IN_DATA2)?); + let mut wtr = Writer::from_writer(runtime.create_output(OUT_RESULT)?); + + let mut record1 = StringRecord::new(); + let mut record2 = StringRecord::new(); + let mut count = 0; + ensure!(rdr1.read_record(&mut record1)?, "input1 is empty"); + ensure!(rdr2.read_record(&mut record2)?, "input2 is empty"); + + loop { + let fields1 = record1 + .get(args.left_column) + .ok_or_else(|| anyhow!("invalid index"))?; + let fields2 = record2 + .get(args.right_column) + .ok_or_else(|| anyhow!("invalid index"))?; + let order = &fields1.cmp(fields2); + + match order { + cmp::Ordering::Equal => { + let new_record1 = if args.drop { + drop_column(&record1, args.left_column) + } else { + record1.clone() + }; + let new_record2 = drop_column(&record2, args.right_column); + wtr.write_record(new_record1.iter().chain(&new_record2))?; + count += 1; + if !rdr1.read_record(&mut record1)? || !rdr2.read_record(&mut record2)? { + break; + } + } + cmp::Ordering::Less => { + if args.ascending { + if !rdr1.read_record(&mut record1)? { + break; + } + } else if !rdr2.read_record(&mut record2)? { + break; + } + } + cmp::Ordering::Greater => { + if args.ascending { + if !rdr2.read_record(&mut record2)? { + break; + } + } else if !rdr1.read_record(&mut record1)? { + break; + } + } + } + } + + Ok(format!("{} records", count)) + } +} + +pub fn drop_column(column: &StringRecord, index: usize) -> StringRecord { + StringRecord::from( + column + .iter() + .enumerate() + .filter_map(|(i, e)| if i != index { Some(e) } else { None }) + .collect::<Vec<_>>(), + ) +} + +#[cfg(feature = "enclave_unit_test")] +pub mod tests { + use super::*; + use serde_json::json; + use std::path::Path; + use std::untrusted::fs; + use teaclave_crypto::*; + use teaclave_runtime::*; + use teaclave_test_utils::*; + use teaclave_types::*; + + pub fn run_tests() -> bool { + run_tests!(test_ordered_set_join) + } + + fn test_ordered_set_join() { + let arguments = FunctionArguments::from_json(json!({ + "left_column": 0, + "right_column": 0, + "ascending":true, + "drop":true + })) + .unwrap(); + + let base = Path::new("fixtures/functions/ordered_set_join"); + + let user1_input = base.join("join0.csv"); + let output = base.join("output_join.csv"); + + let user2_input = base.join("join1.csv"); + + let input_files = StagedFiles::new(hashmap!( + IN_DATA1 => + StagedFileInfo::new(&user1_input, TeaclaveFile128Key::random(), FileAuthTag::mock()), + IN_DATA2 => + StagedFileInfo::new(&user2_input, TeaclaveFile128Key::random(), FileAuthTag::mock()), + )); + + let output_files = StagedFiles::new(hashmap!( + OUT_RESULT => + StagedFileInfo::new(&output, TeaclaveFile128Key::random(), FileAuthTag::mock()), + )); + + let runtime = Box::new(RawIoRuntime::new(input_files, output_files)); + let summary = OrderedSetJoin::new().run(arguments, runtime).unwrap(); + assert_eq!("120 records".to_string(), summary); + + let expected_output = "fixtures/functions/gbdt_training/train.txt"; + let result = fs::read_to_string(&output).unwrap(); + let expected = fs::read_to_string(expected_output).unwrap(); + assert_eq!(result.trim(), expected.trim()); + } +} diff --git a/tests/fixtures/functions/ordered_set_join/join0.csv b/tests/fixtures/functions/ordered_set_join/join0.csv new file mode 100644 index 00000000..67881a3e --- /dev/null +++ b/tests/fixtures/functions/ordered_set_join/join0.csv @@ -0,0 +1,120 @@ +100000,4.8,3.0 +100001,5.1,3.7 +100002,6.7,2.5 +100003,5.5,2.4 +100004,4.8,3.4 +100005,6.9,3.1 +100006,5.4,3.9 +100007,6.9,3.1 +100008,6.5,3.0 +100009,5.0,2.3 +100010,5.4,3.4 +100011,5.7,4.4 +100012,5.0,3.3 +100013,4.4,3.2 +100014,4.9,3.1 +100015,6.9,3.2 +100016,7.7,3.8 +100017,5.5,2.4 +100018,7.7,3.0 +100019,6.4,2.8 +100020,5.8,2.7 +100021,4.6,3.6 +100022,7.2,3.2 +100023,6.3,3.3 +100024,6.7,3.3 +100025,6.5,3.2 +100026,6.9,3.1 +100027,6.1,2.6 +100028,5.9,3.0 +100029,4.4,2.9 +100030,5.8,2.7 +100031,4.8,3.1 +100032,6.4,2.8 +100033,5.1,3.5 +100034,6.3,3.3 +100035,6.0,2.7 +100036,5.4,3.0 +100037,5.5,2.6 +100038,6.4,3.1 +100039,6.3,3.4 +100040,5.2,3.5 +100041,6.5,3.0 +100042,5.6,2.9 +100043,6.0,2.2 +100044,5.4,3.4 +100045,4.9,3.1 +100046,4.6,3.1 +100047,5.1,2.5 +100048,5.0,2.0 +100049,5.8,2.7 +100050,5.9,3.2 +100051,6.8,3.2 +100052,6.6,2.9 +100053,5.0,3.2 +100054,6.8,2.8 +100055,5.6,3.0 +100056,5.0,3.6 +100057,5.6,2.7 +100058,4.4,3.0 +100059,5.2,3.4 +100060,6.1,3.0 +100061,5.0,3.0 +100062,4.9,2.5 +100063,4.7,3.2 +100064,4.3,3.0 +100065,7.9,3.8 +100066,6.4,3.2 +100067,6.4,2.9 +100068,5.1,3.8 +100069,5.2,2.7 +100070,5.1,3.4 +100071,6.0,3.4 +100072,4.7,3.2 +100073,4.8,3.0 +100074,5.6,2.5 +100075,6.7,3.0 +100076,6.5,3.0 +100077,4.6,3.2 +100078,6.7,3.3 +100079,6.2,2.8 +100080,5.7,3.8 +100081,6.3,2.8 +100082,5.7,3.0 +100083,6.3,2.3 +100084,4.9,2.4 +100085,7.2,3.6 +100086,5.7,2.8 +100087,5.5,4.2 +100088,6.6,3.0 +100089,5.9,3.0 +100090,5.7,2.8 +100091,6.2,2.2 +100092,5.1,3.3 +100093,6.2,2.9 +100094,6.3,2.5 +100095,5.5,3.5 +100096,5.1,3.8 +100097,6.1,2.8 +100098,6.1,2.8 +100099,5.2,4.1 +100100,5.6,3.0 +100101,6.3,2.7 +100102,5.7,2.5 +100103,5.7,2.6 +100104,6.4,2.7 +100105,7.7,2.8 +100106,5.5,2.3 +100107,5.3,3.7 +100108,6.7,3.1 +100109,6.2,3.4 +100110,5.8,4.0 +100111,7.3,2.9 +100112,6.3,2.9 +100113,5.8,2.8 +100114,6.8,3.0 +100115,5.1,3.8 +100116,6.5,2.8 +100117,7.4,2.8 +100118,4.9,3.0 +100119,5.8,2.7 diff --git a/tests/fixtures/functions/ordered_set_join/join1.csv b/tests/fixtures/functions/ordered_set_join/join1.csv new file mode 100644 index 00000000..b58f219b --- /dev/null +++ b/tests/fixtures/functions/ordered_set_join/join1.csv @@ -0,0 +1,125 @@ +100000,1.4,0.3,3.0 +100001,1.5,0.4,3.0 +100002,5.8,1.8,2.0 +100003,3.7,1.0,1.0 +100004,1.6,0.2,3.0 +100005,5.4,2.1,2.0 +100006,1.7,0.4,3.0 +100007,4.9,1.5,1.0 +100008,5.5,1.8,2.0 +100009,3.3,1.0,1.0 +100010,1.5,0.4,3.0 +100011,1.5,0.4,3.0 +100012,1.4,0.2,3.0 +100013,1.3,0.2,3.0 +100014,1.5,0.2,3.0 +100015,5.7,2.3,2.0 +100016,6.7,2.2,2.0 +100017,3.8,1.1,1.0 +100018,6.1,2.3,2.0 +100019,5.6,2.2,2.0 +100020,5.1,1.9,2.0 +100021,1.0,0.2,3.0 +100022,6.0,1.8,2.0 +100023,4.7,1.6,1.0 +100024,5.7,2.5,2.0 +100025,5.1,2.0,2.0 +100026,5.1,2.3,2.0 +100027,5.6,1.4,2.0 +100028,4.2,1.5,1.0 +100029,1.4,0.2,3.0 +100030,4.1,1.0,1.0 +100031,1.6,0.2,3.0 +100032,5.6,2.1,2.0 +100033,1.4,0.3,3.0 +100034,6.0,2.5,2.0 +100035,5.1,1.6,1.0 +100036,4.5,1.5,1.0 +100037,4.4,1.2,1.0 +100038,5.5,1.8,2.0 +100039,5.6,2.4,2.0 +100040,1.5,0.2,3.0 +100041,5.8,2.2,2.0 +100042,3.6,1.3,1.0 +100043,5.0,1.5,2.0 +100044,1.7,0.2,3.0 +100045,1.5,0.1,3.0 +100046,1.5,0.2,3.0 +100047,3.0,1.1,1.0 +100048,3.5,1.0,1.0 +100049,3.9,1.2,1.0 +100050,4.8,1.8,1.0 +100051,5.9,2.3,2.0 +100052,4.6,1.3,1.0 +100053,1.2,0.2,3.0 +100054,4.8,1.4,1.0 +100055,4.5,1.5,1.0 +100056,1.4,0.2,3.0 +100057,4.2,1.3,1.0 +100058,1.3,0.2,3.0 +100059,1.4,0.2,3.0 +100060,4.6,1.4,1.0 +100061,1.6,0.2,3.0 +100062,4.5,1.7,2.0 +100063,1.6,0.2,3.0 +100064,1.1,0.1,3.0 +100065,6.4,2.0,2.0 +100066,4.5,1.5,1.0 +100067,4.3,1.3,1.0 +100068,1.9,0.4,3.0 +100069,3.9,1.4,1.0 +100070,1.5,0.2,3.0 +100071,4.5,1.6,1.0 +100072,1.3,0.2,3.0 +100073,1.4,0.1,3.0 +100074,3.9,1.1,1.0 +100075,5.0,1.7,1.0 +100076,5.2,2.0,2.0 +100077,1.4,0.2,3.0 +100078,5.7,2.1,2.0 +100079,4.8,1.8,2.0 +100080,1.7,0.3,3.0 +100081,5.1,1.5,2.0 +100082,4.2,1.2,1.0 +100083,4.4,1.3,1.0 +100084,3.3,1.0,1.0 +100085,6.1,2.5,2.0 +100086,4.5,1.3,1.0 +100087,1.4,0.2,3.0 +100088,4.4,1.4,1.0 +100089,5.1,1.8,2.0 +100090,4.1,1.3,1.0 +100091,4.5,1.5,1.0 +100092,1.7,0.5,3.0 +100093,4.3,1.3,1.0 +100094,5.0,1.9,2.0 +100095,1.3,0.2,3.0 +100096,1.5,0.3,3.0 +100097,4.7,1.2,1.0 +100098,4.0,1.3,1.0 +100099,1.5,0.1,3.0 +100100,4.1,1.3,1.0 +100101,4.9,1.8,2.0 +100102,5.0,2.0,2.0 +100103,3.5,1.0,1.0 +100104,5.3,1.9,2.0 +100105,6.7,2.0,2.0 +100106,4.0,1.3,1.0 +100107,1.5,0.2,3.0 +100108,4.4,1.4,1.0 +100109,5.4,2.3,2.0 +100110,1.2,0.2,3.0 +100111,6.3,1.8,2.0 +100112,5.6,1.8,2.0 +100113,5.1,2.4,2.0 +100114,5.5,2.1,2.0 +100115,1.6,0.2,3.0 +100116,4.6,1.5,1.0 +100117,6.1,1.9,2.0 +100118,1.4,0.2,3.0 +100119,5.1,1.9,2.0 +100120,5.1,1.9,2.0 +100121,1.4,0.2,3.0 +100122,5.1,1.9,2.0 +100123,5.1,1.9,2.0 +100124,3.3,0.1,3.0 --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
