dwh 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (104) hide show
  1. checksums.yaml +7 -0
  2. data/.rubocop.yml +36 -0
  3. data/CHANGELOG.md +5 -0
  4. data/LICENSE +21 -0
  5. data/README.md +130 -0
  6. data/Rakefile +42 -0
  7. data/docs/DWH/Adapters/Adapter.html +3053 -0
  8. data/docs/DWH/Adapters/Athena.html +1704 -0
  9. data/docs/DWH/Adapters/Boolean.html +121 -0
  10. data/docs/DWH/Adapters/Druid.html +1626 -0
  11. data/docs/DWH/Adapters/DuckDb.html +2012 -0
  12. data/docs/DWH/Adapters/MySql.html +1704 -0
  13. data/docs/DWH/Adapters/OpenAuthorizable/ClassMethods.html +265 -0
  14. data/docs/DWH/Adapters/OpenAuthorizable.html +1102 -0
  15. data/docs/DWH/Adapters/Postgres.html +2000 -0
  16. data/docs/DWH/Adapters/Snowflake.html +1662 -0
  17. data/docs/DWH/Adapters/SqlServer.html +2084 -0
  18. data/docs/DWH/Adapters/Trino.html +1835 -0
  19. data/docs/DWH/Adapters.html +129 -0
  20. data/docs/DWH/AuthenticationError.html +142 -0
  21. data/docs/DWH/Behaviors.html +767 -0
  22. data/docs/DWH/Capabilities.html +748 -0
  23. data/docs/DWH/Column.html +1115 -0
  24. data/docs/DWH/ConfigError.html +143 -0
  25. data/docs/DWH/ConnectionError.html +143 -0
  26. data/docs/DWH/DWHError.html +138 -0
  27. data/docs/DWH/ExecutionError.html +143 -0
  28. data/docs/DWH/Factory.html +1133 -0
  29. data/docs/DWH/Functions/Arrays.html +505 -0
  30. data/docs/DWH/Functions/Dates.html +1644 -0
  31. data/docs/DWH/Functions/ExtractDatePart.html +804 -0
  32. data/docs/DWH/Functions/Nulls.html +377 -0
  33. data/docs/DWH/Functions.html +846 -0
  34. data/docs/DWH/Logger.html +258 -0
  35. data/docs/DWH/OAuthError.html +138 -0
  36. data/docs/DWH/Settings.html +658 -0
  37. data/docs/DWH/StreamingStats.html +804 -0
  38. data/docs/DWH/Table.html +1260 -0
  39. data/docs/DWH/TableStats.html +583 -0
  40. data/docs/DWH/TokenExpiredError.html +142 -0
  41. data/docs/DWH/UnsupportedCapability.html +135 -0
  42. data/docs/DWH.html +220 -0
  43. data/docs/_index.html +471 -0
  44. data/docs/class_list.html +54 -0
  45. data/docs/css/common.css +1 -0
  46. data/docs/css/full_list.css +58 -0
  47. data/docs/css/style.css +503 -0
  48. data/docs/file.README.html +210 -0
  49. data/docs/file.adapters.html +514 -0
  50. data/docs/file.creating-adapters.html +497 -0
  51. data/docs/file.getting-started.html +288 -0
  52. data/docs/file.usage.html +446 -0
  53. data/docs/file_list.html +79 -0
  54. data/docs/frames.html +22 -0
  55. data/docs/guides/adapters.md +445 -0
  56. data/docs/guides/creating-adapters.md +430 -0
  57. data/docs/guides/getting-started.md +225 -0
  58. data/docs/guides/usage.md +378 -0
  59. data/docs/index.html +210 -0
  60. data/docs/js/app.js +344 -0
  61. data/docs/js/full_list.js +242 -0
  62. data/docs/js/jquery.js +4 -0
  63. data/docs/method_list.html +2038 -0
  64. data/docs/top-level-namespace.html +110 -0
  65. data/lib/dwh/adapters/athena.rb +359 -0
  66. data/lib/dwh/adapters/druid.rb +267 -0
  67. data/lib/dwh/adapters/duck_db.rb +235 -0
  68. data/lib/dwh/adapters/my_sql.rb +235 -0
  69. data/lib/dwh/adapters/open_authorizable.rb +215 -0
  70. data/lib/dwh/adapters/postgres.rb +250 -0
  71. data/lib/dwh/adapters/snowflake.rb +489 -0
  72. data/lib/dwh/adapters/sql_server.rb +257 -0
  73. data/lib/dwh/adapters/trino.rb +213 -0
  74. data/lib/dwh/adapters.rb +363 -0
  75. data/lib/dwh/behaviors.rb +67 -0
  76. data/lib/dwh/capabilities.rb +39 -0
  77. data/lib/dwh/column.rb +79 -0
  78. data/lib/dwh/errors.rb +29 -0
  79. data/lib/dwh/factory.rb +125 -0
  80. data/lib/dwh/functions/arrays.rb +42 -0
  81. data/lib/dwh/functions/dates.rb +162 -0
  82. data/lib/dwh/functions/extract_date_part.rb +70 -0
  83. data/lib/dwh/functions/nulls.rb +31 -0
  84. data/lib/dwh/functions.rb +86 -0
  85. data/lib/dwh/logger.rb +50 -0
  86. data/lib/dwh/settings/athena.yml +77 -0
  87. data/lib/dwh/settings/base.yml +81 -0
  88. data/lib/dwh/settings/databricks.yml +51 -0
  89. data/lib/dwh/settings/druid.yml +59 -0
  90. data/lib/dwh/settings/duckdb.yml +44 -0
  91. data/lib/dwh/settings/mysql.yml +67 -0
  92. data/lib/dwh/settings/postgres.yml +30 -0
  93. data/lib/dwh/settings/redshift.yml +52 -0
  94. data/lib/dwh/settings/snowflake.yml +45 -0
  95. data/lib/dwh/settings/sqlserver.yml +80 -0
  96. data/lib/dwh/settings/trino.yml +77 -0
  97. data/lib/dwh/settings.rb +79 -0
  98. data/lib/dwh/streaming_stats.rb +69 -0
  99. data/lib/dwh/table.rb +105 -0
  100. data/lib/dwh/table_stats.rb +51 -0
  101. data/lib/dwh/version.rb +5 -0
  102. data/lib/dwh.rb +54 -0
  103. data/sig/dwh.rbs +4 -0
  104. metadata +231 -0
