sequel-xtdb 0.1.0 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 588ca986b6f08698e828e9b82ca407efe7ed9cb53bcf88e4bb7d5a3079c543bb
4
- data.tar.gz: 6f40888887ed889acf0bb4fe0b71aae53e566453668dcea3c983fc5fddfdb11c
3
+ metadata.gz: feef2fdeeefa8b1adfd9d214aab772c02250814aa8e6ef36a79bc7eddc4a8386
4
+ data.tar.gz: 417e16888185230ad9f7714b7d0d322594457f6f0d8645c033a9203463103293
5
5
  SHA512:
6
- metadata.gz: de181ba238344b2eb73143653a63ecd67d53a1920f5016f88b505ec4bc0ad9c8f8461e7bc15dc66f19ac53fe01e840db470a8e7128e48fd33d491b93e73210d2
7
- data.tar.gz: a4dab5cb1ca1ee2e760580df3d12efa101e176dcf0bf5c03f0fc7bab6bedef08f557a6175eaffc5080e0c8b7c6b75e01b78d406aef6c9b9bc65c7095f6cb1b65
6
+ metadata.gz: 28456e08dfc22572d63a5de8dbfba0b8f849a78478f1ec43336e2495212a4217bacf665d53faf7f205d54c75ef8df931064288dd079bf496dd85389bcb3d1911
7
+ data.tar.gz: cb4e306b7641e07812e146843d982104e143935c83d58ffc7cd480246f1dec99fc0f5946fa2ebd964eed4c50e338051785fa772119fe497d156cf88e82e2925c
data/.envrc ADDED
@@ -0,0 +1,7 @@
1
+ # env-var using [direnv](https://github.com/direnv/direnv)
2
+ PATH_add bin
3
+
4
+ export XTDB_URL=xtdb://localhost:5432/xtdb
5
+
6
+ # put overrides in .envrc.local
7
+ source_env_if_exists .envrc.local
data/README.md CHANGED
@@ -24,7 +24,7 @@ Shortcut to happiness:
24
24
  $ sequel 'xtdb://localhost:5432/xtdb'
25
25
 
26
26
  # ..or from repl/your project
27
- DB = Sequel.connect("xtdb://localhost:54321/xtdb")
27
+ DB = Sequel.connect("xtdb://localhost:5432/xtdb")
28
28
 
29
29
  # then
30
30
  irb(main)> DB << "insert into products(_id, name, price) values(1, 'Spam', 1000), (2, 'Ham', 1200)"
@@ -32,6 +32,35 @@ irb(main)> DB["select * from products"].all
32
32
  => [{:_id=>2, :name=>"Ham", :price=>1200}, {:_id=>1, :name=>"Spam", :price=>1100}]
