Class: Sequel::Dataset
- Inherits:
-
Object
- Object
- Sequel::Dataset
- Defined in:
- lib/sequel_opal_runtime_patches.rb,
lib/sequel_opal_async_dataset_patches.rb
Direct Known Subclasses
Instance Method Summary collapse
- #__homura_orig__insert_values_sql ⇒ Object
-
#__homura_orig_literal_append ⇒ Object
upstream literal_append Symbol branch: l = String.new literal_symbol_append(l, v) db.literal_symbol_set(v, l) homura: use Buffer for the append accumulator; cache the rendered String form on the db so subsequent calls hit the cache without re-creating a Buffer.
- #__homura_orig_update_sql_values_hash ⇒ Object
-
#_all(block) ⇒ Object
upstream: a = []; yield a; post_load(a); a.each(&block) if block; a homura: yield(a) returns a Promise when the caller block crosses the D1 adapter’s async boundary (Dataset#all’s block is async-compiled).
- #_insert_values_sql(sql, values) ⇒ Object
-
#each ⇒ Object
upstream each: if rp = row_proc; fetch_rows(select_sql){|r| yield rp.call®} else fetch_rows(select_sql){|r| yield r} end; self homura: fetch_rows is async (D1 adapter awaits the Promise chain).
-
#get_first_row(*conds, &block) ⇒ Object
Sqlite3-ruby / homura-runtime D1Database compatibility shim.
- #literal_append(sql, v) ⇒ Object
-
#single_value ⇒ Object
upstream: single_value_ds.each{|r| r.each{|_, v| return v}}; nil homura: capture first value using sentinel flag.
- #sql_string_origin ⇒ Object
- #update_sql_values_hash(sql, values) ⇒ Object
-
#with_sql_each(sql) ⇒ Object
upstream: with_sql_each(sql){|r| yield r}; self (sync, but fetch_rows returns a Promise under the D1 adapter, so the block body doesn’t run before the caller’s sync flow resumes — the Promise is dropped).
-
#with_sql_first(sql) ⇒ Object
upstream: with_sql_each(sql){|r| return r}; nil homura: capture first row without ‘return`; callers always clone with limit(1) so the no-break form is equivalent.
-
#with_sql_single_value(sql) ⇒ Object
upstream: if r = with_sql_first(sql); r.each{|_, v| return v}; end homura: same capture-first-value pattern via sentinel.
Instance Method Details
#__homura_orig__insert_values_sql ⇒ Object
133 |
# File 'lib/sequel_opal_runtime_patches.rb', line 133 alias_method :__homura_orig__insert_values_sql, :_insert_values_sql |
#__homura_orig_literal_append ⇒ Object
upstream literal_append Symbol branch:
l = String.new
literal_symbol_append(l, v)
db.literal_symbol_set(v, l)
homura: use Buffer for the append accumulator; cache the rendered String form on the db so subsequent calls hit the cache without re-creating a Buffer.
88 |
# File 'lib/sequel_opal_runtime_patches.rb', line 88 alias_method :__homura_orig_literal_append, :literal_append |
#__homura_orig_update_sql_values_hash ⇒ Object
127 |
# File 'lib/sequel_opal_runtime_patches.rb', line 127 alias_method :__homura_orig_update_sql_values_hash, :update_sql_values_hash |
#_all(block) ⇒ Object
upstream: a = []; yield a; post_load(a); a.each(&block) if block; a homura: yield(a) returns a Promise when the caller block crosses the D1 adapter’s async boundary (Dataset#all’s block is async-compiled). Await so ‘a` is populated before post_load.
51 52 53 54 55 56 57 |
# File 'lib/sequel_opal_async_dataset_patches.rb', line 51 def _all(block) a = [] yield(a).__await__ post_load(a) a.each(&block) if block a end |
#_insert_values_sql(sql, values) ⇒ Object
134 135 136 137 138 139 |
# File 'lib/sequel_opal_runtime_patches.rb', line 134 def _insert_values_sql(sql, values) if values.is_a?(Array) values = values.map { |v| homura_sql_value(v) } end __homura_orig__insert_values_sql(sql, values) end |
#each ⇒ Object
upstream each:
if rp = row_proc; fetch_rows(select_sql){|r| yield rp.call(r)}
else fetch_rows(select_sql){|r| yield r}
end; self
homura: fetch_rows is async (D1 adapter awaits the Promise chain). If we leave each sync, the block passed to fetch_rows never runs before each returns. Await fetch_rows to let the inner block fire first.
38 39 40 41 42 43 44 45 |
# File 'lib/sequel_opal_async_dataset_patches.rb', line 38 def each if rp = row_proc fetch_rows(select_sql){|r| yield rp.call(r)}.__await__ else fetch_rows(select_sql){|r| yield r}.__await__ end self end |
#get_first_row(*conds, &block) ⇒ Object
Sqlite3-ruby / homura-runtime D1Database compatibility shim. Mirrors the ‘db.get_first_row(sql, [params])` shape exposed by `Cloudflare::D1Database` so code that mixes the two layers (or follows that documentation style) works on `Sequel::Dataset` too.
db[:users].where(id: 1).get_first_row # → Hash or nil
db[:users].get_first_row('id = ?', 1) # accepts the same
# params as #where.
Implemented as a thin wrapper over ‘Dataset#first`, which already crosses the async boundary correctly via the patches in this file.
132 133 134 |
# File 'lib/sequel_opal_async_dataset_patches.rb', line 132 def get_first_row(*conds, &block) conds.empty? && block.nil? ? first : first(*conds, &block) end |
#literal_append(sql, v) ⇒ Object
89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 |
# File 'lib/sequel_opal_runtime_patches.rb', line 89 def literal_append(sql, v) # IMPORTANT: in Opal, `Symbol` is the same constant as `String` # (`Symbol = String`), so `String#<` subclasses such as # `Sequel::LiteralString` and `Sequel::SQL::Blob` ALSO satisfy # `is_a?(Symbol)`. Upstream Sequel's `case v when Symbol` therefore # captures these subclasses and routes them through # `literal_symbol_append`, which interprets the value as a column # identifier (`Sequel.lit('1 - done')` becomes `` `1 - done` ``). # This was the root cause of homura issue #31: # # db[:todos].where(id: 1).update(done: Sequel.lit('1 - done')) # # SQLite error: no such column: 1 - done # # We branch on the Sequel SQL types FIRST, before Symbol, so they # take the literal path that upstream Ruby would hit naturally # (where `Symbol` and `String` are distinct classes). if v.is_a?(::HomuraSqlStringLiteral) v.sql_literal_append(self, sql) elsif v.is_a?(::Sequel::LiteralString) literal_literal_string_append(sql, v) elsif defined?(::Sequel::SQL::Blob) && v.is_a?(::Sequel::SQL::Blob) literal_blob_append(sql, v) elsif v.is_a?(Symbol) if skip_symbol_cache? literal_symbol_append(sql, v) else unless l = db.literal_symbol(v) l = sql_string_origin literal_symbol_append(l, v) db.literal_symbol_set(v, l.to_s) end sql << l end else __homura_orig_literal_append(sql, v) end end |
#single_value ⇒ Object
upstream: single_value_ds.each{|r| r.each{|_, v| return v}}; nil homura: capture first value using sentinel flag. Relies on each awaiting the D1 Promise chain.
91 92 93 94 95 96 97 98 99 100 101 102 103 104 |
# File 'lib/sequel_opal_async_dataset_patches.rb', line 91 def single_value value = nil found = false # each is async (patched in this file); must await. (single_value_ds.each do |r| next if found r.each do |_, v| next if found value = v found = true end end).__await__ found ? value : nil end |
#sql_string_origin ⇒ Object
66 67 68 |
# File 'lib/sequel_opal_runtime_patches.rb', line 66 def sql_string_origin ::HomuraSqlBuffer.new end |
#update_sql_values_hash(sql, values) ⇒ Object
128 129 130 131 |
# File 'lib/sequel_opal_runtime_patches.rb', line 128 def update_sql_values_hash(sql, values) values = values.each_with_object({}) { |(k, v), acc| acc[k] = homura_sql_value(v) } __homura_orig_update_sql_values_hash(sql, values) end |
#with_sql_each(sql) ⇒ Object
upstream: with_sql_each(sql){|r| yield r}; self (sync, but fetch_rows returns a Promise under the D1 adapter, so the block body doesn’t run before the caller’s sync flow resumes — the Promise is dropped). homura: reopen with ‘.__await__` so the async fetch_rows resolves before this method returns. Required for #first / #with_sql_first / #with_sql_single_value which expect the block to have fired.
65 66 67 68 69 70 71 72 |
# File 'lib/sequel_opal_async_dataset_patches.rb', line 65 def with_sql_each(sql) if rp = row_proc _with_sql_dataset.fetch_rows(sql){|r| yield rp.call(r)}.__await__ else _with_sql_dataset.fetch_rows(sql){|r| yield r}.__await__ end self end |
#with_sql_first(sql) ⇒ Object
upstream: with_sql_each(sql){|r| return r}; nil homura: capture first row without ‘return`; callers always clone with limit(1) so the no-break form is equivalent. Needs with_sql_each to actually await its fetch_rows (see above).
78 79 80 81 82 83 84 85 86 |
# File 'lib/sequel_opal_async_dataset_patches.rb', line 78 def with_sql_first(sql) result = nil # with_sql_each is async now (awaits fetch_rows internally); we must # await here so `result` is populated before returning. (with_sql_each(sql) do |r| result = r if result.nil? end).__await__ result end |
#with_sql_single_value(sql) ⇒ Object
upstream: if r = with_sql_first(sql); r.each{|_, v| return v}; end homura: same capture-first-value pattern via sentinel.
108 109 110 111 112 113 114 115 116 117 118 119 |
# File 'lib/sequel_opal_async_dataset_patches.rb', line 108 def with_sql_single_value(sql) if r = with_sql_first(sql) value = nil captured = false r.each do |_, v| next if captured value = v captured = true end value end end |