From eee73a9ec8366e022b2c202bcbd812d90d502c61 Mon Sep 17 00:00:00 2001 From: Marcus Hof <13001502+MarconLP@users.noreply.github.com> Date: Mon, 3 Mar 2025 12:37:14 +0100 Subject: [PATCH] feat(cdp): allow substring without length param (#28746) Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com> --- .cursorignore | 1 + common/hogvm/__tests__/__snapshots__/stl.hoge | 39 ++++++++++--------- common/hogvm/__tests__/__snapshots__/stl.js | 4 +- .../hogvm/__tests__/__snapshots__/stl.stdout | 1 + common/hogvm/__tests__/stl.hog | 1 + common/hogvm/python/stl/__init__.py | 4 +- common/hogvm/typescript/src/stl/stl.ts | 5 ++- posthog/hogql/compiler/javascript_stl.py | 3 +- 8 files changed, 33 insertions(+), 25 deletions(-) create mode 100644 .cursorignore diff --git a/.cursorignore b/.cursorignore new file mode 100644 index 0000000000..2eea525d88 --- /dev/null +++ b/.cursorignore @@ -0,0 +1 @@ +.env \ No newline at end of file diff --git a/common/hogvm/__tests__/__snapshots__/stl.hoge b/common/hogvm/__tests__/__snapshots__/stl.hoge index 08000276db..59cf74920b 100644 --- a/common/hogvm/__tests__/__snapshots__/stl.hoge +++ b/common/hogvm/__tests__/__snapshots__/stl.hoge @@ -44,22 +44,23 @@ "print", 1, 35, 32, "-- string/array --", 2, "print", 1, 35, 32, "a", 32, "a", 32, "b", 32, "c", 2, "tuple", 3, 2, "in", 2, 32, "z", 32, "a", 32, "b", 32, "c", 2, "tuple", 3, 2, "in", 2, 2, "print", 2, 35, 32, "a", 32, "a", 32, "b", 32, "c", 43, 3, 2, "in", 2, 32, "z", 32, "a", 32, "b", 32, "c", 43, 3, 2, "in", 2, 2, "print", 2, 35, 32, "hello", 32, "he", 2, -"startsWith", 2, 32, "abcdef", 33, 2, 33, 3, 2, "substring", 3, 2, "print", 2, 35, 31, 31, 32, "firstNonNull", 2, -"coalesce", 3, 32, "notNull", 2, "assumeNotNull", 1, 2, "print", 2, 35, 32, "", 2, "print", 1, 35, 32, "-- date --", 2, -"print", 1, 35, 32, "2024-12-18T00:00:00Z", 2, "toDateTime", 1, 2, "toYear", 1, 32, "2024-12-18T00:00:00Z", 2, -"toDateTime", 1, 2, "toMonth", 1, 2, "print", 2, 35, 2, "now", 0, 2, "typeof", 1, 2, "print", 1, 35, 32, -"2024-12-18T11:11:11Z", 2, "toDateTime", 1, 2, "toStartOfDay", 1, 32, "2024-12-18T11:11:11Z", 2, "toDateTime", 1, 2, -"toStartOfWeek", 1, 2, "print", 2, 35, 32, "2024-12-18T00:00:00Z", 2, "toDateTime", 1, 2, "toYYYYMM", 1, 2, "print", 1, -35, 32, "day", 33, 1, 32, "2024-12-18", 2, "toDate", 1, 2, "dateAdd", 3, 32, "day", 32, "2024-12-18", 2, "toDate", 1, -32, "day", 33, 5, 32, "2024-12-18", 2, "toDate", 1, 2, "dateAdd", 3, 2, "dateDiff", 3, 2, "print", 2, 35, 32, "day", 32, -"2024-12-18T12:34:56Z", 2, "toDateTime", 1, 2, "dateTrunc", 2, 2, "print", 1, 35, 32, "2024-12-18", 2, "toDate", 1, 33, -3, 2, "addDays", 2, 2, "print", 1, 35, 33, 5, 2, "toIntervalDay", 1, 33, 2, 2, "toIntervalMonth", 1, 2, "print", 2, 35, -2, "today", 0, 2, "typeof", 1, 2, "print", 1, 35, 32, "", 2, "print", 1, 35, 32, "-- json --", 2, "print", 1, 35, 32, -"{\"a\":123.1}", 32, "a", 2, "JSONExtractInt", 2, 2, "jsonStringify", 1, 32, "{\"a\":\"hello\"}", 32, "a", 2, -"JSONExtractInt", 2, 2, "jsonStringify", 1, 2, "print", 2, 35, 32, "{\"a\":123.1}", 32, "a", 2, "JSONExtractFloat", 2, -2, "jsonStringify", 1, 32, "{\"a\":\"hello\"}", 32, "a", 2, "JSONExtractFloat", 2, 2, "jsonStringify", 1, 2, "print", 2, -35, 32, "{\"a\":123.1}", 32, "a", 2, "JSONExtractString", 2, 2, "jsonStringify", 1, 32, "{\"a\":\"hello\"}", 32, "a", 2, -"JSONExtractString", 2, 2, "jsonStringify", 1, 2, "print", 2, 35, 32, "{\"a\":123}", 32, "a", 2, "JSONExtractArrayRaw", -2, 2, "jsonStringify", 1, 32, "{\"a\":\"hello\"}", 32, "a", 2, "JSONExtractArrayRaw", 2, 2, "jsonStringify", 1, 2, -"print", 2, 35, 32, "{\"a\":[]}", 32, "a", 2, "JSONExtractArrayRaw", 2, 2, "jsonStringify", 1, 32, -"{\"a\":[\"hello\"]}", 32, "a", 2, "JSONExtractArrayRaw", 2, 2, "jsonStringify", 1, 2, "print", 2, 35] +"startsWith", 2, 32, "abcdef", 33, 2, 33, 3, 2, "substring", 3, 2, "print", 2, 35, 32, "abcdef", 33, 2, 2, "substring", +2, 2, "print", 1, 35, 31, 31, 32, "firstNonNull", 2, "coalesce", 3, 32, "notNull", 2, "assumeNotNull", 1, 2, "print", 2, +35, 32, "", 2, "print", 1, 35, 32, "-- date --", 2, "print", 1, 35, 32, "2024-12-18T00:00:00Z", 2, "toDateTime", 1, 2, +"toYear", 1, 32, "2024-12-18T00:00:00Z", 2, "toDateTime", 1, 2, "toMonth", 1, 2, "print", 2, 35, 2, "now", 0, 2, +"typeof", 1, 2, "print", 1, 35, 32, "2024-12-18T11:11:11Z", 2, "toDateTime", 1, 2, "toStartOfDay", 1, 32, +"2024-12-18T11:11:11Z", 2, "toDateTime", 1, 2, "toStartOfWeek", 1, 2, "print", 2, 35, 32, "2024-12-18T00:00:00Z", 2, +"toDateTime", 1, 2, "toYYYYMM", 1, 2, "print", 1, 35, 32, "day", 33, 1, 32, "2024-12-18", 2, "toDate", 1, 2, "dateAdd", +3, 32, "day", 32, "2024-12-18", 2, "toDate", 1, 32, "day", 33, 5, 32, "2024-12-18", 2, "toDate", 1, 2, "dateAdd", 3, 2, +"dateDiff", 3, 2, "print", 2, 35, 32, "day", 32, "2024-12-18T12:34:56Z", 2, "toDateTime", 1, 2, "dateTrunc", 2, 2, +"print", 1, 35, 32, "2024-12-18", 2, "toDate", 1, 33, 3, 2, "addDays", 2, 2, "print", 1, 35, 33, 5, 2, "toIntervalDay", +1, 33, 2, 2, "toIntervalMonth", 1, 2, "print", 2, 35, 2, "today", 0, 2, "typeof", 1, 2, "print", 1, 35, 32, "", 2, +"print", 1, 35, 32, "-- json --", 2, "print", 1, 35, 32, "{\"a\":123.1}", 32, "a", 2, "JSONExtractInt", 2, 2, +"jsonStringify", 1, 32, "{\"a\":\"hello\"}", 32, "a", 2, "JSONExtractInt", 2, 2, "jsonStringify", 1, 2, "print", 2, 35, +32, "{\"a\":123.1}", 32, "a", 2, "JSONExtractFloat", 2, 2, "jsonStringify", 1, 32, "{\"a\":\"hello\"}", 32, "a", 2, +"JSONExtractFloat", 2, 2, "jsonStringify", 1, 2, "print", 2, 35, 32, "{\"a\":123.1}", 32, "a", 2, "JSONExtractString", +2, 2, "jsonStringify", 1, 32, "{\"a\":\"hello\"}", 32, "a", 2, "JSONExtractString", 2, 2, "jsonStringify", 1, 2, +"print", 2, 35, 32, "{\"a\":123}", 32, "a", 2, "JSONExtractArrayRaw", 2, 2, "jsonStringify", 1, 32, "{\"a\":\"hello\"}", +32, "a", 2, "JSONExtractArrayRaw", 2, 2, "jsonStringify", 1, 2, "print", 2, 35, 32, "{\"a\":[]}", 32, "a", 2, +"JSONExtractArrayRaw", 2, 2, "jsonStringify", 1, 32, "{\"a\":[\"hello\"]}", 32, "a", 2, "JSONExtractArrayRaw", 2, 2, +"jsonStringify", 1, 2, "print", 2, 35] diff --git a/common/hogvm/__tests__/__snapshots__/stl.js b/common/hogvm/__tests__/__snapshots__/stl.js index 247aa1ec4a..8978345017 100644 --- a/common/hogvm/__tests__/__snapshots__/stl.js +++ b/common/hogvm/__tests__/__snapshots__/stl.js @@ -61,9 +61,10 @@ function toIntervalMonth(val) { return __toHogInterval(val, 'month') } function toIntervalDay(val) { return __toHogInterval(val, 'day') } function toDateTime (input, zone) { return __toDateTime(input, zone) } function toDate (input) { return __toDate(input) } -function substring(s, start, length) { +function substring(s, start, optionalLength) { if (typeof s !== 'string') return ''; const startIdx = start - 1; + const length = typeof optionalLength === 'number' ? optionalLength : s.length - startIdx; if (startIdx < 0 || length < 0) return ''; const endIdx = startIdx + length; return startIdx < s.length ? s.slice(startIdx, endIdx) : ''; @@ -531,6 +532,7 @@ print("-- string/array --"); print(__x_in("a", tuple("a", "b", "c")), __x_in("z", tuple("a", "b", "c"))); print(__x_in("a", ["a", "b", "c"]), __x_in("z", ["a", "b", "c"])); print(startsWith("hello", "he"), substring("abcdef", 2, 3)); +print(substring("abcdef", 2)); print(coalesce(null, null, "firstNonNull"), assumeNotNull("notNull")); print(""); print("-- date --"); diff --git a/common/hogvm/__tests__/__snapshots__/stl.stdout b/common/hogvm/__tests__/__snapshots__/stl.stdout index b9f6eabbc5..c4d0699f46 100644 --- a/common/hogvm/__tests__/__snapshots__/stl.stdout +++ b/common/hogvm/__tests__/__snapshots__/stl.stdout @@ -89,6 +89,7 @@ one true false true false true bcd +bcdef firstNonNull notNull -- date -- diff --git a/common/hogvm/__tests__/stl.hog b/common/hogvm/__tests__/stl.hog index a00871f041..e4a7f7b383 100644 --- a/common/hogvm/__tests__/stl.hog +++ b/common/hogvm/__tests__/stl.hog @@ -89,6 +89,7 @@ print('-- string/array --') print(in('a', tuple('a','b','c')), in('z', tuple('a','b','c'))) print(in('a', ['a','b','c']), in('z', ['a','b','c'])) print(startsWith('hello','he'), substring('abcdef',2,3)) +print(substring('abcdef',2)) print(coalesce(null, null, 'firstNonNull'), assumeNotNull('notNull')) print('') print('-- date --') diff --git a/common/hogvm/python/stl/__init__.py b/common/hogvm/python/stl/__init__.py index 255d59a67e..e8cab1f89d 100644 --- a/common/hogvm/python/stl/__init__.py +++ b/common/hogvm/python/stl/__init__.py @@ -718,10 +718,10 @@ def substring(args: list[Any], team: Optional["Team"], stdout: Optional[list[str # start is 1-based. s = args[0] start = args[1] - length = args[2] if not isinstance(s, str): return "" start_idx = start - 1 + length = args[2] if len(args) > 2 else len(s) - start_idx if start_idx < 0 or length < 0: return "" end_idx = start_idx + length @@ -1060,7 +1060,7 @@ STL: dict[str, STLFunction] = { "range": STLFunction(fn=range_fn, minArgs=1, maxArgs=2), "round": STLFunction(fn=round_fn, minArgs=1, maxArgs=1), "startsWith": STLFunction(fn=startsWith, minArgs=2, maxArgs=2), - "substring": STLFunction(fn=substring, minArgs=3, maxArgs=3), + "substring": STLFunction(fn=substring, minArgs=2, maxArgs=3), "toIntervalDay": STLFunction(fn=toIntervalDay, minArgs=1, maxArgs=1), "toIntervalHour": STLFunction(fn=toIntervalHour, minArgs=1, maxArgs=1), "toIntervalMinute": STLFunction(fn=toIntervalMinute, minArgs=1, maxArgs=1), diff --git a/common/hogvm/typescript/src/stl/stl.ts b/common/hogvm/typescript/src/stl/stl.ts index 73aaa09b48..f34cd905cc 100644 --- a/common/hogvm/typescript/src/stl/stl.ts +++ b/common/hogvm/typescript/src/stl/stl.ts @@ -316,11 +316,12 @@ function startsWithFn([str, prefix]: any[]): boolean { return typeof str === 'string' && typeof prefix === 'string' && str.startsWith(prefix) } -function substringFn([s, start, length]: any[]): string { +function substringFn([s, start, optionalLength]: any[]): string { if (typeof s !== 'string') { return '' } const startIdx = start - 1 + const length = typeof optionalLength === 'number' ? optionalLength : s.length - startIdx if (startIdx < 0 || length < 0) { return '' } @@ -1259,7 +1260,7 @@ export const STL: Record = { range: { fn: rangeFn, minArgs: 1, maxArgs: 2 }, round: { fn: roundFn, minArgs: 1, maxArgs: 1 }, startsWith: { fn: startsWithFn, minArgs: 2, maxArgs: 2 }, - substring: { fn: substringFn, minArgs: 3, maxArgs: 3 }, + substring: { fn: substringFn, minArgs: 2, maxArgs: 3 }, toIntervalDay: { fn: toIntervalDayFn, minArgs: 1, maxArgs: 1 }, toIntervalHour: { fn: toIntervalHourFn, minArgs: 1, maxArgs: 1 }, toIntervalMinute: { fn: toIntervalMinuteFn, minArgs: 1, maxArgs: 1 }, diff --git a/posthog/hogql/compiler/javascript_stl.py b/posthog/hogql/compiler/javascript_stl.py index 12eb883c03..135214c5b0 100644 --- a/posthog/hogql/compiler/javascript_stl.py +++ b/posthog/hogql/compiler/javascript_stl.py @@ -1295,9 +1295,10 @@ function __setProperty(objectOrArray, key, value) { [], ], "substring": [ - """function substring(s, start, length) { + """function substring(s, start, optionalLength) { if (typeof s !== 'string') return ''; const startIdx = start - 1; + const length = typeof optionalLength === 'number' ? optionalLength : s.length - startIdx; if (startIdx < 0 || length < 0) return ''; const endIdx = startIdx + length; return startIdx < s.length ? s.slice(startIdx, endIdx) : '';