33
33
  ```
34
34
 
35
+ ### time-travel
36
+
37
+ _these examples use the [activesupport time helpers](https://api.rubyonrails.org/classes/ActiveSupport/Duration.html)_
38
+
39
+ ```ruby
40
+ DB = Sequel.connect("xtdb://localhost:5432/xtdb")
41
+
42
+ # get a dataset (ie query)
43
+ users = DB[:users]
44
+ past, future = 2.days.ago, 2.days.from_now
45
+ ds1, ds2 = users.as_of(valid: past), users.as_of(valid: future)
46
+
47
+ # expect empty
48
+ ds1.all
49
+ ds1.insert(_id: 1, name: "James")
50
+
51
+ # expect a user
52
+ ds1.as_of(valid: 2.days.ago).all
53
+
54
+ # add to future
55
+ ds2.insert(_id: 2, name: "Jeremy")
56
+
57
+ # expect only James
58
+ users.all
59
+ # expect both James and Jeremy
60
+ ds2.as_of(valid: 2.days.from_now).all
61
+ ```
62
+
63
+
35
64
  ## Status
36
65
 
37
66
  Very early days :)
@@ -40,7 +69,9 @@ Currently it's essentially the postgres-adapter with support for a xtdb-scheme u
40
69
 
41
70
  ## Development
42
71
 
43
- After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
72
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests.
73
+
74
+ You can also run `bin/console [xtdb-url]` for an interactive prompt that will allow you to experiment. The script will pick up on env-var `XTDB_URL`, though the argument takes precedence.
44
75
 
45
76
  To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
46
77
 
@@ -1,9 +1,104 @@
1
1
  module Sequel
2
2
  module XTDB
3
3
  module DatabaseMethods
4
+ def database_type
5
+ :xtdb
6
+ end
7
+
8
+ def primary_key(_table)
9
+ # eg used for RETURNING on insert (prevents crash)
10
+ :_id
11
+ end
12
+
13
+ # Get a dataset with `current`, `valid` and `system` set.
14
+ #
15
+ # For selects this creates the SETTING pre-amble, e.g. 'SETTING DEFAULT VALID_TIME ...':
16
+ # ```
17
+ # DB.as_of(current: 2.weeks.ago).select(Sequel.lit('current_timestamp')).single_value
18
+ # ```
19
+ #
20
+ # A block can be provided as a convenience to stay in SQL-land (selects only):
21
+ # ```
22
+ # DB.as_of(current: 2.hours.ago) do
23
+ # DB["select current_timestamp"]
24
+ # end.sql
25
+ # =>
26
+ # SETTING
27
+ # CURRENT_TIME TO TIMESTAMP '2024-12-17T12:59:48+01:00'
28
+ # select current_timestamp
29
+ # ```
30
+ #
31
+ # When doing inserts, the `_valid_from` will be added (if not provided):
32
+ # ```
33
+ # DB[:products].as_of(valid: 2.weeks.ago).insert(_id: 1, name: 'Spam')
34
+ # ```
35
+ def as_of(...)
36
+ ds = @default_dataset.as_of(...)
37
+ return ds unless block_given?
38
+
39
+ yield.clone(append_sql: ds.select_setting_sql(""))
40
+ end
4
41
  end
5
42
 
6
43
  module DatasetMethods
44
+ Dataset.def_sql_method(self, :select,
45
+ [["if opts[:values]",
46
+ %w[values compounds order limit]],
47
+ ["else",
48
+ %w[setting select distinct columns from join where group having compounds order limit lock]]])
49
+
50
+ def as_of(valid: nil, system: nil, current: nil)
51
+ {valid: valid, system: system, current: current}.reject { |_k, v| v.nil? }.then do |opts|
52
+ clone(opts)
53
+ end
54
+ end
55
+
56
+ def server_version
57
+ 0
58
+ end
59
+
60
+ def insert_values_sql(sql)
61
+ if (from_ix = opts[:columns].index(:_valid_from))
62
+ opts[:values][from_ix] = Sequel.lit("TIMESTAMP ?", opts[:values][from_ix])
63
+ end
64
+
65
+ if (to_ix = opts[:columns].index(:_valid_to))
66
+ opts[:values][to_ix] = Sequel.lit("TIMESTAMP ?", opts[:values][to_ix])
67
+ end
68
+
69
+ super
70
+ end
71
+
72
+ def insert_columns_sql(sql)
73
+ if opts[:valid] && !opts[:columns].index(:_valid_from)
74
+ opts[:columns] << :_valid_from
75
+ opts[:values] << opts[:valid]
76
+ end
77
+ super
78
+ end
79
+
80
+ def select_setting_sql(sql)
81
+ setting = opts.slice(:current, :valid, :system)
82
+ return sql if setting.empty?
83
+
84
+ cast_value = ->(v) do
85
+ case v
86
+ when DateTime, Time
87
+ literal_append "TIMESTAMP ", v.iso8601
88
+ when Date
89
+ literal_append "DATE ", v.iso8601
90
+ end
91
+ end
92
+ sql << "SETTING "
93
+ sql << setting.map do |k, v|
94
+ if k == :current
95
+ literal_append "CURRENT_TIME TO TIMESTAMP ", v.iso8601
96
+ else
97
+ "DEFAULT #{k.upcase}_TIME AS OF #{cast_value[v]}"
98
+ end
99
+ end.join(", ")
100
+ sql << " "
101
+ end
7
102
  end
