Skip to content

Bind go-ruby-redis, go-ruby-pg and go-ruby-sequel into rbgo as native modules#99

Merged
tannevaled merged 6 commits into
mainfrom
bind/batch6
Jul 2, 2026
Merged

Bind go-ruby-redis, go-ruby-pg and go-ruby-sequel into rbgo as native modules#99
tannevaled merged 6 commits into
mainfrom
bind/batch6

Conversation

@tannevaled

Copy link
Copy Markdown
Contributor

Binds three database libraries into rbgo (require "redis" / require "pg" / require "sequel") as native modules, following the proven per-module pattern (<mod>.go + <mod>_bind.go, registered in builtins.go, providedFeatures in require.go, value wrappers wired into object_model.go's classOf).

Ruby API per module

redisRedis.new(connection: io, db:, username:, password:, protocol:) plus the command surface: get/set/setnx/getset/append/incr/decr family, hset/hget/hgetall/hdel/hmget (hashes), lpush/rpush/lpop/lrange (lists), sadd/smembers/sismember (sets), zadd/zscore/zrange/zrank (sorted sets), call (arbitrary command), pipelined { |p| ... } and multi { |m| ... }. Value model: string→String, int64→Integer, float64→Float, bool→true|false, nil→nil, Array→Array, Map→Hash, Set→Set, big number → Integer, CommandError → a raised Redis::CommandError. Error tree Redis::BaseError < StandardError with CommandError / ConnectionError.

pgPG.connect(connection: io, user:, dbname:/database:, password:, ...) drives the StartupMessage + AuthenticationOk/MD5/SCRAM handshake, then conn.exec/query/exec_params/prepare/exec_preparedPG::Result (ntuples/nfields/fields/fname/fnumber/getvalue/getisnull/values/[]→Hash/each/cmd_tuples/cmd_status) with the OID type decoders, plus escape_string/escape_literal/escape_identifier/quote_ident. Error tree PG::Error < StandardError with ConnectionBad / ServerError.

sequelSequel.sqlite(path) / Sequel.connect(adapter:/URL) / Sequel.mock(host:)Sequel::Database; DB[:table]Sequel::Dataset with the chainable builders (where/exclude/select/order/reverse/group/having/distinct/limit/offset/join/inner_join/left_join/right_join) and terminals (sql/select_sql/insert_sql/update_sql/delete_sql/all/first/each/count/insert/update/delete); schema DSL via create_table(:t) { ... } (primary_key, typed columns String/Integer/Bignum/Float/Numeric/Bool/Date/DateTime/Time, column, foreign_key, index). Sequel::Model deferred.

Seams wired to what

  • redis / pg socket seam — rbgo has no native TCPSocket yet, so both take an injected IO-like connection (any object responding to #read/#write, e.g. a duck-typed socket). rubyConn bridges that object to the libraries' io.ReadWriter Conn; pg's PasswordAuthenticator drives MD5/SCRAM over it. Documented in the binding headers. When rbgo grows a native socket it is wired here the same way.
  • sequel executor seam — wired to go-ruby-sqlite3 (already bound as a real, functional DB). sqliteExecutor runs generated SQL through ExecuteHash.

sequel → sqlite3 real execution: yes

DB[:t].all / first / count really run the generated SELECT against a live in-memory SQLite database and return live rows; create_table / insert / update / delete execute their DDL/DML for real, with insert returning the SQLite last_insert_rowid and update/delete the affected-row count.

Gates

  • rbgo builds; full go test ./... green (the one failure, TestChronicParse, is a pre-existing TZ-dependent test that passes under TZ=UTC as CI runs — unrelated to this PR).
  • 100% coverage on all new binding code (redis.go/redis_bind.go/pg.go/pg_bind.go/sequel.go/sequel_bind.go/sequel_schema.go), including socket-seam error paths (via injected fake sockets and canned RESP / PostgreSQL v3 backend byte streams) and executor error paths; genuinely-dead guards were deleted.
  • gofmt + go vet clean.

🤖 Generated with Claude Code

tannevaled and others added 6 commits July 2, 2026 20:28
…utor seam wired to go-ruby-sqlite3 for real execution

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…ocket = injected IO seam; 100% coverage on new binding code

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…ake), socket = injected IO seam; 100% coverage on new binding code

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…ution); 100% coverage on new binding code

Executor seam wired to go-ruby-sqlite3 so DB[:t].all runs against a live SQLite database. Adds classOf cases for the new wrapper types. 100% coverage on all new binding code (redis/pg/sequel), full test suite green, gofmt+vet clean.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@tannevaled tannevaled merged commit c8b272c into main Jul 2, 2026
9 checks passed
@tannevaled tannevaled deleted the bind/batch6 branch July 2, 2026 20:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant