Class: Sequel::Dataset

Inherits:
Object
  • Object
show all
Defined in:
lib/sequel_opal_runtime_patches.rb,
lib/sequel_opal_async_dataset_patches.rb

Overview


String-buffer overrides: Sequel’s Dataset#sql_string_origin and literal_append allocate plain String instances which Opal treats as immutable — the ‘<<` accumulator pattern raises NotImplementedError. Replace the allocation sites with HomuraSqlBuffer, which implements the Sequel-expected subset of String (from lib/sequel_opal_patches.rb).


Direct Known Subclasses

Sequel::D1::Dataset

Instance Method Summary collapse

Instance Method Details

#__homura_orig_literal_appendObject

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.



63
# File 'lib/sequel_opal_runtime_patches.rb', line 63

alias_method :__homura_orig_literal_append, :literal_append

#_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

#eachObject

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

#literal_append(sql, v) ⇒ Object



64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
# File 'lib/sequel_opal_runtime_patches.rb', line 64

def literal_append(sql, v)
  if 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_valueObject

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_originObject



52
53
54
# File 'lib/sequel_opal_runtime_patches.rb', line 52

def sql_string_origin
  ::HomuraSqlBuffer.new
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