8
103
  end
9
104
  end
@@ -1,4 +1,4 @@
1
- require_relative 'shared/xtdb'
1
+ require_relative "shared/xtdb"
2
2
  require "sequel/adapters/postgres"
3
3
 
4
4
  module Sequel
@@ -13,12 +13,31 @@ module Sequel
13
13
  def adapter_initialize
14
14
  # XTDB can't handle this SET-command
15
15
  @opts[:force_standard_strings] = false
16
+
17
+ Sequel.database_timezone = :utc
18
+ Sequel.application_timezone = :local
19
+
20
+ if (app_tz = @opts[:application_timezone])
21
+ Sequel.extension(:named_timezones)
22
+ Sequel.application_timezone = app_tz
23
+ end
24
+
16
25
  super
17
26
  end
27
+
28
+ def dataset_class_default
29
+ Dataset
30
+ end
18
31
  end
19
32
 
20
33
  class Dataset < Sequel::Postgres::Dataset
21
34
  include ::Sequel::XTDB::DatasetMethods
35
+
36
+ private
37
+
38
+ def default_timestamp_format
39
+ "'%Y-%m-%d %H:%M:%S'"
40
+ end
22
41
  end
23
42
  end
24
43
  end
@@ -2,6 +2,7 @@
2
2
 
3
3
  module Sequel
4
4
  module XTDB
5
- VERSION = "0.1.0"
5
+ # NOTE when releasing the git-tag will replace the version below
6
+ VERSION = "0.3.0"
6
7
  end
7
8
  end
data/rakelib/gem.rake ADDED
@@ -0,0 +1,23 @@
1
+ namespace :gem do
2
+ task "write_version", [:version] do |_task, args|
3
+ if args[:version]
4
+ version = args[:version].split("=").last
5
+ version_file = File.expand_path("../../lib/sequel/xtdb/version.rb", __FILE__)
6
+
7
+ system(<<~CMD, exception: true)
8
+ ruby -pi -e 'gsub(/VERSION = ".*"/, %{VERSION = "#{version}"})' #{version_file}
9
+ CMD
10
+ Bundler.ui.confirm "Version #{version} written to #{version_file}."
11
+ else
12
+ Bundler.ui.warn "No version provided, keeping version.rb as is."
13
+ end
14
+ end
15
+
16
+ desc "Build [version]"
17
+ task "build", [:version] => ["write_version", "build"] do
18
+ end
19
+
20
+ desc "Build and push [version] to rubygems"
21
+ task "release", [:version] => ["gem:build", "release:rubygem_push"] do
22
+ end
23
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sequel-xtdb
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Gert Goet
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2024-12-13 00:00:00.000000000 Z
11
+ date: 2024-12-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: sequel
@@ -45,6 +45,7 @@ executables: []
45
45
  extensions: []
46
46
  extra_rdoc_files: []
47
47
  files:
48
+ - ".envrc"
48
49
  - ".rspec"
49
50
  - ".standard.yml"
50
51
  - CHANGELOG.md
@@ -55,6 +56,7 @@ files:
55
56
  - lib/sequel/adapters/xtdb.rb
56
57
  - lib/sequel/xtdb.rb
57
58
  - lib/sequel/xtdb/version.rb
59
+ - rakelib/gem.rake
58
60
  - sig/sequel/xtdb.rbs
59
61
  homepage: https://github.com/eval/sequel-xtdb
60
62
  licenses:
@@ -78,7 +80,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
78
80
  - !ruby/object:Gem::Version
79
81
  version: '0'
80
82
  requirements: []
81
- rubygems_version: 3.5.23
83
+ rubygems_version: 3.5.22
82
84
  signing_key:
83
85
  specification_version: 4
84
86
  summary: Adapter to connect to XTDB v2 using Sequel.