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.
- checksums.yaml +7 -0
- data/.rubocop.yml +36 -0
- data/CHANGELOG.md +5 -0
- data/LICENSE +21 -0
- data/README.md +130 -0
- data/Rakefile +42 -0
- data/docs/DWH/Adapters/Adapter.html +3053 -0
- data/docs/DWH/Adapters/Athena.html +1704 -0
- data/docs/DWH/Adapters/Boolean.html +121 -0
- data/docs/DWH/Adapters/Druid.html +1626 -0
- data/docs/DWH/Adapters/DuckDb.html +2012 -0
- data/docs/DWH/Adapters/MySql.html +1704 -0
- data/docs/DWH/Adapters/OpenAuthorizable/ClassMethods.html +265 -0
- data/docs/DWH/Adapters/OpenAuthorizable.html +1102 -0
- data/docs/DWH/Adapters/Postgres.html +2000 -0
- data/docs/DWH/Adapters/Snowflake.html +1662 -0
- data/docs/DWH/Adapters/SqlServer.html +2084 -0
- data/docs/DWH/Adapters/Trino.html +1835 -0
- data/docs/DWH/Adapters.html +129 -0
- data/docs/DWH/AuthenticationError.html +142 -0
- data/docs/DWH/Behaviors.html +767 -0
- data/docs/DWH/Capabilities.html +748 -0
- data/docs/DWH/Column.html +1115 -0
- data/docs/DWH/ConfigError.html +143 -0
- data/docs/DWH/ConnectionError.html +143 -0
- data/docs/DWH/DWHError.html +138 -0
- data/docs/DWH/ExecutionError.html +143 -0
- data/docs/DWH/Factory.html +1133 -0
- data/docs/DWH/Functions/Arrays.html +505 -0
- data/docs/DWH/Functions/Dates.html +1644 -0
- data/docs/DWH/Functions/ExtractDatePart.html +804 -0
- data/docs/DWH/Functions/Nulls.html +377 -0
- data/docs/DWH/Functions.html +846 -0
- data/docs/DWH/Logger.html +258 -0
- data/docs/DWH/OAuthError.html +138 -0
- data/docs/DWH/Settings.html +658 -0
- data/docs/DWH/StreamingStats.html +804 -0
- data/docs/DWH/Table.html +1260 -0
- data/docs/DWH/TableStats.html +583 -0
- data/docs/DWH/TokenExpiredError.html +142 -0
- data/docs/DWH/UnsupportedCapability.html +135 -0
- data/docs/DWH.html +220 -0
- data/docs/_index.html +471 -0
- data/docs/class_list.html +54 -0
- data/docs/css/common.css +1 -0
- data/docs/css/full_list.css +58 -0
- data/docs/css/style.css +503 -0
- data/docs/file.README.html +210 -0
- data/docs/file.adapters.html +514 -0
- data/docs/file.creating-adapters.html +497 -0
- data/docs/file.getting-started.html +288 -0
- data/docs/file.usage.html +446 -0
- data/docs/file_list.html +79 -0
- data/docs/frames.html +22 -0
- data/docs/guides/adapters.md +445 -0
- data/docs/guides/creating-adapters.md +430 -0
- data/docs/guides/getting-started.md +225 -0
- data/docs/guides/usage.md +378 -0
- data/docs/index.html +210 -0
- data/docs/js/app.js +344 -0
- data/docs/js/full_list.js +242 -0
- data/docs/js/jquery.js +4 -0
- data/docs/method_list.html +2038 -0
- data/docs/top-level-namespace.html +110 -0
- data/lib/dwh/adapters/athena.rb +359 -0
- data/lib/dwh/adapters/druid.rb +267 -0
- data/lib/dwh/adapters/duck_db.rb +235 -0
- data/lib/dwh/adapters/my_sql.rb +235 -0
- data/lib/dwh/adapters/open_authorizable.rb +215 -0
- data/lib/dwh/adapters/postgres.rb +250 -0
- data/lib/dwh/adapters/snowflake.rb +489 -0
- data/lib/dwh/adapters/sql_server.rb +257 -0
- data/lib/dwh/adapters/trino.rb +213 -0
- data/lib/dwh/adapters.rb +363 -0
- data/lib/dwh/behaviors.rb +67 -0
- data/lib/dwh/capabilities.rb +39 -0
- data/lib/dwh/column.rb +79 -0
- data/lib/dwh/errors.rb +29 -0
- data/lib/dwh/factory.rb +125 -0
- data/lib/dwh/functions/arrays.rb +42 -0
- data/lib/dwh/functions/dates.rb +162 -0
- data/lib/dwh/functions/extract_date_part.rb +70 -0
- data/lib/dwh/functions/nulls.rb +31 -0
- data/lib/dwh/functions.rb +86 -0
- data/lib/dwh/logger.rb +50 -0
- data/lib/dwh/settings/athena.yml +77 -0
- data/lib/dwh/settings/base.yml +81 -0
- data/lib/dwh/settings/databricks.yml +51 -0
- data/lib/dwh/settings/druid.yml +59 -0
- data/lib/dwh/settings/duckdb.yml +44 -0
- data/lib/dwh/settings/mysql.yml +67 -0
- data/lib/dwh/settings/postgres.yml +30 -0
- data/lib/dwh/settings/redshift.yml +52 -0
- data/lib/dwh/settings/snowflake.yml +45 -0
- data/lib/dwh/settings/sqlserver.yml +80 -0
- data/lib/dwh/settings/trino.yml +77 -0
- data/lib/dwh/settings.rb +79 -0
- data/lib/dwh/streaming_stats.rb +69 -0
- data/lib/dwh/table.rb +105 -0
- data/lib/dwh/table_stats.rb +51 -0
- data/lib/dwh/version.rb +5 -0
- data/lib/dwh.rb +54 -0
- data/sig/dwh.rbs +4 -0
- 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
|
data/lib/dwh/settings.rb
ADDED
@@ -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
|