sequel-xtdb 0.2.1 → 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.
- checksums.yaml +4 -4
- data/.envrc +7 -0
- data/README.md +30 -1
- data/lib/sequel/adapters/shared/xtdb.rb +92 -0
- data/lib/sequel/adapters/xtdb.rb +15 -0
- data/lib/sequel/xtdb/version.rb +1 -1
- metadata +3 -2
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA256:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: feef2fdeeefa8b1adfd9d214aab772c02250814aa8e6ef36a79bc7eddc4a8386
         | 
| 4 | 
            +
              data.tar.gz: 417e16888185230ad9f7714b7d0d322594457f6f0d8645c033a9203463103293
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: 28456e08dfc22572d63a5de8dbfba0b8f849a78478f1ec43336e2495212a4217bacf665d53faf7f205d54c75ef8df931064288dd079bf496dd85389bcb3d1911
         | 
| 7 | 
            +
              data.tar.gz: cb4e306b7641e07812e146843d982104e143935c83d58ffc7cd480246f1dec99fc0f5946fa2ebd964eed4c50e338051785fa772119fe497d156cf88e82e2925c
         | 
    
        data/.envrc
    ADDED
    
    
    
        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: | 
| 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 :)  
         | 
| @@ -4,9 +4,101 @@ module Sequel | |
| 4 4 | 
             
                  def database_type
         | 
| 5 5 | 
             
                    :xtdb
         | 
| 6 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
         | 
| 7 41 | 
             
                end
         | 
| 8 42 |  | 
| 9 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
         | 
| 10 102 | 
             
                end
         | 
| 11 103 | 
             
              end
         | 
| 12 104 | 
             
            end
         | 
    
        data/lib/sequel/adapters/xtdb.rb
    CHANGED
    
    | @@ -13,6 +13,15 @@ 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
         | 
| 18 27 |  | 
| @@ -23,6 +32,12 @@ module Sequel | |
| 23 32 |  | 
| 24 33 | 
             
                class Dataset < Sequel::Postgres::Dataset
         | 
| 25 34 | 
             
                  include ::Sequel::XTDB::DatasetMethods
         | 
| 35 | 
            +
             | 
| 36 | 
            +
                  private
         | 
| 37 | 
            +
             | 
| 38 | 
            +
                  def default_timestamp_format
         | 
| 39 | 
            +
                    "'%Y-%m-%d %H:%M:%S'"
         | 
| 40 | 
            +
                  end
         | 
| 26 41 | 
             
                end
         | 
| 27 42 | 
             
              end
         | 
| 28 43 | 
             
            end
         | 
    
        data/lib/sequel/xtdb/version.rb
    CHANGED
    
    
    
        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. | 
| 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- | 
| 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
         |