@@ -41,13 +41,13 @@ use self::{
41
41
create_current_schemas_udf, create_current_timestamp_udf, create_current_user_udf,
42
42
create_date_add_udf, create_date_sub_udf, create_date_udf, create_dateadd_udf,
43
43
create_datediff_udf, create_dayofmonth_udf, create_dayofweek_udf, create_dayofyear_udf,
44
- create_db_udf, create_format_type_udf , create_generate_series_udtf ,
45
- create_generate_subscripts_udtf , create_has_schema_privilege_udf , create_hour_udf ,
46
- create_if_udf , create_instr_udf , create_interval_mul_udf , create_isnull_udf ,
47
- create_json_build_object_udf , create_least_udf , create_locate_udf , create_makedate_udf ,
48
- create_measure_udaf , create_minute_udf , create_pg_backend_pid_udf ,
49
- create_pg_datetime_precision_udf , create_pg_expandarray_udtf ,
50
- create_pg_get_constraintdef_udf, create_pg_get_expr_udf,
44
+ create_db_udf, create_ends_with_udf , create_format_type_udf ,
45
+ create_generate_series_udtf , create_generate_subscripts_udtf ,
46
+ create_has_schema_privilege_udf , create_hour_udf , create_if_udf , create_instr_udf ,
47
+ create_interval_mul_udf , create_isnull_udf , create_json_build_object_udf ,
48
+ create_least_udf , create_locate_udf , create_makedate_udf , create_measure_udaf ,
49
+ create_minute_udf , create_pg_backend_pid_udf , create_pg_datetime_precision_udf ,
50
+ create_pg_expandarray_udtf , create_pg_get_constraintdef_udf, create_pg_get_expr_udf,
51
51
create_pg_get_serial_sequence_udf, create_pg_get_userbyid_udf,
52
52
create_pg_is_other_temp_schema, create_pg_my_temp_schema,
53
53
create_pg_numeric_precision_udf, create_pg_numeric_scale_udf,
@@ -1128,6 +1128,7 @@ WHERE `TABLE_SCHEMA` = '{}'",
1128
1128
ctx. register_udf ( create_json_build_object_udf ( ) ) ;
1129
1129
ctx. register_udf ( create_regexp_substr_udf ( ) ) ;
1130
1130
ctx. register_udf ( create_interval_mul_udf ( ) ) ;
1131
+ ctx. register_udf ( create_ends_with_udf ( ) ) ;
1131
1132
1132
1133
// udaf
1133
1134
ctx. register_udaf ( create_measure_udaf ( ) ) ;
@@ -1766,6 +1767,112 @@ mod tests {
1766
1767
)
1767
1768
}
1768
1769
1770
+ #[ tokio:: test]
1771
+ async fn test_starts_with ( ) {
1772
+ let query_plan = convert_select_to_query_plan (
1773
+ "SELECT COUNT(*) as cnt FROM KibanaSampleDataEcommerce WHERE starts_with(customer_gender, 'fe')"
1774
+ . to_string ( ) ,
1775
+ DatabaseProtocol :: PostgreSQL ,
1776
+ )
1777
+ . await ;
1778
+
1779
+ let cube_scan = query_plan. as_logical_plan ( ) . find_cube_scan ( ) ;
1780
+
1781
+ assert_eq ! (
1782
+ cube_scan. request,
1783
+ V1LoadRequestQuery {
1784
+ measures: Some ( vec![ "KibanaSampleDataEcommerce.count" . to_string( ) , ] ) ,
1785
+ segments: Some ( vec![ ] ) ,
1786
+ dimensions: Some ( vec![ ] ) ,
1787
+ time_dimensions: None ,
1788
+ order: None ,
1789
+ limit: None ,
1790
+ offset: None ,
1791
+ filters: Some ( vec![ V1LoadRequestQueryFilterItem {
1792
+ member: Some ( "KibanaSampleDataEcommerce.customer_gender" . to_string( ) ) ,
1793
+ operator: Some ( "startsWith" . to_string( ) ) ,
1794
+ values: Some ( vec![ "fe" . to_string( ) ] ) ,
1795
+ or: None ,
1796
+ and: None
1797
+ } ] )
1798
+ }
1799
+ )
1800
+ }
1801
+
1802
+ #[ tokio:: test]
1803
+ async fn test_ends_with_query ( ) {
1804
+ let query_plan = convert_select_to_query_plan (
1805
+ "SELECT COUNT(*) as cnt FROM KibanaSampleDataEcommerce WHERE ends_with(customer_gender, 'emale')"
1806
+ . to_string ( ) ,
1807
+ DatabaseProtocol :: PostgreSQL ,
1808
+ )
1809
+ . await ;
1810
+
1811
+ let cube_scan = query_plan. as_logical_plan ( ) . find_cube_scan ( ) ;
1812
+
1813
+ assert_eq ! (
1814
+ cube_scan. request,
1815
+ V1LoadRequestQuery {
1816
+ measures: Some ( vec![ "KibanaSampleDataEcommerce.count" . to_string( ) , ] ) ,
1817
+ segments: Some ( vec![ ] ) ,
1818
+ dimensions: Some ( vec![ ] ) ,
1819
+ time_dimensions: None ,
1820
+ order: None ,
1821
+ limit: None ,
1822
+ offset: None ,
1823
+ filters: Some ( vec![ V1LoadRequestQueryFilterItem {
1824
+ member: Some ( "KibanaSampleDataEcommerce.customer_gender" . to_string( ) ) ,
1825
+ operator: Some ( "endsWith" . to_string( ) ) ,
1826
+ values: Some ( vec![ "emale" . to_string( ) ] ) ,
1827
+ or: None ,
1828
+ and: None
1829
+ } ] )
1830
+ }
1831
+ )
1832
+ }
1833
+
1834
+ #[ tokio:: test]
1835
+ async fn test_lower_equals_thoughtspot ( ) {
1836
+ let query_plan = convert_select_to_query_plan (
1837
+ "SELECT COUNT(*) as cnt FROM KibanaSampleDataEcommerce WHERE LOWER(customer_gender) = 'female'"
1838
+ . to_string ( ) ,
1839
+ DatabaseProtocol :: PostgreSQL ,
1840
+ )
1841
+ . await ;
1842
+
1843
+ let cube_scan = query_plan. as_logical_plan ( ) . find_cube_scan ( ) ;
1844
+
1845
+ assert_eq ! (
1846
+ cube_scan. request,
1847
+ V1LoadRequestQuery {
1848
+ measures: Some ( vec![ "KibanaSampleDataEcommerce.count" . to_string( ) , ] ) ,
1849
+ segments: Some ( vec![ ] ) ,
1850
+ dimensions: Some ( vec![ ] ) ,
1851
+ time_dimensions: None ,
1852
+ order: None ,
1853
+ limit: None ,
1854
+ offset: None ,
1855
+ // TODO: Migrate to equalsLower operator, when it will be available in Cube?
1856
+ filters: Some ( vec![
1857
+ V1LoadRequestQueryFilterItem {
1858
+ member: Some ( "KibanaSampleDataEcommerce.customer_gender" . to_string( ) ) ,
1859
+ operator: Some ( "startsWith" . to_string( ) ) ,
1860
+ values: Some ( vec![ "female" . to_string( ) ] ) ,
1861
+ or: None ,
1862
+ and: None
1863
+ } ,
1864
+ V1LoadRequestQueryFilterItem {
1865
+ member: Some ( "KibanaSampleDataEcommerce.customer_gender" . to_string( ) ) ,
1866
+ operator: Some ( "endsWith" . to_string( ) ) ,
1867
+ values: Some ( vec![ "female" . to_string( ) ] ) ,
1868
+ or: None ,
1869
+ and: None
1870
+ }
1871
+ ] )
1872
+ }
1873
+ )
1874
+ }
1875
+
1769
1876
#[ tokio:: test]
1770
1877
async fn test_change_user_via_in_filter_thoughtspot ( ) {
1771
1878
let query_plan = convert_select_to_query_plan (
@@ -5219,6 +5326,24 @@ ORDER BY \"COUNT(count)\" DESC"
5219
5326
Ok ( ( ) )
5220
5327
}
5221
5328
5329
+ #[ tokio:: test]
5330
+ async fn test_ends_with ( ) -> Result < ( ) , CubeError > {
5331
+ insta:: assert_snapshot!(
5332
+ "ends_with" ,
5333
+ execute_query(
5334
+ "select \
5335
+ ends_with('rust is killing me', 'me') as r1,
5336
+ ends_with('rust is killing me', 'no') as r2
5337
+ "
5338
+ . to_string( ) ,
5339
+ DatabaseProtocol :: MySQL
5340
+ )
5341
+ . await ?
5342
+ ) ;
5343
+
5344
+ Ok ( ( ) )
5345
+ }
5346
+
5222
5347
#[ tokio:: test]
5223
5348
async fn test_locate ( ) -> Result < ( ) , CubeError > {
5224
5349
assert_eq ! (
0 commit comments