sequelizer 0.1.6 → 0.3.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 (54) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +60 -0
  3. data/LICENSE +21 -0
  4. data/README.md +28 -14
  5. data/config/platforms/base.csv +5 -0
  6. data/config/platforms/rdbms/athena.csv +4 -0
  7. data/config/platforms/rdbms/postgres.csv +3 -0
  8. data/config/platforms/rdbms/snowflake.csv +1 -0
  9. data/config/platforms/rdbms/spark.csv +3 -0
  10. data/lib/sequel/extensions/cold_col.rb +41 -17
  11. data/lib/sequel/extensions/funky.rb +136 -0
  12. data/lib/sequel/extensions/make_readyable.rb +18 -10
  13. data/lib/sequel/extensions/platform.rb +300 -0
  14. data/lib/sequel/extensions/smart_select_remove.rb +101 -0
  15. data/lib/sequelizer/options.rb +15 -6
  16. data/lib/sequelizer/version.rb +1 -1
  17. data/lib/sequelizer/yaml_config.rb +0 -1
  18. metadata +90 -57
  19. data/.claude/settings.local.json +0 -64
  20. data/.devcontainer/.p10k.zsh +0 -1713
  21. data/.devcontainer/.zshrc +0 -29
  22. data/.devcontainer/Dockerfile +0 -137
  23. data/.devcontainer/copy-claude-credentials.sh +0 -32
  24. data/.devcontainer/devcontainer.json +0 -102
  25. data/.devcontainer/init-firewall.sh +0 -123
  26. data/.devcontainer/setup-credentials.sh +0 -95
  27. data/.github/workflows/test.yml +0 -14
  28. data/.gitignore +0 -40
  29. data/.overcommit.yml +0 -73
  30. data/.rubocop.yml +0 -167
  31. data/CLAUDE.md +0 -219
  32. data/Gemfile +0 -12
  33. data/Gemfile.lock +0 -158
  34. data/Guardfile +0 -28
  35. data/LICENSE.txt +0 -22
  36. data/Rakefile +0 -35
  37. data/examples/database.with_one_set_of_options.yml +0 -15
  38. data/examples/database.yml +0 -30
  39. data/examples/dot_env.txt +0 -10
  40. data/sequelizer.gemspec +0 -35
  41. data/test/lib/sequel/extensions/test_cold_col.rb +0 -251
  42. data/test/lib/sequel/extensions/test_db_opts.rb +0 -42
  43. data/test/lib/sequel/extensions/test_make_readyable.rb +0 -259
  44. data/test/lib/sequel/extensions/test_more_sql.rb +0 -132
  45. data/test/lib/sequel/extensions/test_settable.rb +0 -109
  46. data/test/lib/sequel/extensions/test_sql_recorder.rb +0 -231
  47. data/test/lib/sequel/extensions/test_unionize.rb +0 -76
  48. data/test/lib/sequel/extensions/test_usable.rb +0 -15
  49. data/test/lib/sequelizer/test_connection_maker.rb +0 -123
  50. data/test/lib/sequelizer/test_env_config.rb +0 -37
  51. data/test/lib/sequelizer/test_gemfile_modifier.rb +0 -88
  52. data/test/lib/sequelizer/test_options.rb +0 -83
  53. data/test/lib/sequelizer/test_yaml_config.rb +0 -83
  54. data/test/test_helper.rb +0 -44
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: bd4b9fbda8a56b5f1f9f83787e9fd0abbd76850d30447624ee513669fab9a5ed
4
- data.tar.gz: 51905a6233ab05fb60560b0542f2078de9f26cee1e6a1cb6d7e9cfdd6599b71f
3
+ metadata.gz: 348bea43e8571c35056619a31d45731f55b48a24cb4b93e94f23ecf7eba3a4af
4
+ data.tar.gz: 170ae6de8d06dc7f8030fd97151b1ff7b5666a6d94849a4fe3e056a863938a65
5
5
  SHA512:
