diff --git a/funnel-udf/Cargo.lock b/funnel-udf/Cargo.lock index c24bd48c14..858f3a3da5 100644 --- a/funnel-udf/Cargo.lock +++ b/funnel-udf/Cargo.lock @@ -2,12 +2,27 @@ # It is not intended for manual editing. version = 4 +[[package]] +name = "aho-corasick" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301" +dependencies = [ + "memchr", +] + [[package]] name = "autocfg" version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" +[[package]] +name = "bumpalo" +version = "3.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43" + [[package]] name = "cfg-if" version = "1.0.0" @@ -20,33 +35,106 @@ version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" +[[package]] +name = "equivalent" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" + [[package]] name = "funnels" version = "0.1.0" dependencies = [ "itertools", "ordered-float", + "rstest", "serde", "serde_json", "uuid", ] [[package]] -name = "getrandom" -version = "0.2.15" +name = "futures-core" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" +checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" + +[[package]] +name = "futures-macro" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "futures-task" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" + +[[package]] +name = "futures-timer" +version = "3.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f288b0a4f20f9a56b5d1da57e2227c661b7b16168e2f72365f57b63326e29b24" + +[[package]] +name = "futures-util" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" +dependencies = [ + "futures-core", + "futures-macro", + "futures-task", + "pin-project-lite", + "pin-utils", + "slab", +] + +[[package]] +name = "getrandom" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" dependencies = [ "cfg-if", "libc", - "wasi", + "r-efi", + "wasip2", +] + +[[package]] +name = "glob" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0cc23270f6e1808e30a928bdc84dea0b9b4136a8bc82338574f23baf47bbd280" + +[[package]] +name = "hashbrown" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5419bdc4f6a9207fbeba6d11b604d481addf78ecd10c11ad51e76c2f6482748d" + +[[package]] +name = "indexmap" +version = "2.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6717a8d2a5a929a1a2eb43a12812498ed141a0bcfb7e8f7844fbdbe4303bba9f" +dependencies = [ + "equivalent", + "hashbrown", ] [[package]] name = "itertools" -version = "0.11.0" +version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1c173a5686ce8bfa551b3563d0c2170bf24ca44da99c7ca4bfdab5418c3fe57" +checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285" dependencies = [ "either", ] @@ -57,6 +145,16 @@ version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" +[[package]] +name = "js-sys" +version = "0.3.82" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b011eec8cc36da2aab2d5cff675ec18454fad408585853910a202391cf9f8e65" +dependencies = [ + "once_cell", + "wasm-bindgen", +] + [[package]] name = "libc" version = "0.2.159" @@ -79,14 +177,41 @@ dependencies = [ ] [[package]] -name = "ordered-float" -version = "5.0.0" +name = "once_cell" +version = "1.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2c1f9f56e534ac6a9b8a4600bdf0f530fb393b5f393e7b4d03489c3cf0c3f01" +checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" + +[[package]] +name = "ordered-float" +version = "5.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f4779c6901a562440c3786d08192c6fbda7c1c2060edd10006b05ee35d10f2d" dependencies = [ "num-traits", ] +[[package]] +name = "pin-project-lite" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "proc-macro-crate" +version = "3.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "219cb19e96be00ab2e37d6e299658a0cfa83e52429179969b0f0121b4ac46983" +dependencies = [ + "toml_edit", +] + [[package]] name = "proc-macro2" version = "1.0.86" @@ -105,6 +230,91 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "r-efi" +version = "5.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" + +[[package]] +name = "regex" +version = "1.12.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "843bc0191f75f3e22651ae5f1e72939ab2f72a4bc30fa80a066bd66edefc24d4" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5276caf25ac86c8d810222b3dbb938e512c55c6831a10f3e6ed1c93b84041f1c" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a2d987857b319362043e95f5353c0535c1f58eec5336fdfcf626430af7def58" + +[[package]] +name = "relative-path" +version = "1.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba39f3699c378cd8970968dcbff9c43159ea4cfbd88d43c00b22f2ef10a435d2" + +[[package]] +name = "rstest" +version = "0.26.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f5a3193c063baaa2a95a33f03035c8a72b83d97a54916055ba22d35ed3839d49" +dependencies = [ + "futures-timer", + "futures-util", + "rstest_macros", +] + +[[package]] +name = "rstest_macros" +version = "0.26.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c845311f0ff7951c5506121a9ad75aec44d083c31583b2ea5a30bcb0b0abba0" +dependencies = [ + "cfg-if", + "glob", + "proc-macro-crate", + "proc-macro2", + "quote", + "regex", + "relative-path", + "rustc_version", + "syn", + "unicode-ident", +] + +[[package]] +name = "rustc_version" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" +dependencies = [ + "semver", +] + +[[package]] +name = "rustversion" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" + [[package]] name = "ryu" version = "1.0.18" @@ -112,19 +322,35 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" [[package]] -name = "serde" -version = "1.0.210" +name = "semver" +version = "1.0.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8e3592472072e6e22e0a54d5904d9febf8508f65fb8552499a1abc7d1078c3a" +checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2" + +[[package]] +name = "serde" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" +dependencies = [ + "serde_core", + "serde_derive", +] + +[[package]] +name = "serde_core" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.210" +version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f" +checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" dependencies = [ "proc-macro2", "quote", @@ -133,27 +359,64 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.128" +version = "1.0.145" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ff5456707a1de34e7e37f2a6fd3d3f808c318259cbd01ab6377795054b483d8" +checksum = "402a6f66d8c709116cf22f558eab210f5a50187f702eb4d7e5ef38d9a7f1c79c" dependencies = [ "itoa", "memchr", "ryu", "serde", + "serde_core", ] [[package]] -name = "syn" -version = "2.0.77" +name = "slab" +version = "0.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f35bcdf61fd8e7be6caf75f429fdca8beb3ed76584befb503b1569faee373ed" +checksum = "7a2ae44ef20feb57a68b23d846850f861394c2e02dc425a50098ae8c90267589" + +[[package]] +name = "syn" +version = "2.0.87" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25aa4ce346d03a6dcd68dd8b4010bcb74e54e62c90c573f394c46eae99aba32d" dependencies = [ "proc-macro2", "quote", "unicode-ident", ] +[[package]] +name = "toml_datetime" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2cdb639ebbc97961c51720f858597f7f24c4fc295327923af55b74c3c724533" +dependencies = [ + "serde_core", +] + +[[package]] +name = "toml_edit" +version = "0.23.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6485ef6d0d9b5d0ec17244ff7eb05310113c3f316f2d14200d4de56b3cb98f8d" +dependencies = [ + "indexmap", + "toml_datetime", + "toml_parser", + "winnow", +] + +[[package]] +name = "toml_parser" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0cbe268d35bdb4bb5a56a2de88d0ad0eb70af5384a99d648cd4b3d04039800e" +dependencies = [ + "winnow", +] + [[package]] name = "unicode-ident" version = "1.0.13" @@ -162,16 +425,81 @@ checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" [[package]] name = "uuid" -version = "1.10.0" +version = "1.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81dfa00651efa65069b0b6b651f4aaa31ba9e3c3ce0137aaad053604ee7e0314" +checksum = "2f87b8aa10b915a06587d0dec516c282ff295b475d94abf425d62b57710070a2" dependencies = [ "getrandom", + "js-sys", "serde", + "wasm-bindgen", ] [[package]] -name = "wasi" -version = "0.11.0+wasi-snapshot-preview1" +name = "wasip2" +version = "1.0.1+wasi-0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" +checksum = "0562428422c63773dad2c345a1882263bbf4d65cf3f42e90921f787ef5ad58e7" +dependencies = [ + "wit-bindgen", +] + +[[package]] +name = "wasm-bindgen" +version = "0.2.105" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da95793dfc411fbbd93f5be7715b0578ec61fe87cb1a42b12eb625caa5c5ea60" +dependencies = [ + "cfg-if", + "once_cell", + "rustversion", + "wasm-bindgen-macro", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.105" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04264334509e04a7bf8690f2384ef5265f05143a4bff3889ab7a3269adab59c2" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.105" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "420bc339d9f322e562942d52e115d57e950d12d88983a14c79b86859ee6c7ebc" +dependencies = [ + "bumpalo", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.105" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76f218a38c84bcb33c25ec7059b07847d465ce0e0a76b995e134a45adcb6af76" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "winnow" +version = "0.7.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21a0236b59786fed61e2a80582dd500fe61f18b5dca67a4a067d0bc9039339cf" +dependencies = [ + "memchr", +] + +[[package]] +name = "wit-bindgen" +version = "0.46.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f17a85883d4e6d00e8a97c586de764dabcc06133f7f1d55dce5cdc070ad7fe59" diff --git a/funnel-udf/Cargo.toml b/funnel-udf/Cargo.toml index caa5cf6be6..0e5b1d21c9 100644 --- a/funnel-udf/Cargo.toml +++ b/funnel-udf/Cargo.toml @@ -4,11 +4,14 @@ version = "0.1.0" edition = "2021" [dependencies] -serde = { version = "1.0.104", features = ["derive"] } -serde_json = "1.0.48" -itertools = "0.11" -uuid = { version = "1.10.0", features = ["v4", "serde"] } -ordered-float = "5.0.0" +serde = { version = "1.0.228", features = ["derive"] } +serde_json = "1.0.145" +itertools = "0.14.0" +uuid = { version = "1.18.1", features = ["v4", "serde"] } +ordered-float = "5.1.0" + +[dev-dependencies] +rstest = "0.26.1" [profile.release] lto = true diff --git a/funnel-udf/build.sh b/funnel-udf/build.sh old mode 100644 new mode 100755 diff --git a/funnel-udf/src/main.rs b/funnel-udf/src/main.rs index 104519c4f3..20463b6538 100644 --- a/funnel-udf/src/main.rs +++ b/funnel-udf/src/main.rs @@ -1,3 +1,4 @@ +mod parsing; mod steps; mod trends; mod unordered_steps; diff --git a/funnel-udf/src/parsing.rs b/funnel-udf/src/parsing.rs new file mode 100644 index 0000000000..6bce1788c5 --- /dev/null +++ b/funnel-udf/src/parsing.rs @@ -0,0 +1,58 @@ +use serde::{Deserialize, Deserializer}; +use std::str::FromStr; + +#[derive(Deserialize)] +#[serde(untagged)] +enum U64OrString { + U64(u64), + String(String), +} + +pub fn u64_or_string<'de, D>(deserializer: D) -> Result +where + D: Deserializer<'de>, +{ + match U64OrString::deserialize(deserializer)? { + U64OrString::U64(v) => Ok(v), + U64OrString::String(v) => u64::from_str(&v).map_err(serde::de::Error::custom), + } +} + +#[cfg(test)] +mod tests { + use super::*; + use rstest::rstest; + use serde::Deserialize; + + #[derive(Deserialize)] + struct TestStruct { + #[serde(deserialize_with = "u64_or_string")] + value: u64, + } + + #[rstest] + #[case(r#"{"value": 0}"#, 0)] + #[case(r#"{"value": 12345}"#, 12345)] + #[case(r#"{"value": 67890}"#, 67890)] + #[case(r#"{"value": 18446744073709551615}"#, u64::MAX)] + #[case(r#"{"value": "0"}"#, 0)] + #[case(r#"{"value": "12345"}"#, 12345)] + #[case(r#"{"value": "67890"}"#, 67890)] + #[case(r#"{"value": "18446744073709551615"}"#, u64::MAX)] + fn test_deserialize_u64_valid(#[case] json: &str, #[case] expected: u64) { + let result: TestStruct = serde_json::from_str(json).unwrap(); + assert_eq!(result.value, expected); + } + + #[rstest] + #[case(r#"{"value": "not_a_number"}"#)] + #[case(r#"{"value": "-123"}"#)] + #[case(r#"{"value": ""}"#)] + #[case(r#"{"value": "18446744073709551616"}"#)] // u64::MAX + 1 + #[case(r#"{"value": "12.34"}"#)] + #[case(r#"{"value": " 123 "}"#)] + fn test_deserialize_u64_invalid(#[case] json: &str) { + let result: Result = serde_json::from_str(json); + assert!(result.is_err()); + } +} diff --git a/funnel-udf/src/steps.rs b/funnel-udf/src/steps.rs index f6958f5d92..472198b608 100644 --- a/funnel-udf/src/steps.rs +++ b/funnel-udf/src/steps.rs @@ -1,3 +1,4 @@ +use crate::parsing::u64_or_string; use crate::unordered_steps::AggregateFunnelRowUnordered; use crate::PropVal; use itertools::Itertools; @@ -26,6 +27,7 @@ pub struct Event { #[derive(Deserialize)] pub struct Args { pub num_steps: usize, + #[serde(deserialize_with = "u64_or_string")] pub conversion_window_limit: u64, // In seconds pub breakdown_attribution_type: String, pub funnel_order_type: String, diff --git a/funnel-udf/src/trends.rs b/funnel-udf/src/trends.rs index 041ff7acfb..3d94d6a522 100644 --- a/funnel-udf/src/trends.rs +++ b/funnel-udf/src/trends.rs @@ -1,20 +1,12 @@ +use crate::parsing::u64_or_string; use crate::unordered_trends::AggregateFunnelRowUnordered; use crate::PropVal; use itertools::Itertools; use serde::{Deserialize, Serialize}; use serde_json::{json, Value}; use std::collections::HashMap; -use std::str::FromStr; use uuid::Uuid; -fn deserialize_number_from_string<'de, D>(deserializer: D) -> Result -where - D: serde::Deserializer<'de>, -{ - let s = String::deserialize(deserializer)?; - u64::from_str(&s).map_err(serde::de::Error::custom) -} - #[derive(Clone, Deserialize)] pub struct EnteredTimestamp { pub timestamp: f64, @@ -24,7 +16,7 @@ pub struct EnteredTimestamp { #[derive(Debug, Clone, Deserialize)] pub struct Event { pub timestamp: f64, - #[serde(deserialize_with = "deserialize_number_from_string")] + #[serde(deserialize_with = "u64_or_string")] pub interval_start: u64, pub uuid: Uuid, pub breakdown: PropVal, @@ -36,6 +28,7 @@ pub struct Args { pub from_step: usize, pub to_step: usize, pub num_steps: usize, + #[serde(deserialize_with = "u64_or_string")] pub conversion_window_limit: u64, // In seconds pub breakdown_attribution_type: String, pub funnel_order_type: String, diff --git a/posthog/user_scripts/aggregate_funnel_aarch64 b/posthog/user_scripts/aggregate_funnel_aarch64 index a4b1e0c051..feb7b990f5 100755 Binary files a/posthog/user_scripts/aggregate_funnel_aarch64 and b/posthog/user_scripts/aggregate_funnel_aarch64 differ diff --git a/posthog/user_scripts/aggregate_funnel_x86_64 b/posthog/user_scripts/aggregate_funnel_x86_64 index ae2c298c18..c4f8212f3b 100755 Binary files a/posthog/user_scripts/aggregate_funnel_x86_64 and b/posthog/user_scripts/aggregate_funnel_x86_64 differ diff --git a/posthog/user_scripts/latest_user_defined_function.xml b/posthog/user_scripts/latest_user_defined_function.xml index f0c64736a3..5b7b857f84 100644 --- a/posthog/user_scripts/latest_user_defined_function.xml +++ b/posthog/user_scripts/latest_user_defined_function.xml @@ -1,5 +1,5 @@ - executable_pool aggregate_funnel_v7 @@ -181,7 +181,7 @@ This file is autogenerated by udf_versioner.py. Do not edit this, only edit the executable_pool aggregate_funnel_array_trends_v7 - + Array(Tuple(UInt64, Int8, Array(String), UUID)) result @@ -224,7 +224,7 @@ This file is autogenerated by udf_versioner.py. Do not edit this, only edit the executable_pool aggregate_funnel_cohort_trends_v7 - + Array(Tuple(UInt64, Int8, UInt64, UUID)) result @@ -502,7 +502,7 @@ This file is autogenerated by udf_versioner.py. Do not edit this, only edit the executable_pool aggregate_funnel_array_trends_v8 - + Array(Tuple(UInt64, Int8, Array(String), UUID)) result @@ -545,7 +545,7 @@ This file is autogenerated by udf_versioner.py. Do not edit this, only edit the executable_pool aggregate_funnel_cohort_trends_v8 - + Array(Tuple(UInt64, Int8, UInt64, UUID)) result @@ -626,4 +626,325 @@ This file is autogenerated by udf_versioner.py. Do not edit this, only edit the v8/aggregate_funnel_array_trends_test.py 600 - \ No newline at end of file + + executable_pool + aggregate_funnel_v9 + Array(Tuple(Int8, Nullable(String), Array(Float64), Array(Array(UUID)), UInt32)) + result + + UInt8 + num_steps + + + UInt64 + conversion_window_limit + + + String + breakdown_attribution_type + + + String + funnel_order_type + + + Array(Nullable(String)) + prop_vals + + + Array(Int8) + optional_steps + + + Array(Tuple(Nullable(Float64), UUID, Nullable(String), Array(Int8))) + value + + JSONEachRow + v9/aggregate_funnel steps + 600 + + + + executable_pool + aggregate_funnel_cohort_v9 + Array(Tuple(Int8, UInt64, Array(Float64), Array(Array(UUID)), UInt32)) + result + + UInt8 + num_steps + + + UInt64 + conversion_window_limit + + + String + breakdown_attribution_type + + + String + funnel_order_type + + + Array(UInt64) + prop_vals + + + Array(Int8) + optional_steps + + + Array(Tuple(Nullable(Float64), UUID, UInt64, Array(Int8))) + value + + JSONEachRow + v9/aggregate_funnel steps + 600 + + + + executable_pool + aggregate_funnel_array_v9 + Array(Tuple(Int8, Array(String), Array(Float64), Array(Array(UUID)), UInt32)) + result + + UInt8 + num_steps + + + UInt64 + conversion_window_limit + + + String + breakdown_attribution_type + + + String + funnel_order_type + + + Array(Array(String)) + prop_vals + + + Array(Int8) + optional_steps + + + Array(Tuple(Nullable(Float64), UUID, Array(String), Array(Int8))) + value + + JSONEachRow + v9/aggregate_funnel steps + 600 + + + + executable_pool + aggregate_funnel_test_v9 + String + result + + UInt8 + num_steps + + + UInt64 + conversion_window_limit + + + String + breakdown_attribution_type + + + String + funnel_order_type + + + Array(Array(String)) + prop_vals + + + Array(Int8) + optional_steps + + + Array(Tuple(Nullable(Float64), UUID, Nullable(String), Array(Int8))) + value + + JSONEachRow + v9/aggregate_funnel_test.py + 600 + + + + executable_pool + aggregate_funnel_trends_v9 + Array(Tuple(UInt64, Int8, Nullable(String), UUID)) + result + + UInt8 + from_step + + + UInt8 + to_step + + + UInt8 + num_steps + + + UInt64 + conversion_window_limit + + + String + breakdown_attribution_type + + + String + funnel_order_type + + + Array(Nullable(String)) + prop_vals + + + Array(Tuple(Nullable(Float64), UInt64, UUID, Nullable(String), Array(Int8))) + value + + JSONEachRow + v9/aggregate_funnel trends + 600 + + + + executable_pool + aggregate_funnel_array_trends_v9 + + Array(Tuple(UInt64, Int8, Array(String), UUID)) + result + + UInt8 + from_step + + + UInt8 + to_step + + + UInt8 + num_steps + + + UInt64 + conversion_window_limit + + + String + breakdown_attribution_type + + + String + funnel_order_type + + + Array(Array(String)) + prop_vals + + + Array(Tuple(Nullable(Float64), UInt64, UUID, Array(String), Array(Int8))) + value + + JSONEachRow + v9/aggregate_funnel trends + 600 + + + + executable_pool + aggregate_funnel_cohort_trends_v9 + + Array(Tuple(UInt64, Int8, UInt64, UUID)) + result + + UInt8 + from_step + + + UInt8 + to_step + + + UInt8 + num_steps + + + UInt64 + conversion_window_limit + + + String + breakdown_attribution_type + + + String + funnel_order_type + + + Array(UInt64) + prop_vals + + + Array(Tuple(Nullable(Float64), UInt64, UUID, UInt64, Array(Int8))) + value + + JSONEachRow + v9/aggregate_funnel trends + 600 + + + + executable_pool + aggregate_funnel_array_trends_test_v9 + String + result + + UInt8 + from_step + + + UInt8 + to_step + + + UInt8 + num_steps + + + UInt64 + conversion_window_limit + + + String + breakdown_attribution_type + + + String + funnel_order_type + + + Array(Array(String)) + prop_vals + + + Array(Tuple(Nullable(Float64), UInt64, UUID, Array(String), Array(Int8))) + value + + JSONEachRow + v9/aggregate_funnel_array_trends_test.py + 600 + + diff --git a/posthog/user_scripts/v9/aggregate_funnel b/posthog/user_scripts/v9/aggregate_funnel new file mode 100755 index 0000000000..61e671cba0 --- /dev/null +++ b/posthog/user_scripts/v9/aggregate_funnel @@ -0,0 +1,25 @@ +#!/bin/sh + +DIR_NAME=$(dirname "$0") + +# Create a temporary directory in /tmp +TEMP_DIR=$(mktemp -d -p /tmp "aggregate_funnel_XXXXXXXXXX") + +# Trap to clean up the temporary directory on exit +trap 'rm -rf "$TEMP_DIR"; exit' 0 + +# Determine which executable to use based on architecture +case $( uname -m ) in +aarch64) + EXECUTABLE_NAME="aggregate_funnel_aarch64" + ;; +*) + EXECUTABLE_NAME="aggregate_funnel_x86_64" + ;; +esac + +# Copy the executable to a temporary location +cp "$DIR_NAME/$EXECUTABLE_NAME" "$TEMP_DIR/$EXECUTABLE_NAME" +chmod +x "$TEMP_DIR/$EXECUTABLE_NAME" +"$TEMP_DIR/$EXECUTABLE_NAME" "$@" + diff --git a/posthog/user_scripts/v9/aggregate_funnel_aarch64 b/posthog/user_scripts/v9/aggregate_funnel_aarch64 new file mode 100755 index 0000000000..feb7b990f5 Binary files /dev/null and b/posthog/user_scripts/v9/aggregate_funnel_aarch64 differ diff --git a/posthog/user_scripts/v9/aggregate_funnel_array_trends_test.py b/posthog/user_scripts/v9/aggregate_funnel_array_trends_test.py new file mode 100755 index 0000000000..ae5d7f2438 --- /dev/null +++ b/posthog/user_scripts/v9/aggregate_funnel_array_trends_test.py @@ -0,0 +1,12 @@ +#!/usr/bin/python3 + +import sys +import json + +if __name__ == "__main__": + for line in sys.stdin: + try: + print(json.dumps({"result": line})) # noqa: T201 + except Exception as e: + print(json.dumps({"result": json.dumps(str(e))}), end="\n") # noqa: T201 + sys.stdout.flush() diff --git a/posthog/user_scripts/v9/aggregate_funnel_test.py b/posthog/user_scripts/v9/aggregate_funnel_test.py new file mode 100755 index 0000000000..d524cc8e83 --- /dev/null +++ b/posthog/user_scripts/v9/aggregate_funnel_test.py @@ -0,0 +1,12 @@ +#!/usr/bin/python3 +import sys +import json +import traceback + +if __name__ == "__main__": + for line in sys.stdin: + try: + print(json.dumps({"result": line})) # noqa: T201 + except Exception as e: + print(json.dumps({"result": json.dumps(str(e) + traceback.format_exc())}), end="\n") # noqa: T201 + sys.stdout.flush() diff --git a/posthog/user_scripts/v9/aggregate_funnel_x86_64 b/posthog/user_scripts/v9/aggregate_funnel_x86_64 new file mode 100755 index 0000000000..c4f8212f3b Binary files /dev/null and b/posthog/user_scripts/v9/aggregate_funnel_x86_64 differ diff --git a/posthog/user_scripts/v9/user_defined_function.xml b/posthog/user_scripts/v9/user_defined_function.xml new file mode 100644 index 0000000000..ba88d3b873 --- /dev/null +++ b/posthog/user_scripts/v9/user_defined_function.xml @@ -0,0 +1,950 @@ + + + executable_pool + aggregate_funnel_v7 + Array(Tuple(Int8, Nullable(String), Array(Float64), Array(Array(UUID)))) + result + + UInt8 + num_steps + + + UInt64 + conversion_window_limit + + + String + breakdown_attribution_type + + + String + funnel_order_type + + + Array(Nullable(String)) + prop_vals + + + Array(Tuple(Nullable(Float64), UUID, Nullable(String), Array(Int8))) + value + + JSONEachRow + v7/aggregate_funnel steps + 600 + + + + executable_pool + aggregate_funnel_cohort_v7 + Array(Tuple(Int8, UInt64, Array(Float64), Array(Array(UUID)))) + result + + UInt8 + num_steps + + + UInt64 + conversion_window_limit + + + String + breakdown_attribution_type + + + String + funnel_order_type + + + Array(UInt64) + prop_vals + + + Array(Tuple(Nullable(Float64), UUID, UInt64, Array(Int8))) + value + + JSONEachRow + v7/aggregate_funnel steps + 600 + + + + executable_pool + aggregate_funnel_array_v7 + Array(Tuple(Int8, Array(String), Array(Float64), Array(Array(UUID)))) + result + + UInt8 + num_steps + + + UInt64 + conversion_window_limit + + + String + breakdown_attribution_type + + + String + funnel_order_type + + + Array(Array(String)) + prop_vals + + + Array(Tuple(Nullable(Float64), UUID, Array(String), Array(Int8))) + value + + JSONEachRow + v7/aggregate_funnel steps + 600 + + + + executable_pool + aggregate_funnel_test_v7 + String + result + + UInt8 + num_steps + + + UInt64 + conversion_window_limit + + + String + breakdown_attribution_type + + + String + funnel_order_type + + + Array(Array(String)) + prop_vals + + + Array(Tuple(Nullable(Float64), UUID, Nullable(String), Array(Int8))) + value + + JSONEachRow + v7/aggregate_funnel_test.py + 600 + + + + executable_pool + aggregate_funnel_trends_v7 + Array(Tuple(UInt64, Int8, Nullable(String), UUID)) + result + + UInt8 + from_step + + + UInt8 + to_step + + + UInt8 + num_steps + + + UInt64 + conversion_window_limit + + + String + breakdown_attribution_type + + + String + funnel_order_type + + + Array(Nullable(String)) + prop_vals + + + Array(Tuple(Nullable(Float64), UInt64, UUID, Nullable(String), Array(Int8))) + value + + JSONEachRow + v7/aggregate_funnel trends + 600 + + + + executable_pool + aggregate_funnel_array_trends_v7 + + Array(Tuple(UInt64, Int8, Array(String), UUID)) + result + + UInt8 + from_step + + + UInt8 + to_step + + + UInt8 + num_steps + + + UInt64 + conversion_window_limit + + + String + breakdown_attribution_type + + + String + funnel_order_type + + + Array(Array(String)) + prop_vals + + + Array(Tuple(Nullable(Float64), UInt64, UUID, Array(String), Array(Int8))) + value + + JSONEachRow + v7/aggregate_funnel trends + 600 + + + + executable_pool + aggregate_funnel_cohort_trends_v7 + + Array(Tuple(UInt64, Int8, UInt64, UUID)) + result + + UInt8 + from_step + + + UInt8 + to_step + + + UInt8 + num_steps + + + UInt64 + conversion_window_limit + + + String + breakdown_attribution_type + + + String + funnel_order_type + + + Array(UInt64) + prop_vals + + + Array(Tuple(Nullable(Float64), UInt64, UUID, UInt64, Array(Int8))) + value + + JSONEachRow + v7/aggregate_funnel trends + 600 + + + + executable_pool + aggregate_funnel_array_trends_test_v7 + String + result + + UInt8 + from_step + + + UInt8 + to_step + + + UInt8 + num_steps + + + UInt64 + conversion_window_limit + + + String + breakdown_attribution_type + + + String + funnel_order_type + + + Array(Array(String)) + prop_vals + + + Array(Tuple(Nullable(Float64), UInt64, UUID, Array(String), Array(Int8))) + value + + JSONEachRow + v7/aggregate_funnel_array_trends_test.py + 600 + + + executable_pool + aggregate_funnel_v8 + Array(Tuple(Int8, Nullable(String), Array(Float64), Array(Array(UUID)), UInt32)) + result + + UInt8 + num_steps + + + UInt64 + conversion_window_limit + + + String + breakdown_attribution_type + + + String + funnel_order_type + + + Array(Nullable(String)) + prop_vals + + + Array(Int8) + optional_steps + + + Array(Tuple(Nullable(Float64), UUID, Nullable(String), Array(Int8))) + value + + JSONEachRow + v8/aggregate_funnel steps + 600 + + + + executable_pool + aggregate_funnel_cohort_v8 + Array(Tuple(Int8, UInt64, Array(Float64), Array(Array(UUID)), UInt32)) + result + + UInt8 + num_steps + + + UInt64 + conversion_window_limit + + + String + breakdown_attribution_type + + + String + funnel_order_type + + + Array(UInt64) + prop_vals + + + Array(Int8) + optional_steps + + + Array(Tuple(Nullable(Float64), UUID, UInt64, Array(Int8))) + value + + JSONEachRow + v8/aggregate_funnel steps + 600 + + + + executable_pool + aggregate_funnel_array_v8 + Array(Tuple(Int8, Array(String), Array(Float64), Array(Array(UUID)), UInt32)) + result + + UInt8 + num_steps + + + UInt64 + conversion_window_limit + + + String + breakdown_attribution_type + + + String + funnel_order_type + + + Array(Array(String)) + prop_vals + + + Array(Int8) + optional_steps + + + Array(Tuple(Nullable(Float64), UUID, Array(String), Array(Int8))) + value + + JSONEachRow + v8/aggregate_funnel steps + 600 + + + + executable_pool + aggregate_funnel_test_v8 + String + result + + UInt8 + num_steps + + + UInt64 + conversion_window_limit + + + String + breakdown_attribution_type + + + String + funnel_order_type + + + Array(Array(String)) + prop_vals + + + Array(Int8) + optional_steps + + + Array(Tuple(Nullable(Float64), UUID, Nullable(String), Array(Int8))) + value + + JSONEachRow + v8/aggregate_funnel_test.py + 600 + + + + executable_pool + aggregate_funnel_trends_v8 + Array(Tuple(UInt64, Int8, Nullable(String), UUID)) + result + + UInt8 + from_step + + + UInt8 + to_step + + + UInt8 + num_steps + + + UInt64 + conversion_window_limit + + + String + breakdown_attribution_type + + + String + funnel_order_type + + + Array(Nullable(String)) + prop_vals + + + Array(Tuple(Nullable(Float64), UInt64, UUID, Nullable(String), Array(Int8))) + value + + JSONEachRow + v8/aggregate_funnel trends + 600 + + + + executable_pool + aggregate_funnel_array_trends_v8 + + Array(Tuple(UInt64, Int8, Array(String), UUID)) + result + + UInt8 + from_step + + + UInt8 + to_step + + + UInt8 + num_steps + + + UInt64 + conversion_window_limit + + + String + breakdown_attribution_type + + + String + funnel_order_type + + + Array(Array(String)) + prop_vals + + + Array(Tuple(Nullable(Float64), UInt64, UUID, Array(String), Array(Int8))) + value + + JSONEachRow + v8/aggregate_funnel trends + 600 + + + + executable_pool + aggregate_funnel_cohort_trends_v8 + + Array(Tuple(UInt64, Int8, UInt64, UUID)) + result + + UInt8 + from_step + + + UInt8 + to_step + + + UInt8 + num_steps + + + UInt64 + conversion_window_limit + + + String + breakdown_attribution_type + + + String + funnel_order_type + + + Array(UInt64) + prop_vals + + + Array(Tuple(Nullable(Float64), UInt64, UUID, UInt64, Array(Int8))) + value + + JSONEachRow + v8/aggregate_funnel trends + 600 + + + + executable_pool + aggregate_funnel_array_trends_test_v8 + String + result + + UInt8 + from_step + + + UInt8 + to_step + + + UInt8 + num_steps + + + UInt64 + conversion_window_limit + + + String + breakdown_attribution_type + + + String + funnel_order_type + + + Array(Array(String)) + prop_vals + + + Array(Tuple(Nullable(Float64), UInt64, UUID, Array(String), Array(Int8))) + value + + JSONEachRow + v8/aggregate_funnel_array_trends_test.py + 600 + + + executable_pool + aggregate_funnel_v9 + Array(Tuple(Int8, Nullable(String), Array(Float64), Array(Array(UUID)), UInt32)) + result + + UInt8 + num_steps + + + UInt64 + conversion_window_limit + + + String + breakdown_attribution_type + + + String + funnel_order_type + + + Array(Nullable(String)) + prop_vals + + + Array(Int8) + optional_steps + + + Array(Tuple(Nullable(Float64), UUID, Nullable(String), Array(Int8))) + value + + JSONEachRow + v9/aggregate_funnel steps + 600 + + + + executable_pool + aggregate_funnel_cohort_v9 + Array(Tuple(Int8, UInt64, Array(Float64), Array(Array(UUID)), UInt32)) + result + + UInt8 + num_steps + + + UInt64 + conversion_window_limit + + + String + breakdown_attribution_type + + + String + funnel_order_type + + + Array(UInt64) + prop_vals + + + Array(Int8) + optional_steps + + + Array(Tuple(Nullable(Float64), UUID, UInt64, Array(Int8))) + value + + JSONEachRow + v9/aggregate_funnel steps + 600 + + + + executable_pool + aggregate_funnel_array_v9 + Array(Tuple(Int8, Array(String), Array(Float64), Array(Array(UUID)), UInt32)) + result + + UInt8 + num_steps + + + UInt64 + conversion_window_limit + + + String + breakdown_attribution_type + + + String + funnel_order_type + + + Array(Array(String)) + prop_vals + + + Array(Int8) + optional_steps + + + Array(Tuple(Nullable(Float64), UUID, Array(String), Array(Int8))) + value + + JSONEachRow + v9/aggregate_funnel steps + 600 + + + + executable_pool + aggregate_funnel_test_v9 + String + result + + UInt8 + num_steps + + + UInt64 + conversion_window_limit + + + String + breakdown_attribution_type + + + String + funnel_order_type + + + Array(Array(String)) + prop_vals + + + Array(Int8) + optional_steps + + + Array(Tuple(Nullable(Float64), UUID, Nullable(String), Array(Int8))) + value + + JSONEachRow + v9/aggregate_funnel_test.py + 600 + + + + executable_pool + aggregate_funnel_trends_v9 + Array(Tuple(UInt64, Int8, Nullable(String), UUID)) + result + + UInt8 + from_step + + + UInt8 + to_step + + + UInt8 + num_steps + + + UInt64 + conversion_window_limit + + + String + breakdown_attribution_type + + + String + funnel_order_type + + + Array(Nullable(String)) + prop_vals + + + Array(Tuple(Nullable(Float64), UInt64, UUID, Nullable(String), Array(Int8))) + value + + JSONEachRow + v9/aggregate_funnel trends + 600 + + + + executable_pool + aggregate_funnel_array_trends_v9 + + Array(Tuple(UInt64, Int8, Array(String), UUID)) + result + + UInt8 + from_step + + + UInt8 + to_step + + + UInt8 + num_steps + + + UInt64 + conversion_window_limit + + + String + breakdown_attribution_type + + + String + funnel_order_type + + + Array(Array(String)) + prop_vals + + + Array(Tuple(Nullable(Float64), UInt64, UUID, Array(String), Array(Int8))) + value + + JSONEachRow + v9/aggregate_funnel trends + 600 + + + + executable_pool + aggregate_funnel_cohort_trends_v9 + + Array(Tuple(UInt64, Int8, UInt64, UUID)) + result + + UInt8 + from_step + + + UInt8 + to_step + + + UInt8 + num_steps + + + UInt64 + conversion_window_limit + + + String + breakdown_attribution_type + + + String + funnel_order_type + + + Array(UInt64) + prop_vals + + + Array(Tuple(Nullable(Float64), UInt64, UUID, UInt64, Array(Int8))) + value + + JSONEachRow + v9/aggregate_funnel trends + 600 + + + + executable_pool + aggregate_funnel_array_trends_test_v9 + String + result + + UInt8 + from_step + + + UInt8 + to_step + + + UInt8 + num_steps + + + UInt64 + conversion_window_limit + + + String + breakdown_attribution_type + + + String + funnel_order_type + + + Array(Array(String)) + prop_vals + + + Array(Tuple(Nullable(Float64), UInt64, UUID, Array(String), Array(Int8))) + value + + JSONEachRow + v9/aggregate_funnel_array_trends_test.py + 600 + + \ No newline at end of file