conceptql 0.4.0 → 0.4.1

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5201b0144372677675ffcd8abea73662b8e79544ffacfbbd1a61e39a9923d2da
4
- data.tar.gz: b81fc6806c7aae55562b073e33b2f6704f36fd6cd57266ffe6b8055df6c6baa0
3
+ metadata.gz: 1958ad620e733aede026fc74e0c21f06a2376031b514d6a7736ef287eda9afc5
4
+ data.tar.gz: 0ed440d679a23994a83237d54120eabac40bbcd9d9b7499e8cfff18c076aabd8
5
5
  SHA512:
6
- metadata.gz: 2a49e99ec315bac889401893e68a83de444ab6ac3307e3ae08897a07f7cd59f9a60e3f4f712cff0d43e4d50394d6ff921900e7c23f06f86fdd6134f691fd1d1f
7
- data.tar.gz: bf260ffadecac3a5e0dbd8aeb6eb932258fdebcc709363be34704b8f74abde9bd092be0f5710208b4a84d362758087c0c7fb4bf72871f2bafce8fb9496d5fbf9
6
+ metadata.gz: f42b9ec69eefd01041c9eab5f3aa421aaf8fc63df0933df1e0ab79a9919f4e4da06f48338c96f6af51226fb567ce15f3355116a962dd757d111efd14bdf262da
7
+ data.tar.gz: c50c2a4934b10f457ea25fb317f7844ab98f5816f55ea09aad50f1cb9a24424b567f67abf4ec9585ac677435641db986947b2b78b33f388b4f46a1bdb6f9bcd8
data/CHANGELOG.md CHANGED
@@ -4,6 +4,26 @@ All notable changes to this project will be documented in this file.
4
4
 
5
5
  ## [Unreleased]
6
6
 
7
+ ## [0.4.1] - 2026-10-28
8
+
9
+ ### Changed
10
+
11
+ - `Query#sql(:formatted)` formats SQL inside the Ruby process with the new runtime dependency
12
+ sequel-sqlformat (`~> 0.1`), a binding to the Rust `sqlformat` crate. It no longer starts
13
+ sql-formatter, pg_format or sqlformat once per statement. A large algorithm (78 statements)
14
+ now formats in about 0.13 s instead of about 8.3 s. Formatting changes only whitespace and
15
+ keyword case, for Postgres, DuckDB and Spark SQL. sequel-sqlformat ships precompiled gems
16
+ for Linux and macOS, so no Rust toolchain is needed.
17
+ - The development dependency sequel-duckdb is now `~> 0.4.2` (was `~> 0.4.1`). 0.4.2 fixes
18
+ `create_or_replace_view` and drops support for the duckdb gem 1.5.x, which conceptql
19
+ already did not use.
20
+
21
+ ### Removed
22
+
23
+ - `ConceptQL::SqlFormatters`, every adapter's `preferred_formatter`, and
24
+ `ConceptQL::Utils.timed_capture`. The external formatter programs are no longer used.
25
+ - The test Docker image no longer installs the `sqlformat` package.
26
+
7
27
  ## [0.4.0] - 2026-10-26
8
28
 
9
29
  ### Added
@@ -4,7 +4,7 @@ require "json"
4
4
  require "forwardable"
5
5
  require_relative "scope"
6
6
  require_relative "nodifier"
7
- require_relative "sql_formatters"
7
+ require "sequel/sqlformat"
8
8
 
9
9
  module ConceptQL
10
10
  class Query
@@ -208,8 +208,11 @@ module ConceptQL
208
208
  end
209
209
  end
210
210
 
211
+ # Formats inside the Ruby process with the sequel-sqlformat gem (the Rust
212
+ # sqlformat crate). It changes only whitespace and keyword case, and it never
213
+ # fails on unknown syntax, so DuckDB and Spark SQL format too.
211
214
  def format(sql)
212
- SqlFormatters.format(sql, rdbms)
215
+ Sequel::SQLFormat.format(sql, dialect: Sequel::SQLFormat.dialect_for(cdb.database_type), indent: 2, uppercase: true)
213
216
  end
214
217
  end
215
218
  end
@@ -12,10 +12,6 @@ module ConceptQL
12
12
  Sequel.function(:datediff, "day", to, from)
13
13
  end
14
14
 
15
- def preferred_formatter
16
- SqlFormatters::PG_FORMAT
17
- end
18
-
19
15
  # DuckDB accepts WITH ... AS MATERIALIZED since v0.8.0.
20
16
  def supports_materialized?
21
17
  true
@@ -59,10 +59,6 @@ module ConceptQL
59
59
  end
60
60
  end
61
61
 
62
- def preferred_formatter
63
- SqlFormatters::SQL_FORMATTER
64
- end
65
-
66
62
  # Returns from - to in days, NOT to - from, so datediff(later, earlier)
67
63
  # is positive. Every adapter keeps this order. This default emits
68
64
  # Spark's datediff(endDate, startDate), which returns endDate - startDate,
@@ -14,10 +14,6 @@ module ConceptQL
14
14
  db.vacuum_table(table_name, analyze: true) if analyze_temp_tables?
15
15
  end
16
16
 
17
- def preferred_formatter
18
- SqlFormatters::POSTGRES
19
- end
20
-
21
17
  # DISTINCT ON is Postgres-only. The other adapters inherit
22
18
  # Generic#primary_concepts, which uses ROW_NUMBER() instead.
23
19
  def primary_concepts(db, all_primary_ids)