6
- metadata.gz: a589e19ca1c6a7bc8b3d5ff125becf56f2b19336560286d937210efbbd075785f065ae8cd90cd248d0721bcae2af7cf99449a2ca78c5dc19fc338364db32c23b
7
- data.tar.gz: c697540e63315616982acfaed7a3488dea5abd6482bec1de8402cb6ac208144b0932511fbf39535a65498499e83bcf91bfbab4c530b5ed1a70541889769baa03
6
+ metadata.gz: 497923374b34e892918aa86dea037c0b25323dc8d829398bb0e97d77386c13e248b68d47f4c7c31650d099fdf85d9cf62203703c2576f31310054f9937df9119
7
+ data.tar.gz: f6a8dd133701a962fab9b16a0c0df30a4897d9c08526db07ec7ddef9029eb7140adcfbbab44974be7da2d970f2203308aa419b7112baad046947a50ad4ad93f5
data/CHANGELOG.md CHANGED
@@ -2,9 +2,56 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file.
4
4
 
5
+ ## [0.3.0] - 2026-10-01
6
+
7
+ ### Breaking changes
8
+
9
+ - Drop support for Ruby 3.2 ([feef6de](https://github.com/outcomesinsights/sequelizer/commit/feef6de5c155dc0dd39642ad1686ff9bab0211de)): sequelizer now requires Ruby >= 3.3.0.
10
+
11
+ ### Added
12
+
13
+ - Add smart_select_remove Sequel extension ([a1366ec](https://github.com/outcomesinsights/sequelizer/commit/a1366ec8f68e64728b3c794de15c2fd78cfa9e2e))
14
+ - DuckDB support in make_readyable and cold_col extensions ([9433d98](https://github.com/outcomesinsights/sequelizer/commit/9433d982bc0855df11ac6f48a915e861fd78a572))
15
+
16
+ ### Changed
17
+
18
+ - Extract available_tables to fix AbcSize in ReadyMaker#run ([60c6a68](https://github.com/outcomesinsights/sequelizer/commit/60c6a6803afbfde2b0747fd19e3bcd346bf2d1ef))
19
+ - Simplify cold_col find_columns and remove rescue nil guards ([752eab1](https://github.com/outcomesinsights/sequelizer/commit/752eab14595af23974ea56a976dd99e29d9d5552))
20
+ - Remove OptionalAdapterSupport, add sequel-duckdb to bundle ([74d6d16](https://github.com/outcomesinsights/sequelizer/commit/74d6d16f564742138a32e111d7b6107289abec75))
21
+ - Let Sequel handle adapter loading, remove pre-require ([c2b592d](https://github.com/outcomesinsights/sequelizer/commit/c2b592d1965e24370dae2f5cfb515097358cd3da))
22
+ - Ship only runtime files in the gem: lib/, the sequelizer executable, the platform CSVs, and the docs and licence ([1cc49b6](https://github.com/outcomesinsights/sequelizer/commit/1cc49b69dec0c6c879a469f0774c1196c467ed17))
23
+
24
+ ### Fixed
25
+
26
+ - Fall back to database query in cold_col for unregistered tables ([d07f7c5](https://github.com/outcomesinsights/sequelizer/commit/d07f7c5e482074e631828afbf558a767d6695b66))
27
+ - Replace rescue modifier with explicit begin/rescue in cold_col ([6fced2b](https://github.com/outcomesinsights/sequelizer/commit/6fced2b4957277b5c6d45fabf11e89d0b476a8e5))
28
+ - Handle string SQL in cold_col create_table_as and create_view_sql ([8f30602](https://github.com/outcomesinsights/sequelizer/commit/8f306028857e3838370fc623cd619a9a79c8c06f))
29
+ - Handle Array search_path in after_connect ([c376825](https://github.com/outcomesinsights/sequelizer/commit/c3768251695286668ca49dcbb84aa12c3bbb7f69))
30
+
31
+ ## 0.2.0
32
+
33
+ ### Added
34
+
35
+ - funky Sequel extension for database-specific function abstraction
36
+ - kvcsv as a runtime dependency
37
+ - Platform configuration fixtures in config/platforms/
38
+
39
+ ### Changed
40
+
41
+ - Broadened activesupport dependency from ~> 7.0 to >= 7, < 9
42
+ - Broadened hashie dependency from ~> 3.2 to >= 3.2, < 6.0
43
+ - Broadened dotenv dependency from ~> 2.1 to >= 2.1, < 4.0
44
+ - Bumped sequel from 5.93.0 to 5.101.0
45
+ - Added multi-Ruby CI matrix (3.2, 3.3, 3.4, 4.0) with separate lint job
46
+
47
+ ### Fixed
48
+
49
+ - Adapter extraction from URL scheme for search_path processing
50
+
5
51
  ## 0.1.6
6
52
 
7
53
  ### Removed
54
+
8
55
  - JDBC adapter support (jdbc_hive2, jdbc_impala, jdbc_postgres) - not needed for foreseeable future
9
56
  - Native Impala adapter support - not needed for foreseeable future
10
57
  - Kerberos authentication functionality for enterprise databases
@@ -12,9 +59,11 @@ All notable changes to this project will be documented in this file.
12
59
  - 16 test methods related to JDBC and Impala adapters
13
60
 
14
61
  ### Added
62
+
15
63
  - pg gem as development dependency to support PostgreSQL testing
16
64
 
17
65
  ### Changed
66
+
18
67
  - Simplified ConnectionMaker class by removing adapter-specific configuration methods
19
68
  - Improved test coverage from 84.95% to 93.54% by removing unused code paths
20
69
  - Updated documentation to reflect focus on standard Sequel adapters
@@ -28,11 +77,13 @@ All notable changes to this project will be documented in this file.
28
77
  ## [0.1.0] - 2016-11-08
29
78
 
30
79
  ### Added
80
+
31
81
  - Connections are cached by options to avoid over-allocation
32
82
  - URL or URI option represent connection string
33
83
  - sequelizer.yml is passed through ERB
34
84
 
35
85
  ### Changed
86
+
36
87
  - Format of this [CHANGELOG](http://keepachangelog.com/en/0.3.0/)
37
88
  - Prefer environment variables over other options
38
89
  - Use config/sequelizer.yml instead of config/database.yml
@@ -40,34 +91,41 @@ All notable changes to this project will be documented in this file.
40
91
  ## [0.0.6] - 2015-08-21
41
92
 
42
93
  ### Added
94
+
43
95
  - Support for ruby-oci8 (Oracle) in update_gemfile command
44
96
  - Read user-level configuration from ~/.config/sequelizer/database.yml
45
97
 
46
98
  ### Fixed
99
+
47
100
  - Bug where options passed as symbols where sometimes ignored.
48
101
 
49
102
  ## [0.0.5] - 2014-08-29
50
103
 
51
104
  ### Added
105
+
52
106
  - Support for TinyTDS (SQL Server) in update_gemfile command
53
107
 
54
108
  ### Fixed
109
+
55
110
  - timeout is always converted to integer before passing to Sequel.connect
56
111
 
57
112
  ## [0.0.4] - 2014-08-18
58
113
 
59
114
  ### Added
115
+
60
116
  - `init_env` command to bin/sequelizer
61
117
  - Prefer `search_path` over `schema_search_path` option
62
118
 
63
119
  ## [0.0.3] - 2014-07-10
64
120
 
65
121
  ### Added
122
+
66
123
  - Ability to view configuration by running `sequelizer config`
67
124
 
68
125
  ## [0.0.2] - 2014-07-10
69
126
 
70
127
  ### Added
128
+
71
129
  - This [CHANGELOG](http://keepachangelog.com/)
72
130
  - Behavior to merge options from all sources (#3)
73
131
  - Dependency on hashie gem
@@ -76,9 +134,11 @@ All notable changes to this project will be documented in this file.
76
134
  - Reference to issues #1, #3 in README
77
135
 
78
136
  ### Fixed
137
+
79
138
  - Prevented TestEnvConfig from polluting environment variables
80
139
 
81
140
  ## [0.0.1] - 2014-07-10
82
141
 
83
142
  ### Added
143
+
84
144
  - The project itself
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2014-2026 Outcomes Insights, Inc.
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
data/README.md CHANGED
@@ -12,35 +12,46 @@ I normally use this gem when I'm writing a quick script or a Thor-based command
12
12
 
13
13
  Add this line to your application's Gemfile:
14
14
 
15
- gem 'sequelizer'
15
+ ```
16
+ gem 'sequelizer'
17
+ ```
16
18
 
17
19
  And then execute:
18
20
 
19
- $ bundle
21
+ ```
22
+ $ bundle
23
+ ```
20
24
 
21
25
  Or install it yourself as:
22
26
 
23
- $ gem install sequelizer
27
+ ```
28
+ $ gem install sequelizer
29
+ ```
24
30
 
25
31
  ## Usage
26
32
 
27
33
  To get the most out of Sequelizer, you'll need to create a config/database.yml file or a .env file and specify your database configuration options in that file.
28
34
 
29
- Sequelizer comes with a handy command that will print out your connection parameters. Just run:
35
+ Sequelizer comes with a handy command that will print out your connection parameters. Just run:
30
36
 
31
- bundle exec sequelizer config
37
+ ```
38
+ bundle exec sequelizer config
39
+ ```
32
40
 
33
- You'll also need to make sure the gem for your database is installed. You can do this by adding the gem to your application's Gemfile.
41
+ You'll also need to make sure the gem for your database is installed. You can do this by adding the gem to your application's Gemfile.
34
42
 
35
- Sequelizer comes with a handy command that will update your Gemfile for you. Once you've specified your database configuration, run
43
+ Sequelizer comes with a handy command that will update your Gemfile for you. Once you've specified your database configuration, run
36
44
 
37
- bundle exec sequelizer update_gemfile
45
+ ```
46
+ bundle exec sequelizer update_gemfile
47
+ ```
38
48
 
39
49
  The command will look up the right gem to use with the adapter you've specified, add a line to your Gemfile specifying that gem, and run `bundle install` to install the gem for you.
40
50
 
41
51
  Once you've specified your options and made sure your database's gem is installed, simply include the Sequelizer module in any class that needs a database connection and you'll get two handy-dandy methods: `db` and `new_db`
42
52
 
43
53
  Observe:
54
+
44
55
  ```ruby
45
56
  require 'sequelizer'
46
57
 
@@ -59,17 +70,19 @@ end
59
70
 
60
71
  `new_db` will create a new connection to the database on each call.
61
72
 
62
- Both take a hash of database options if you don't want to create a config/database.yml or .env file, or simply wish to override those options. Options are merged together from all sources with the following precedence:
73
+ Both take a hash of database options if you don't want to create a config/database.yml or .env file, or simply wish to override those options. Options are merged together from all sources with the following precedence:
63
74
 
64
- passed_options > .env > manually defined environment variables > config/database.yml > ~/.config/sequelizer/database.yml
75
+ ```
76
+ passed_options > .env > manually defined environment variables > config/database.yml > ~/.config/sequelizer/database.yml
77
+ ```
65
78
 
66
- So if config/database.yml specifies a connection, you can set an environment variable (either manually, or through .env) to override one of those options. Similarly, if you pass an option to the method directly, that option will override the YAML and ENV-based options. See #3 for further discussion.
79
+ So if config/database.yml specifies a connection, you can set an environment variable (either manually, or through .env) to override one of those options. Similarly, if you pass an option to the method directly, that option will override the YAML and ENV-based options. See #3 for further discussion.
67
80
 
68
81
  Take a look at the examples directory for a few ways you can specify your database configuration options.
69
82
 
70
83
  ## Frustrations
71
84
 
72
- I can't seem to figure out a way to avoid having to specify the database gem in the a user's bundler file. If anyone has ideas on how to automagically load the correct database gem based on the database options fed to Sequelizer, please let me know (#1)!
85
+ I can't seem to figure out a way to avoid having to specify the database gem in the a user's bundler file. If anyone has ideas on how to automagically load the correct database gem based on the database options fed to Sequelizer, please let me know (#1)!
73
86
 
74
87
  ## Contributing
75
88
 
@@ -82,9 +95,10 @@ I can't seem to figure out a way to avoid having to specify the database gem in
82
95
  ## Thanks
83
96
 
84
97
  - [Outcomes Insights, Inc.](http://outins.com)
85
- - Many thanks for allowing me to release a portion of my work as Open Source Software!
98
+ - Many thanks for allowing me to release a portion of my work as Open Source Software!
86
99
  - Jeremy Evans
87
- - For writing Sequel!
100
+ - For writing Sequel!
88
101
 
89
102
  ## License
103
+
90
104
  Released under the MIT license, Copyright (c) 2014 Outcomes Insights, Inc.
@@ -0,0 +1,5 @@
1
+ key,value
2
+ supports_cte,true
3
+ supports_cte_recursive,true
4
+ supports_temp_tables,true
5
+ drop_table_needs_unquoted,false
@@ -0,0 +1,4 @@
1
+ key,value
2
+ supports_temp_tables,false
3
+ supports_cte_recursive,false
4
+ drop_table_needs_unquoted,true
@@ -0,0 +1,3 @@
1
+ key,value
2
+ prefers_cte,true
3
+ schema_switching_method,search_path
@@ -0,0 +1 @@
1
+ key,value
@@ -0,0 +1,3 @@
1
+ key,value
2
+ prefers_cte,false
3
+ prefers_parquet,true
@@ -88,37 +88,27 @@ module Sequel
88
88
  end
89
89
 
90
90
  # Find column information for a given table/view name.
91
- # This method searches through all available registries in priority order:
91
+ # Searches all registries in priority order:
92
92
  # 1. Created views (highest priority - most recent)
93
93
  # 2. Created tables (medium priority - session specific)
94
94
  # 3. Loaded schemas (lowest priority - external definitions)
95
95
  #
96
- # @param name [String, Symbol] the table/view name to look up
96
+ # @param name [String, Symbol, Sequel::SQL::Identifier, Sequel::SQL::QualifiedIdentifier]
97
97
  # @return [Array<Symbol>, nil] array of column names as symbols, or nil if not found
98
98
  def find_columns(name)
99
- table_name = name.to_s
100
99
  literal_name = @db.literal(name)
100
+ table_name = name_to_string(name)
101
101
 
102
- # Search through registries in priority order
103
102
  [@created_views, @created_tables, @schemas].each do |registry|
104
103
  next unless registry
105
104
 
106
- # Try literal representation first (most common for created tables/views)
107
105
  if (columns = Sequel.synchronize { registry[literal_name] })
108
106
  return columns.map { |c, _| c }
109
107
  end
110
108
 
111
- # Try string representation (for manually added schemas)
112
109
  if (columns = Sequel.synchronize { registry[table_name] })
113
110
  return columns.map { |c, _| c }
114
111
  end
115
-
116
- # Try finding by Sequel::LiteralString key (for test setup compatibility)
117
- registry.each_key do |key|
118
- if key.respond_to?(:to_s) && key.to_s == literal_name && (columns = Sequel.synchronize { registry[key] })
119
- return columns.map { |c, _| c }
120
- end
121
- end
122
112
  end
123
113
 
124
114
  nil
@@ -140,6 +130,22 @@ module Sequel
140
130
  Sequel.synchronize { @schemas = schemas_hash }
141
131
  end
142
132
 
133
+ private
134
+
135
+ # Extract a plain string name from any Sequel name type.
136
+ # Sequel::SQL::Identifier#to_s returns an inspect-like string, not the value,
137
+ # so we must unwrap expression types to get a usable lookup key.
138
+ def name_to_string(name)
139
+ case name
140
+ when Sequel::SQL::QualifiedIdentifier
141
+ "#{name_to_string(name.table)}.#{name_to_string(name.column)}"
142
+ when Sequel::SQL::Identifier
143
+ name.value.to_s
144
+ else
145
+ name.to_s
146
+ end
147
+ end
148
+
143
149
  end
144
150
 
145
151
  # Sets up the cold column tracking when the extension is loaded
@@ -172,7 +178,12 @@ module Sequel
172
178
 
173
179
  def create_table_as(name, sql, options = {})
174
180
  super.tap do |_|
175
- record_table(name, columns_from_sql(sql))
181
+ columns = begin
182
+ columns_from_sql(sql)
183
+ rescue StandardError
184
+ nil
185
+ end
186
+ record_table(name, columns) if columns
176
187
  end
177
188
  end
178
189
 
@@ -190,7 +201,12 @@ module Sequel
190
201
 
191
202
  def create_view_sql(name, source, options)
192
203
  super.tap do |_|
193
- record_view(name, columns_from_sql(source)) unless options[:dont_record]
204
+ columns = begin
205
+ columns_from_sql(source)
206
+ rescue StandardError
207
+ nil
208
+ end
209
+ record_view(name, columns) if columns && !options[:dont_record]
194
210
  end
195
211
  end
196
212
 
@@ -292,7 +308,7 @@ module Sequel
292
308
  # @param opts_chain [Hash] the dataset's query options
293
309
  # @return [Array<Symbol>] array of column names from table.* expressions
294
310
  def extract_table_star_columns(cols, opts_chain)
295
- cols.select { |c| c.is_a?(Sequel::SQL::ColumnAll) }
311
+ cols.grep(Sequel::SQL::ColumnAll)
296
312
  .flat_map { |c| from_named_sources(c.table, opts_chain) }
297
313
  end
298
314
 
@@ -348,6 +364,14 @@ module Sequel
348
364
  return columns
349
365
  end
350
366
 
367
+ # Fall back to database query for real tables cold_col doesn't know about
368
+ begin
369
+ columns = db[name].columns!
370
+ return columns if columns && !columns.empty?
371
+ rescue StandardError
372
+ nil
373
+ end
374
+
351
375
  raise("Failed to find columns for #{literal(name)}")
352
376
  end
353
377
 
@@ -359,7 +383,7 @@ module Sequel
359
383
  # @return [Array<Symbol>, nil] column names if found, nil otherwise
360
384
  def find_from_alias(name, opts_chain)
361
385
  from = (opts_chain[:from] || [])
362
- .select { |f| f.is_a?(Sequel::SQL::AliasedExpression) }
386
+ .grep(Sequel::SQL::AliasedExpression)
363
387
  .detect { |f| literal(f.alias) == literal(name) }
364
388
 
365
389
  from&.expression&.columns_search(opts_chain)
@@ -0,0 +1,136 @@
1
+ module Sequel
2
+
3
+ module Funky
4
+
5
+ class FunkyBase
6
+
7
+ def initialize(db)
8
+ @db = db
9
+ end
10
+
11
+ def to_strptime(format)
12
+ return format if format =~ /%/
13
+
14
+ format.gsub('yyyy', '%Y').gsub('MM', '%m').gsub('dd', '%d')
15
+ end
16
+
17
+ def from_strptime(format)
18
+ return format unless format =~ /%/
19
+
20
+ format.gsub('%Y', 'yyyy').gsub('%m', 'MM').gsub('%d', 'dd')
21
+ end
22
+
23
+ end
24
+
25
+ class FunkySpark < FunkyBase
26
+
27
+ def str_to_date(value, format, try: false) # rubocop:disable Lint/UnusedMethodArgument
28
+ Sequel.function(:to_date, Sequel.cast_string(value), format)
29
+ end
30
+
31
+ def hash(*)
32
+ Sequel.function(:xxhash64, *)
33
+ end
34
+
35
+ def make_json_column(ds, key_column, value_column)
36
+ json_object_col = Sequel.function(
37
+ :named_struct,
38
+ 'key',
39
+ key_column,
40
+ 'value',
41
+ value_column,
42
+ ).then do |json_object_col|
43
+ Sequel.function(
44
+ :collect_list,
45
+ json_object_col,
46
+ )
47
+ end.then do |list_col|
48
+ Sequel.function(
49
+ :map_from_entries,
50
+ list_col,
51
+ )
52
+ end.then do |map_from_entries_col|
53
+ Sequel.function(
54
+ :to_json,
55
+ map_from_entries_col,
56
+ )
57
+ end
58
+ ds.from_self
59
+ .select(json_object_col)
60
+ .limit(1)
61
+ end
62
+
63
+ def collect_list(column)
64
+ Sequel.function(:collect_list, column)
65
+ end
66
+
67
+ end
68
+
69
+ class FunkyDuckDB < FunkyBase
70
+
71
+ def str_to_date(value, format, try: false)
72
+ strptime_func = try ? :try_strptime : :strptime
73
+ Sequel.function(strptime_func, Sequel.cast_string(value), to_strptime(format))
74
+ end
75
+
76
+ def hash(*)
77
+ Sequel.function(:hash, concat(*)).then do |hash_val|
78
+ Sequel.case(
79
+ { hash_val <= 9_223_372_036_854_775_807 => hash_val },
80
+ hash_val - 18_446_744_073_709_551_616,
81
+ ).cast(:bigint)
82
+ end
83
+ end
84
+
85
+ def concat(*)
86
+ Sequel.function(:concat, *)
87
+ end
88
+
89
+ def make_json_column(ds, key_column, value_column)
90
+ json_object_col = Sequel.function(
91
+ :json_object,
92
+ Sequel.cast_string(key_column),
93
+ value_column,
94
+ ).then do |json_object_col|
95
+ Sequel.function(
96
+ :list,
97
+ json_object_col,
98
+ )
99
+ end
100
+ ds.from_self
101
+ .select(json_object_col)
102
+ .limit(1)
103
+ end
104
+
105
+ def collect_list(column)
106
+ Sequel.function(:list, column)
107
+ end
108
+
109
+ end
110
+
111
+ def self.extended(db)
112
+ db.instance_exec do
113
+ @funky = get_funky(db.database_type)
114
+ end
115
+ end
116
+
117
+ def funky
118
+ @funky
119
+ end
120
+
121
+ def get_funky(database_type)
122
+ case database_type
123
+ when :spark
124
+ FunkySpark.new(self)
125
+ when :duckdb
126
+ FunkyDuckDB.new(self)
127
+ else
128
+ raise "No known functions for #{database_type}"
129
+ end
130
+ end
131
+
132
+ end
133
+
134
+ Database.register_extension(:funky, Funky)
135
+
136
+ end
@@ -1,5 +1,3 @@
1
- require 'pathname'
2
-
3
1
  module Sequel
4
2
 
5
3
  # = MakeReadyable
@@ -89,13 +87,9 @@ module Sequel
89
87
  only_tables = Array(opts[:only])
90
88
  created_views = Array(opts[:except]) || []
91
89
  (opts[:search_path] || []).flatten.each do |schema|
92
- schema = schema.to_sym unless schema.is_a?(Pathname)
90
+ schema = schema.to_sym unless schema.is_a?(Pathname) || schema.is_a?(Sequel::SQL::QualifiedIdentifier)
93
91
  source = get_source(db, schema)
94
- tables = if schema.is_a?(Pathname)
95
- source.tables - created_views
96
- else
97
- source.tables(schema: schema) - created_views
98
- end
92
+ tables = available_tables(source, schema, created_views)
99
93
  tables &= only_tables unless only_tables.empty?
100
94
  tables.each do |table|
101
95
  create_view(source, table, schema)
@@ -104,6 +98,20 @@ module Sequel
104
98
  end
105
99
  end
106
100
 
101
+ # Returns tables (and views) from the source that haven't already been created.
102
+ #
103
+ # @param source [Sequel::Database, FileSourcerer] the source handler
104
+ # @param schema [Symbol, Pathname] the schema or file path
105
+ # @param created_views [Array<Symbol>] tables/views already created
106
+ # @return [Array<Symbol>] available table names
107
+ def available_tables(source, schema, created_views)
108
+ if schema.is_a?(Pathname)
109
+ source.tables - created_views
110
+ else
111
+ (source.tables(schema: schema) + source.views(schema: schema)) - created_views
112
+ end
113
+ end
114
+
107
115
  # Creates a temporary view for the given table.
108
116
  #
109
117
  # @param source [Object] the source (database or FileSourcerer)
@@ -112,9 +120,9 @@ module Sequel
112
120
  def create_view(source, table, schema)
113
121
  if schema.to_s =~ %r{/}
114
122
  source.create_view(table, temp: true)
123
+ elsif db.database_type == :duckdb
124
+ source.create_or_replace_view(table, db[Sequel.qualify(schema, table)], temp: true)
115
125
  else
116
- # For schema-based tables, just create temporary views
117
- # This extension is primarily for Spark SQL-based databases
118
126
  source.create_view(table, db[Sequel.qualify(schema, table)], temp: true)
119
127
  end
120
128
  end