@@ -0,0 +1,59 @@
1
+
2
+ date_add: "TIMESTAMPADD(@unit, @val, @exp)"
3
+ date_diff: "TIMESTAMPDIFF(@unit, @start_exp, @end_exp)"
4
+ date_format_sql: "TIME_FORMAT(@exp, '@format')"
5
+ day_name_format: "EEEE"
6
+ abbreviated_day_name_format: "EEE"
7
+ month_name_format: "MMMM"
8
+ abbreviated_month_name_format: "MMM"
9
+
10
+ date_literal: "'@val'"
11
+ date_time_literal: "TIMESTAMP '@val'"
12
+ extract_year: "TIME_EXTRACT(@exp, 'YEAR')"
13
+ extract_month: "TIME_EXTRACT(@exp, 'MONTH')"
14
+ extract_quarter: "TIME_EXTRACT(@exp, 'QUARTER')"
15
+ extract_day_of_year: "TIME_EXTRACT(@exp, 'DOY')"
16
+ extract_day_of_month: "TIME_EXTRACT(@exp, 'DAY')"
17
+ extract_day_of_week: "TIME_EXTRACT(@exp, 'DOW')"
18
+ extract_week_of_year: "TIME_EXTRACT(@exp, 'WEEK')"
19
+ extract_hour: "TIME_EXTRACT(@exp, 'HOUR')"
20
+ extract_minute: "TIME_EXTRACT(@exp, 'MINUTE')"
21
+ extract_year_month: "cast((TIME_EXTRACT(@exp, 'YEAR') || TIME_EXTRACT(@exp, 'MONTH')) as integer)"
22
+ default_week_start_day: "monday"
23
+ week_start_day: "sunday"
24
+ sunday_week_start_day: "TIME_FLOOR(@exp, 'P7D', TIMESTAMP '1970-01-04 00:00:00')"
25
+ monday_week_start_day: "TIME_FLOOR(@exp, 'P7D', TIMESTAMP '1970-01-05 00:00:00')"
26
+
27
+ # string functions
28
+ trim: "trim(@exp)"
29
+ lower_case: "lower(@exp)"
30
+ upper_case: "upper(@exp)"
31
+
32
+ # Relevant db capabilities
33
+ supports_table_join: true
34
+ supports_full_join: true
35
+ supports_cross_join: true
36
+ supports_common_table_expressions: false
37
+ supports_temp_tables: false
38
+ supports_window_functions: true
39
+ extend_ending_date_to_last_hour_of_day: true
40
+
41
+ # array operations
42
+ array_in_list: "MV_OVERLAP(@exp, ARRAY[@list])" # list is comma separated
43
+ array_exclude_list: "MV_OVERLAP(@exp, ARRAY[@list]) = 0" # list is comma separated
44
+ array_unnest_join: "CROSS JOIN UNNEST(MV_TO_ARRAY(@exp)) @alias"
45
+
46
+ #joins
47
+ cross_join: "JOIN @relation ON 1=1"
48
+
49
+ # null handling
50
+ if_null: "NVL(@exp, @when_null)"
51
+
52
+ # sql output behavior
53
+ temp_table_type: "subquery" # options cte, subquery, temp
54
+ # Determines how measures across fact universes are combined.
55
+ # Default is full join when supported.
56
+ final_pass_measure_join_type: "full" # inner left right etc
57
+ apply_advanced_filtering_on_array_projections: true # druid needs a having clause or un-nesting
58
+ greedy_apply_date_filters: false
59
+ cross_universe_measure_filtering_strategy: "both" # both, final, intermediate
@@ -0,0 +1,44 @@
1
+
2
+
3
+ # Date Literal Formats
4
+ day_name_format: "%A"
5
+ abbreviated_day_name_format: "%a"
6
+ month_name_format: "%B"
7
+ abbreviated_month_name_format: "%b"
8
+
9
+ # Date functions patterns
10
+ date_add: "DATE_ADD(@exp, INTERVAL @val @unit)"
11
+ date_diff: "DATE_DIFF('@unit', @start_exp, @end_exp)"
12
+ date_format_sql: "STRFTIME(@exp, '@format')"
13
+ date_literal: "DATE '@val'"
14
+ date_time_literal: "TIMESTAMP '@val'"
15
+ extract_year: "EXTRACT('YEAR' FROM @exp)"
16
+ extract_month: "EXTRACT('MONTH' FROM @exp)"
17
+ extract_quarter: "EXTRACT('QUARTER' FROM @exp)"
18
+ extract_day_of_year: "EXTRACT('DOY' FROM @exp)"
19
+ extract_day_of_month: "EXTRACT('DAY' FROM @exp)"
20
+ extract_day_of_week: "EXTRACT('DAYOFWEEK' FROM @exp)"
21
+ extract_week_of_year: "EXTRACT('WEEK' FROM @exp)"
22
+ extract_hour: 'HOUR(@exp)'
23
+ extract_minute: 'MINUTE(@exp)'
24
+ extract_year_month: "(STRFTIME(@exp, '%Y') || STRFTIME(@exp, '%m'))::INTEGER"
25
+ default_week_start_day: "monday"
26
+ week_start_day: "monday"
27
+ sunday_week_start_day: "(DATE_TRUNC('week', @exp + 1) - 1)"
28
+ monday_week_start_day: "( DATE_TRUNC('week', @exp - 1) + 1 )"
29
+
30
+ cast: "@exp::@type"
31
+
32
+ # string functions
33
+ trim: "TRIM(@exp)"
34
+ lower_case: "LOWER(@exp)"
35
+ upper_case: "UPPER(@exp)"
36
+
37
+ # Relevant db capabilities for query gen
38
+ create_temp_table_template: "CREATE TEMP TABLE @table AS \n@sql"
39
+
40
+ # array operations
41
+ array_in_list: "array_length(array_intersect(@exp, @list)) > 0"
42
+ array_exclude_list: "array_length(array_intersect(@exp, @list)) = 0"
43
+ array_unnest_join: ", LATERAL (SELECT UNNEST(@exp)) AS @alias"
44
+
@@ -0,0 +1,67 @@
1
+ # quotes and string lit
2
+ quote: "`@exp`"
3
+ string_literal: "'@exp'"
4
+
5
+ # Date functions patterns
6
+ current_date: "CURDATE()"
7
+ current_time: "CURTIME()"
8
+ current_timestamp: "NOW()"
9
+ truncate_date: "CUSTOM"
10
+ date_add: "DATE_ADD(@exp, INTERVAL @val @unit)"
11
+ date_diff: "DATEDIFF(@end_exp, @start_exp)"
12
+ date_format_sql: "DATE_FORMAT(@exp, '@format')"
13
+ date_literal: "'@val'"
14
+ date_time_literal: "'@val'"
15
+ extract_year: 'YEAR(@exp)'
16
+ extract_month: 'MONTH(@exp)'
17
+ extract_quarter: 'QUARTER(@exp)'
18
+ extract_day_of_year: 'DAYOFYEAR(@exp)'
19
+ extract_day_of_month: 'DAY(@exp)'
20
+ extract_day_of_week: 'DAYOFWEEK(@exp)'
21
+ extract_week_of_year: 'WEEK(@exp)'
22
+ extract_hour: 'HOUR(@exp)'
23
+ extract_minute: 'MINUTE(@exp)'
24
+ extract_year_month: 'CAST(CONCAT(YEAR(@exp), LPAD(MONTH(@exp), 2, "0")) AS UNSIGNED)'
25
+ default_week_start_day: "sunday"
26
+ week_start_day: "monday"
27
+ sunday_week_start_day: "DATE(DATE_SUB(@exp, INTERVAL dayofweek(@exp)-1 DAY ))"
28
+ monday_week_start_day: "DATE(DATE_SUB(@exp, INTERVAL dayofweek(@exp)-2 DAY ))"
29
+ cast: "CAST(@exp AS @type)"
30
+
31
+ # string functions
32
+ trim: "TRIM(@exp)"
33
+ lower_case: "LCASE(@exp)"
34
+ upper_case: "UCASE(@exp)"
35
+
36
+ # null handling
37
+ if_null: "COALESCE(@exp, @when_null)"
38
+ null_if: "NULLIF(@exp, @target)"
39
+ null_if_zero: "NULLIF(@exp, 0)"
40
+
41
+ # Relevant db capabilities for query gen
42
+ supports_table_join: true
43
+ supports_full_join: false # MySQL doesn't support FULL OUTER JOIN
44
+ supports_cross_join: true
45
+ supports_sub_queries: true
46
+ supports_common_table_expressions: true # MySQL 8.0+
47
+ supports_temp_tables: true
48
+ create_temp_table_template: "CREATE TEMPORARY TABLE @table AS \n@sql"
49
+ supports_window_functions: true # MySQL 8.0+
50
+ extend_ending_date_to_last_hour_of_day: false
51
+
52
+ # array operations (MySQL has limited array support, using JSON functions for MySQL 8.0+)
53
+ array_in_list: "JSON_OVERLAPS(@exp, JSON_ARRAY(@list))" # MySQL 8.0.17+
54
+ array_exclude_list: "NOT JSON_OVERLAPS(@exp, JSON_ARRAY(@list))" # MySQL 8.0.17+
55
+ array_unnest_join: "JOIN JSON_TABLE(@exp, '$[*]' COLUMNS (@alias JSON PATH '$')) AS @alias"
56
+
57
+ cross_join: "CROSS JOIN @relation"
58
+
59
+ # sql output behavior
60
+ temp_table_type: "cte" # options cte, subquery, temp
61
+ temp_table_prefix: ""
62
+
63
+ # Determines how measures across fact universes are combined.
64
+ final_pass_measure_join_type: "left" # inner left right etc
65
+ apply_advanced_filtering_on_array_projections: false
66
+ greedy_apply_date_filters: true
67
+ cross_universe_measure_filtering_strategy: "both" # both, final, intermediate
@@ -0,0 +1,30 @@
1
+
2
+ date_add: "(@exp + '@val @unit'::interval)"
3
+ date_diff: "age(@start_exp, @end_exp)"
4
+ date_format_sql: "TO_CHAR(@exp, '@format')"
5
+ date_literal: "'@val'::DATE"
6
+ date_time_literal: "'@val'::TIMESTAMP"
7
+ day_name_format: "Day"
8
+ abbreviated_day_name_format: "Dy"
9
+ month_name_format: "Month"
10
+ abbreviated_month_name_format: "Mon"
11
+ # Adjust week start day
12
+ sunday_week_start_day: "( DATE_TRUNC('WEEK', @exp + INTERVAL '1 DAY') - INTERVAL '1 DAY' )"
13
+ monday_week_start_day: "( DATE_TRUNC('WEEK', @exp - INTERVAL '1 DAY') + INTERVAL '1 DAY' )"
14
+
15
+ extract_year: 'extract(year from @exp)'
16
+ extract_month: 'extract(month from @exp)'
17
+ extract_quarter: 'extract(quarter from @exp)'
18
+ extract_day_of_year: 'extract(DOY from @exp)'
19
+ extract_day_of_month: 'extract(DAY from @exp)'
20
+ extract_day_of_week: 'extract(DOW from @exp)'
21
+ extract_week_of_year: 'extract(WEEK from @exp)'
22
+ extract_hour: 'extract(HOUR from @exp)'
23
+ extract_minute: 'extract(MINUTE from @exp)'
24
+ extract_year_month: "cast((extract(year from @exp)::varchar || TO_CHAR(@exp, 'MM')) as integer)"
25
+
26
+ cast: "@exp::@type"
27
+
28
+ # array operations
29
+ array_in_list: "@exp && ARRAY[@list]" # list is comma separated
30
+ array_exclude_list: "NOT (@exp && ARRAY[@list])" # list is comma separated
@@ -0,0 +1,52 @@
1
+
2
+ # quotes and string lit
3
+ quote: "\"@exp\""
4
+ string_literal: "'@exp'"
5
+
6
+ # Date Literal Formats
7
+ date_format: "%Y-%m-%d"
8
+ date_time_format: "%Y-%m-%d %H:%M:%S"
9
+ date_time_tz_format: "%Y-%m-%d %H:%M:%S %Z"
10
+ date_type: "string" # alternative is int, integer, dateint
11
+ day_name_format: "Day"
12
+ abbreviated_day_name_format: "Dy"
13
+ month_name_format: "Month"
14
+ abbreviated_month_name_format: "Mon"
15
+
16
+ # Date functions patterns
17
+ current_date: "current_date"
18
+ current_time: "current_time"
19
+ current_timestamp: "current_timestamp"
20
+ truncate_date: "date_trunc('@unit', @exp)"
21
+ date_add: "dateadd(@unit, @val, @exp)"
22
+ date_diff: "datediff(@unit, @start_exp, @end_exp)"
23
+ date_format_sql: "TO_CHAR(@exp, '@format')"
24
+ date_literal: "'@val'"
25
+ date_time_literal: "TIMESTAMP '@val'"
26
+ extract_year: 'EXTRACT(YEAR FROM @exp)'
27
+ extract_month: 'EXTRACT(MONTH FROM @exp)'
28
+ extract_quarter: 'EXTRACT(QUARTER FROM @exp)'
29
+ extract_day_of_year: 'EXTRACT(DOY FROM @exp)'
30
+ extract_day_of_month: 'EXTRACT(DAY FROM @exp)'
31
+ extract_day_of_week: 'EXTRACT(DOW FROM @exp)'
32
+ extract_week_of_year: 'EXTRACT(WEEK FROM @exp)'
33
+ extract_hour: 'EXTRACT(HOUR FROM @exp)'
34
+ extract_minute: 'EXTRACT(MINUTE FROM @exp)'
35
+ extract_year_month: "TO_CHAR(@exp, 'YYYYMM')::INTEGER"
36
+ default_week_start_day: "sunday" # Redshift uses Sunday as default
37
+ week_start_day: "sunday"
38
+ sunday_week_start_day: "DATEADD(day, -1, DATE_TRUNC(WEEK, DATEADD(DAY, 1, @exp)))"
39
+ monday_week_start_day: "DATEADD(day, 1, DATE_TRUNC(WEEK, DATEADD(day, -1, @exp)))"
40
+
41
+ # string functions
42
+ trim: "trim(@exp)"
43
+ lower_case: "lower(@exp)"
44
+ upper_case: "upper(@exp)"
45
+
46
+ # null handling
47
+ if_null: "COALESCE(@exp, @when_null)"
48
+ null_if: "NULLIF(@exp, @target)"
49
+ null_if_zero: "NULLIF(@exp, 0)"
50
+
51
+ # array operations
52
+ supports_array_functions: false
@@ -0,0 +1,45 @@
1
+
2
+ # Date Literal Formats
3
+ date_format: "%Y-%m-%d"
4
+ date_time_format: "%Y-%m-%d %H:%M:%S"
5
+ date_time_tz_format: "%Y-%m-%d %H:%M:%S %Z"
6
+ date_type: "string" # alternative is int, integer, dateint
7
+ day_name_format: "DY"
8
+ abbreviated_day_name_format: "DY"
9
+ month_name_format: "MMMM"
10
+ abbreviated_month_name_format: "MON"
11
+
12
+ # Date functions patterns
13
+ current_date: "current_date()"
14
+ current_time: "current_time()"
15
+ current_timestamp: "current_timestamp()"
16
+
17
+ date_add: "dateadd(@unit, @val, @exp)"
18
+ date_diff: "datediff(@unit, @start_exp, @end_exp)"
19
+ date_format_sql: "TO_VARCHAR(@exp, '@format')"
20
+ date_literal: "'@val'::DATE"
21
+ date_time_literal: "'@val'::TIMESTAMP"
22
+ extract_year: 'year(@exp)'
23
+ extract_month: 'month(@exp)'
24
+ extract_quarter: 'quarter(@exp)'
25
+ extract_day_of_year: 'DAYOFYEAR(@exp)'
26
+ extract_day_of_month: 'day(@exp)'
27
+ extract_day_of_week: 'DAYOFWEEK(@exp)'
28
+ extract_week_of_year: 'week(@exp)'
29
+ extract_hour: 'hour(@exp)'
30
+ extract_minute: 'minute(@exp)'
31
+ extract_year_month: 'cast((TO_VARCHAR(@exp, ''YYYY'') || TO_VARCHAR(@exp, ''MM'')) as integer)'
32
+ default_week_start_day: "monday"
33
+ week_start_day: "monday"
34
+ sunday_week_start_day: "dateadd(day, -1,date_trunc('week', dateadd(day,1, @exp)))"
35
+ monday_week_start_day: "dateadd(day, 1,date_trunc('week', dateadd(day,-1, @exp)))"
36
+
37
+ # array operations
38
+ array_in_list: "ARRAY_CONTAINS(@exp, ARRAY_CONSTRUCT(@list))"
39
+ array_exclude_list: "NOT ARRAY_CONTAINS(@exp, ARRAY_CONSTRUCT(@list))"
40
+ apply_advanced_filtering_on_array_projections: false # druid needs a having clause or un-nesting
41
+ array_unnest_join: "LATERAL FLATTEN(INPUT => @exp) @alias"
42
+
43
+ # null handling
44
+ if_null: "NVL(@exp, @when_null)"
45
+ null_if_zero: "NULLIFZERO(@exp)"
@@ -0,0 +1,80 @@
1
+ # quotes and string lit
2
+ quote: "[@exp]"
3
+ string_literal: "'@exp'"
4
+
5
+ # Date Literal Formats
6
+ date_format: "%Y-%m-%d"
7
+ date_time_format: "%Y-%m-%d %H:%M:%S"
8
+ date_time_tz_format: "%Y-%m-%d %H:%M:%S %Z"
9
+ date_type: "string" # alternative is int, integer, dateint
10
+ day_name_format: "dddd"
11
+ abbreviated_day_name_format: "ddd"
12
+ month_name_format: "mmmm"
13
+ abbreviated_month_name_format: "MMM"
14
+
15
+ # Date functions patterns
16
+ current_date: "CAST(GETDATE() DATE)"
17
+ current_time: "CAST(GETDATE() AS TIME)"
18
+ current_timestamp: "GETDATE()"
19
+ truncate_date: "DATETRUNC(@unit, @exp)"
20
+ date_add: "DATEADD(@unit, @val, @exp)"
21
+ date_diff: "DATEDIFF(DAY, @start_exp, @end_exp)"
22
+ date_format_sql: "FORMAT(@exp, '@format')"
23
+ date_literal: "'@val'"
24
+ date_time_literal: "'@val'"
25
+ extract_year: 'YEAR(@exp)'
26
+ extract_month: 'MONTH(@exp)'
27
+ extract_quarter: 'DATEPART(QUARTER, @exp)'
28
+ extract_day_of_year: 'DATEPART(DAYOFYEAR, @exp)'
29
+ extract_day_of_month: 'DAY(@exp)'
30
+ extract_day_of_week: 'DATEPART(WEEKDAY, @exp)'
31
+ extract_week_of_year: 'DATEPART(WEEK, @exp)'
32
+ extract_hour: 'DATEPART(HOUR, @exp)'
33
+ extract_minute: 'DATEPART(MINUTE, @exp)'
34
+ extract_year_month: 'CAST(CONCAT(YEAR(@exp), FORMAT(MONTH(@exp), N''00'')) AS INT)'
35
+ default_week_start_day: "sunday"
36
+ week_start_day: "monday"
37
+ sunday_week_start_day: "CAST(DATEADD(DAY, -(DATEPART(WEEKDAY, @exp) - 1), @exp) AS DATE)"
38
+ monday_week_start_day: "CAST(DATEADD(DAY, -(DATEPART(WEEKDAY, @exp) - 2), @exp) AS DATE)"
39
+ cast: "CAST(@exp AS @type)"
40
+
41
+ # string functions
42
+ trim: "TRIM(@exp)"
43
+ lower_case: "LOWER(@exp)"
44
+ upper_case: "UPPER(@exp)"
45
+
46
+ # null handling
47
+ if_null: "COALESCE(@exp, @when_null)"
48
+ null_if: "NULLIF(@exp, @target)"
49
+ null_if_zero: "NULLIF(@exp, 0)"
50
+
51
+ # Relevant db capabilities for query gen
52
+ supports_array_functions: false
53
+ supports_table_join: true
54
+ supports_full_join: true
55
+ supports_cross_join: true
56
+ supports_sub_queries: true
57
+ supports_common_table_expressions: true
58
+ supports_temp_tables: true
59
+ create_temp_table_template: "CREATE TEMPORARY TABLE @table AS \n@sql"
60
+ supports_window_functions: true
61
+ extend_ending_date_to_last_hour_of_day: false # druid needs this for inclusive filtering
62
+
63
+ # array operations
64
+ array_in_list: "ANY_MATCH(@exp, x -> x IN (@list)" # list is comma separated
65
+ array_exclude_list: "NONE_MATCH(@exp, x -> x IN (@list)" # list is comma separated
66
+ array_unnest_join: "CROSS JOIN UNNEST(@exp) @alias"
67
+
68
+ # joins
69
+ cross_join: "CROSS JOIN @relation"
70
+
71
+ # sql output behavior
72
+ temp_table_type: "cte" # options cte, subquery, temp
73
+ temp_table_prefix: ""
74
+ # Determines how measures across fact universes are combined.
75
+ # Default is full join when supported.
76
+ final_pass_measure_join_type: "full" # inner left right etc
77
+ apply_advanced_filtering_on_array_projections: false # druid needs a having clause or un-nesting
78
+ greedy_apply_date_filters: true
79
+ cross_universe_measure_filtering_strategy: "both" # both, final, intermediatet
80
+
@@ -0,0 +1,77 @@
1
+
2
+ # Date Literal Formats
3
+ date_format: "%Y-%m-%d"
4
+ date_time_format: "%Y-%m-%d %H:%M:%S"
5
+ date_time_tz_format: "%Y-%m-%d %H:%M:%S %Z"
6
+ date_type: "string" # alternative is int, integer, dateint
7
+ day_name_format: "%W"
8
+ abbreviated_day_name_format: "%a"
9
+ month_name_format: "%M"
10
+ abbreviated_month_name_format: "%b"
11
+
12
+ # Date functions patterns
13
+ current_date: "CURRENT_DATE"
14
+ current_time: "CURRENT_TIME"
15
+ current_timestamp: "CURRENT_TIMESTAMP"
16
+ truncate_date: "DATE_TRUNC('@unit', @exp)"
17
+ date_add: "DATE_ADD('@unit', @val, @exp)"
18
+ date_diff: "DATE_DIFF('@unit', @start_exp, @end_exp)"
19
+ date_format_sql: "DATE_FORMAT(@exp, '@format')"
20
+ date_literal: "DATE '@val'"
21
+ date_time_literal: "TIMESTAMP '@val'"
22
+ extract_year: 'YEAR(@exp)'
23
+ extract_month: 'MONTH(@exp)'
24
+ extract_quarter: 'QUARTER(@exp)'
25
+ extract_day_of_year: 'DAY_OF_YEAR(@exp)'
26
+ extract_day_of_month: 'DAY(@exp)'
27
+ extract_day_of_week: 'DAY_OF_WEEK(@exp)'
28
+ extract_week_of_year: 'WEEK(@exp)'
29
+ extract_hour: 'HOUR(@exp)'
30
+ extract_minute: 'MINUTE(@exp)'
31
+ extract_year_month: "CAST(DATE_FORMAT(@exp, '%Y%m') AS INTEGER)"
32
+ default_week_start_day: "monday"
33
+ week_start_day: "monday"
34
+ sunday_week_start_day: "DATE_ADD('day', -1,DATE_TRUNC('week', DATE_ADD('day',1, @exp)))"
35
+ monday_week_start_day: "DATE_ADD('day', 1, DATE_TRUNC('week', DATE_ADD('day',-1, @exp)))"
36
+
37
+ cast: "CAST(@exp AS @type)"
38
+
39
+ # string functions
40
+ trim: "TRIM(@exp)"
41
+ lower_case: "LOWER(@exp)"
42
+ upper_case: "UPPER(@exp)"
43
+
44
+ # null handling
45
+ if_null: "COALESCE(@exp, @when_null)"
46
+ null_if: "NULLIF(@exp, @target)"
47
+ null_if_zero: "NULLIF(@exp, 0)"
48
+
49
+ # Relevant db capabilities for query gen
50
+ supports_array_functions: true
51
+ supports_table_join: true
52
+ supports_full_join: true
53
+ supports_cross_join: true
54
+ supports_sub_queries: true
55
+ supports_common_table_expressions: true
56
+ supports_temp_tables: true
57
+ create_temp_table_template: "CREATE TEMPORARY TABLE @table AS \n@sql"
58
+ supports_window_functions: true
59
+ extend_ending_date_to_last_hour_of_day: false # druid needs this for inclusive filtering
60
+
61
+ # array operations
62
+ array_in_list: "ANY_MATCH(@exp, x -> x IN (@list)" # list is comma separated
63
+ array_exclude_list: "NONE_MATCH(@exp, x -> x IN (@list)" # list is comma separated
64
+ array_unnest_join: "CROSS JOIN UNNEST(@exp) @alias"
65
+
66
+ # joins
67
+ cross_join: "CROSS JOIN @relation"
68
+
69
+ # sql output behavior
70
+ temp_table_type: "cte" # options cte, subquery, temp
71
+ temp_table_prefix: ""
72
+ # Determines how measures across fact universes are combined.
73
+ # Default is full join when supported.
74
+ final_pass_measure_join_type: "full" # inner left right etc
75
+ apply_advanced_filtering_on_array_projections: false # druid needs a having clause or un-nesting
76
+ greedy_apply_date_filters: true
77
+ cross_universe_measure_filtering_strategy: "both" # both, final, intermediate
@@ -0,0 +1,79 @@
1
+ require 'yaml'
2
+
3
+ module DWH
4
+ # Functions related to loading and managing the Adapters
5
+ # settings. These settings should by default have the same name
6
+ # as the adapter but lower case and no camelcase. i.e. MySql adapter
7
+ # has a settings file called mysql.yml.
8
+ #
9
+ # When creating a new adapter copy {settings/base.yml} and modify it
10
+ # to suit your adapters needs.
11
+ #
12
+ # An adapters settings are merged into the base settings config. So each adapter
13
+ # doesn't have to define every property when they are the same.
14
+ #
15
+ # By default the file will be looked for in relative location like settings/myadapter.yml.
16
+ # However, you can specify the locastion with (@see #settings_file_path)
17
+ module Settings
18
+ include Logger
19
+
20
+ # Gets the current loaded adatper settings. If nil, then
21
+ # load_settings hasn't been called.
22
+ attr_reader :adapter_settings
23
+
24
+ # This is the default base settings that each adapter can override
25
+ # with its own yaml files.
26
+ BASE_SETTINGS_FILE = File.join(__dir__, 'settings', 'base.yml')
27
+
28
+ # This will load adapter level settings. These settings can be
29
+ # overridden at runtime by calling alter_settings after
30
+ # an adapter is initialized.
31
+ def load_settings
32
+ return unless @adapter_settings.nil?
33
+
34
+ logger.debug "+++ LOADING SETTINGS: #{name} +++"
35
+
36
+ @using_base = true
37
+ @adapter_settings = YAML.load_file(BASE_SETTINGS_FILE)
38
+
39
+ if File.exist?(settings_file)
40
+ @using_base = false
41
+ settings_from_file = YAML.load_file(settings_file) || {}
42
+ @adapter_settings.merge!(settings_from_file)
43
+ else
44
+ logger.debug "#{adapter_name} Adapter didn't have a settings YAML file. Using only base settings."
45
+ end
46
+
47
+ @adapter_settings.symbolize_keys!
48
+ end
49
+
50
+ # By default settings_file are expected to be in a
51
+ # relative directory called settings. If not,
52
+ # change the settings file with call to settings_file_path FILE_PATH
53
+ def settings_file
54
+ @settings_file ||= File.join(__dir__, 'settings', "#{adapter_name}.yml")
55
+ end
56
+
57
+ # Allows the manual configuration of where to
58
+ # load default database settings from.
59
+ #
60
+ # It will reload settings if adapter settings has already
61
+ # been loaded.
62
+ # @param [String] file - path or file name string
63
+ def settings_file_path(file)
64
+ @settings_file = file
65
+ return if @adapter_settings.nil?
66
+
67
+ @adapter_settings = nil
68
+ load_settings
69
+ end
70
+
71
+ def adapter_name
72
+ name.demodulize.downcase
73
+ end
74
+
75
+ def using_base_settings?
76
+ @using_base
77
+ end
78
+ end
79
+ end
@@ -0,0 +1,69 @@
1
+ module DWH
2
+ # Basic streaming stats collector. This is used when runing a query
3
+ # via execute_streaming method. As the data comes in it will write
4
+ # to the stats object. This can be read in another thread to
5
+ # update a UI.
6
+ class StreamingStats
7
+ # Most cases the streaming data will be streamed to a tempfile
8
+ # rather than memory. In those cases, we will keep a limited amount
9
+ # of data in memory. This is for previewing or other quick intropsections.
10
+ # The default limit is 20,000 rows.
11
+ attr_reader :in_memory_limit
12
+
13
+ def initialize(limit = 20_000)
14
+ @status = :init
15
+ @in_memory_limit = limit
16
+ @mutex = Mutex.new
17
+ reset
18
+ end
19
+
20
+ # Resets the data, total rows etc back to 0
21
+ def reset
22
+ @mutex.synchronize do
23
+ @total_rows = 0
24
+ @max_row_size = 0
25
+ @data = []
26
+ end
27
+ end
28
+
29
+ # Add a single row to the in memory dataset. Will
30
+ # automatically stop once the limit is reached.
31
+ #
32
+ # @param [Array] row
33
+ def <<(row)
34
+ raise ArgumentError, 'Row must be an array' unless row.is_a?(Array)
35
+
36
+ @mutex.synchronize do
37
+ @data << row unless @data.size >= @in_memory_limit
38
+ @total_rows += 1
39
+ @max_row_size = [@max_row_size, row.to_s.bytesize].max
40
+ end
41
+ end
42
+
43
+ def add_row(row)
44
+ self << row
45
+ end
46
+
47
+ # Returns the streamed result set thus far upto the
48
+ # specified limit or default 20,000 rows.
49
+ def data
50
+ @mutex.synchronize { @data }
51
+ end
52
+
53
+ # The total rows streamed. This is everything written to the IO object
54
+ # including whats in memory.
55
+ def total_rows
56
+ @mutex.synchronize { @total_rows }
57
+ end
58
+
59
+ # Largest row in bytesize. Can estimate eventual file size.
60
+ def max_row_size
61
+ @mutex.synchronize { @max_row_size }
62
+ end
63
+
64
+ # Whether the in memory row limit was reached
65
+ def limit_reached?
66
+ data.size >= in_memory_limit
67
+ end
68
+ end
69
+ end