@@ -13,10 +13,6 @@ module ConceptQL
13
13
  def null_safe_equal(lhs, rhs)
14
14
  Sequel.lit("(? <=> ?)", lhs, rhs)
15
15
  end
16
-
17
- def preferred_formatter
18
- SqlFormatters::PG_FORMAT
19
- end
20
16
  end
21
17
  end
22
18
  end
@@ -4,8 +4,6 @@ require "active_support/core_ext/array/conversions"
4
4
  require "active_support/core_ext/object/blank"
5
5
  require "active_support/core_ext/string/inflections"
6
6
  require "json"
7
- require "open3"
8
- require "timeout"
9
7
 
10
8
  module ConceptQL
11
9
  module Utils
@@ -31,47 +29,6 @@ module ConceptQL
31
29
  end
32
30
  end
33
31
 
34
- def timed_capture(*commands)
35
- # Heavily adapted from:
36
- # https://gist.github.com/lpar/1032297#gistcomment-1738285
37
- opts = extract_opts!(commands)
38
- timeout = opts.fetch(:timeout)
39
-
40
- stdin, stdout, stderr, wait_thread = Open3.popen3(*commands)
41
- wait_thread[:timed_out] = false
42
- stdin.puts opts[:stdin_data] if opts[:stdin_data]
43
- stdin.close
44
-
45
- # Purposefully NOT using Timeout.rb because in general it is a dangerous API!
46
- # http://blog.headius.com/2008/02/rubys-threadraise-threadkill-timeoutrb.html
47
- Thread.new do
48
- sleep timeout
49
- if wait_thread.alive?
50
- begin
51
- wait_thread[:timed_out] = true
52
- # please note: we are assuming the command will create ONE process (not handling subprocs / proc groups)
53
- command = "kill -9 #{wait_thread.pid}"
54
- system(command)
55
- rescue(Errno::ESRCH)
56
- # Do nothing!
57
- end
58
- end
59
- end
60
-
61
- if (es = wait_thread.value.exitstatus) && !es.zero?
62
- raise stderr.read
63
- end
64
-
65
- out = stdout.read
66
- stdout.close
67
-
68
- if wait_thread[:timed_out]
69
- raise Timeout::Error, "Command #{commands} failed to complete after #{timeout} seconds"
70
- end
71
-
72
- out
73
- end
74
-
75
32
  def extract_opts!(arr)
76
33
  return {} unless arr.last.is_a?(Hash)
77
34
 
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ConceptQL
4
- VERSION = "0.4.0"
4
+ VERSION = "0.4.1"
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: conceptql
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.0
4
+ version: 0.4.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ryan Duryea
@@ -79,6 +79,20 @@ dependencies:
79
79
  - - "~>"
80
80
  - !ruby/object:Gem::Version
81
81
  version: '5.66'
82
+ - !ruby/object:Gem::Dependency
83
+ name: sequel-sqlformat
84
+ requirement: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - "~>"
87
+ - !ruby/object:Gem::Version
88
+ version: '0.1'
89
+ type: :runtime
90
+ prerelease: false
91
+ version_requirements: !ruby/object:Gem::Requirement
92
+ requirements:
93
+ - - "~>"
94
+ - !ruby/object:Gem::Version
95
+ version: '0.1'
82
96
  - !ruby/object:Gem::Dependency
83
97
  name: sequelizer
84
98
  requirement: !ruby/object:Gem::Requirement
@@ -416,8 +430,6 @@ files:
416
430
  - lib/conceptql/rdbms/postgres.rb
417
431
  - lib/conceptql/rdbms/spark.rb
418
432
  - lib/conceptql/scope.rb
419
- - lib/conceptql/sql_formatters.rb
420
- - lib/conceptql/sql_formatters/formatter.rb
421
433
  - lib/conceptql/utils.rb
422
434
  - lib/conceptql/utils_cli.rb
423
435
  - lib/conceptql/version.rb
@@ -1,25 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module ConceptQL
4
- module SqlFormatters
5
- # An external SQL formatter, given as a command array that reads SQL on
6
- # stdin, e.g. Formatter.new(%w[sql-formatter -l postgresql]).
7
- class Formatter
8
- attr_reader :command
9
-
10
- def initialize(command)
11
- @command = command
12
- end
13
-
14
- def available?
15
- system("which", command.first, out: File::NULL, err: File::NULL)
16
- end
17
-
18
- def format(sql)
19
- ConceptQL::Utils.timed_capture(*command, stdin_data: sql, timeout: 10)
20
- rescue Timeout::Error
21
- sql
22
- end
23
- end
24
- end
25
- end
@@ -1,22 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative "sql_formatters/formatter"
4
-
5
- module ConceptQL
6
- module SqlFormatters
7
- SQL_FORMATTER = %w[sql-formatter].freeze
8
- POSTGRES = %w[sql-formatter -l postgresql].freeze
9
- SQLFORMAT = %w[sqlformat --reindent --use_space_around_operators --identifiers lower --keywords upper -].freeze
10
- PG_FORMAT = %w[pg_format].freeze
11
-
12
- # Formats with the rdbms's preferred formatter, else the first of the
13
- # fallbacks that is installed, else returns the SQL untouched.
14
- def self.format(sql, rdbms)
15
- formatter = [ rdbms.preferred_formatter, SQL_FORMATTER, SQLFORMAT, PG_FORMAT ]
16
- .compact
17
- .map { |command| Formatter.new(command) }
18
- .detect(&:available?)
19
- formatter ? formatter.format(sql) : sql
20
- end
21
- end
22
- end