From fd65f86fc4b7231e3783de7b411deec7514b3020 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 19 Aug 2026 19:42:43 +0000 Subject: [PATCH 1/7] Initial plan From 460235c4caa2ac4d6a6cc6273b96e5193436cbd4 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 19 Aug 2026 19:48:22 +0000 Subject: [PATCH 2/7] Fix ASCII-8BIT strings with ASCII-only content binding as BLOB instead of TEXT Co-authored-by: flavorjones <8207+flavorjones@users.noreply.github.com> --- ext/sqlite3/Makefile | 269 ++++++++++++++++++++++++++++++++++++++++ ext/sqlite3/statement.c | 3 +- test/test_statement.rb | 20 +++ 3 files changed, 291 insertions(+), 1 deletion(-) create mode 100644 ext/sqlite3/Makefile diff --git a/ext/sqlite3/Makefile b/ext/sqlite3/Makefile new file mode 100644 index 00000000..4207d2b1 --- /dev/null +++ b/ext/sqlite3/Makefile @@ -0,0 +1,269 @@ + +SHELL = /bin/sh + +# V=0 quiet, V=1 verbose. other values don't work. +V = 0 +V0 = $(V:0=) +Q1 = $(V:1=) +Q = $(Q1:0=@) +ECHO1 = $(V:1=@ :) +ECHO = $(ECHO1:0=@ echo) +NULLCMD = : + +#### Start of system configuration section. #### + +srcdir = . +topdir = /usr/include/ruby-3.2.0 +hdrdir = $(topdir) +arch_hdrdir = /usr/include/x86_64-linux-gnu/ruby-3.2.0 +PATH_SEPARATOR = : +VPATH = $(srcdir):$(arch_hdrdir)/ruby:$(hdrdir)/ruby +prefix = $(DESTDIR)/usr +rubysitearchprefix = $(sitearchlibdir)/$(RUBY_BASE_NAME) +rubyarchprefix = $(archlibdir)/$(RUBY_BASE_NAME) +rubylibprefix = $(libdir)/$(RUBY_BASE_NAME) +exec_prefix = $(prefix) +vendorarchhdrdir = $(sitearchincludedir)/$(RUBY_VERSION_NAME)/vendor_ruby +sitearchhdrdir = $(sitearchincludedir)/$(RUBY_VERSION_NAME)/site_ruby +rubyarchhdrdir = $(archincludedir)/$(RUBY_VERSION_NAME) +vendorhdrdir = $(rubyhdrdir)/vendor_ruby +sitehdrdir = $(rubyhdrdir)/site_ruby +rubyhdrdir = $(includedir)/$(RUBY_VERSION_NAME) +vendorarchdir = $(rubysitearchprefix)/vendor_ruby/$(ruby_version) +vendorlibdir = $(vendordir)/$(ruby_version) +vendordir = $(rubylibprefix)/vendor_ruby +sitearchdir = $(DESTDIR)/usr/local/lib/x86_64-linux-gnu/site_ruby +sitelibdir = $(sitedir)/$(ruby_version) +sitedir = $(DESTDIR)/usr/local/lib/site_ruby +rubyarchdir = $(rubyarchprefix)/$(ruby_version) +rubylibdir = $(rubylibprefix)/$(ruby_version) +sitearchincludedir = $(includedir)/$(sitearch) +archincludedir = $(includedir)/$(arch) +sitearchlibdir = $(libdir)/$(sitearch) +archlibdir = $(libdir)/$(arch) +ridir = $(datarootdir)/$(RI_BASE_NAME) +mandir = $(datarootdir)/man +localedir = $(datarootdir)/locale +libdir = $(exec_prefix)/lib +psdir = $(docdir) +pdfdir = $(docdir) +dvidir = $(docdir) +htmldir = $(docdir) +infodir = $(datarootdir)/info +docdir = $(datarootdir)/doc/$(PACKAGE) +oldincludedir = $(DESTDIR)/usr/include +includedir = $(prefix)/include +runstatedir = $(DESTDIR)/var/run +localstatedir = $(DESTDIR)/var +sharedstatedir = $(prefix)/com +sysconfdir = $(DESTDIR)/etc +datadir = $(datarootdir) +datarootdir = $(prefix)/share +libexecdir = $(exec_prefix)/libexec +sbindir = $(exec_prefix)/sbin +bindir = $(exec_prefix)/bin +archdir = $(rubyarchdir) + + +CC_WRAPPER = +CC = x86_64-linux-gnu-gcc +CXX = x86_64-linux-gnu-g++ +LIBRUBY = $(LIBRUBY_SO) +LIBRUBY_A = lib$(RUBY_SO_NAME)-static.a +LIBRUBYARG_SHARED = -l$(RUBY_SO_NAME) +LIBRUBYARG_STATIC = -l$(RUBY_SO_NAME)-static $(MAINLIBS) +empty = +OUTFLAG = -o $(empty) +COUTFLAG = -o $(empty) +CSRCFLAG = $(empty) + +RUBY_EXTCONF_H = +cflags = $(optflags) $(debugflags) $(warnflags) +cxxflags = +optflags = -O3 -fno-fast-math +debugflags = -ggdb3 +warnflags = -Wall -Wextra -Wdeprecated-declarations -Wdiv-by-zero -Wduplicated-cond -Wimplicit-function-declaration -Wimplicit-int -Wmisleading-indentation -Wpointer-arith -Wwrite-strings -Wold-style-definition -Wimplicit-fallthrough=0 -Wmissing-noreturn -Wno-cast-function-type -Wno-constant-logical-operand -Wno-long-long -Wno-missing-field-initializers -Wno-overlength-strings -Wno-packed-bitfield-compat -Wno-parentheses-equality -Wno-self-assign -Wno-tautological-compare -Wno-unused-parameter -Wno-unused-value -Wsuggest-attribute=format -Wsuggest-attribute=noreturn -Wunused-variable -Wundef +cppflags = +CCDLFLAGS = -fPIC +CFLAGS = $(CCDLFLAGS) -g -O2 -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer -ffile-prefix-map=BUILDDIR=. -fstack-protector-strong -fstack-clash-protection -Wformat -Werror=format-security -fcf-protection -fdebug-prefix-map=BUILDDIR=/usr/src/ruby3.2-3.2.3-1ubuntu0.24.04.8 -fPIC -fvisibility=hidden $(ARCH_FLAG) +INCFLAGS = -I. -I$(arch_hdrdir) -I$(hdrdir)/ruby/backward -I$(hdrdir) -I$(srcdir) +DEFS = +CPPFLAGS = -DHAVE_RB_ENC_INTERNED_STR_CSTR -DHAVE_RB_PROC_ARITY -DHAVE_RB_INTEGER_PACK -DHAVE_SQLITE3_INITIALIZE -DHAVE_SQLITE3_BACKUP_INIT -DHAVE_SQLITE3_COLUMN_DATABASE_NAME -DHAVE_SQLITE3_ENABLE_LOAD_EXTENSION -DHAVE_SQLITE3_LOAD_EXTENSION -DHAVE_SQLITE3_OPEN_V2 -DHAVE_SQLITE3_PREPARE_V2 -DHAVE_SQLITE3_DB_NAME -DHAVE_SQLITE3_ERROR_OFFSET -DHAVE_TYPE_SQLITE3_INT64 -DHAVE_TYPE_SQLITE3_UINT64 -Wdate-time -D_FORTIFY_SOURCE=3 $(DEFS) $(cppflags) +CXXFLAGS = $(CCDLFLAGS) -g -O2 -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer -ffile-prefix-map=BUILDDIR=. -fstack-protector-strong -fstack-clash-protection -Wformat -Werror=format-security -fcf-protection -fdebug-prefix-map=BUILDDIR=/usr/src/ruby3.2-3.2.3-1ubuntu0.24.04.8 $(ARCH_FLAG) +ldflags = -L. -Wl,-Bsymbolic-functions -Wl,-z,relro -Wl,-z,now -fstack-protector-strong -rdynamic -Wl,-export-dynamic -Wl,--no-as-needed +dldflags = -Wl,-Bsymbolic-functions -Wl,-z,relro -Wl,-z,now +ARCH_FLAG = +DLDFLAGS = $(ldflags) $(dldflags) $(ARCH_FLAG) +LDSHARED = $(CC) -shared +LDSHAREDXX = $(CXX) -shared +AR = x86_64-linux-gnu-gcc-ar +EXEEXT = + +RUBY_INSTALL_NAME = $(RUBY_BASE_NAME)3.2 +RUBY_SO_NAME = ruby-3.2 +RUBYW_INSTALL_NAME = +RUBY_VERSION_NAME = $(RUBY_BASE_NAME)-$(ruby_version) +RUBYW_BASE_NAME = rubyw +RUBY_BASE_NAME = ruby + +arch = x86_64-linux-gnu +sitearch = $(arch) +ruby_version = 3.2.0 +ruby = $(bindir)/$(RUBY_BASE_NAME)3.2 +RUBY = $(ruby) +BUILTRUBY = $(bindir)/$(RUBY_BASE_NAME)3.2 +ruby_headers = $(hdrdir)/ruby.h $(hdrdir)/ruby/backward.h $(hdrdir)/ruby/ruby.h $(hdrdir)/ruby/defines.h $(hdrdir)/ruby/missing.h $(hdrdir)/ruby/intern.h $(hdrdir)/ruby/st.h $(hdrdir)/ruby/subst.h $(arch_hdrdir)/ruby/config.h + +RM = rm -f +RM_RF = rm -fr +RMDIRS = rmdir --ignore-fail-on-non-empty -p +MAKEDIRS = /bin/mkdir -p +INSTALL = /usr/bin/install -c +INSTALL_PROG = $(INSTALL) -m 0755 +INSTALL_DATA = $(INSTALL) -m 644 +COPY = cp +TOUCH = exit > + +#### End of system configuration section. #### + +preload = +libpath = . $(archlibdir) +LIBPATH = -L. -L$(archlibdir) +DEFFILE = + +CLEANFILES = mkmf.log +DISTCLEANFILES = +DISTCLEANDIRS = + +extout = +extout_prefix = +target_prefix = /sqlite3 +LOCAL_LIBS = +LIBS = $(LIBRUBYARG_SHARED) -lsqlite3 -lsqlite3 -lm -lpthread -lc +ORIG_SRCS = aggregator.c backup.c database.c exception.c sqlite3.c statement.c +SRCS = $(ORIG_SRCS) +OBJS = aggregator.o backup.o database.o exception.o sqlite3.o statement.o +HDRS = $(srcdir)/aggregator.h $(srcdir)/backup.h $(srcdir)/database.h $(srcdir)/exception.h $(srcdir)/sqlite3_ruby.h $(srcdir)/statement.h $(srcdir)/timespec.h +LOCAL_HDRS = +TARGET = sqlite3_native +TARGET_NAME = sqlite3_native +TARGET_ENTRY = Init_$(TARGET_NAME) +DLLIB = $(TARGET).so +EXTSTATIC = +STATIC_LIB = + +TIMESTAMP_DIR = . +BINDIR = $(bindir) +RUBYCOMMONDIR = $(sitedir)$(target_prefix) +RUBYLIBDIR = $(sitelibdir)$(target_prefix) +RUBYARCHDIR = $(sitearchdir)$(target_prefix) +HDRDIR = $(sitehdrdir)$(target_prefix) +ARCHHDRDIR = $(sitearchhdrdir)$(target_prefix) +TARGET_SO_DIR = +TARGET_SO = $(TARGET_SO_DIR)$(DLLIB) +CLEANLIBS = $(TARGET_SO) false +CLEANOBJS = $(OBJS) *.bak +TARGET_SO_DIR_TIMESTAMP = $(TIMESTAMP_DIR)/.sitearchdir.-.sqlite3.time + +all: $(DLLIB) +static: $(STATIC_LIB) +.PHONY: all install static install-so install-rb +.PHONY: clean clean-so clean-static clean-rb + +clean-static:: +clean-rb-default:: +clean-rb:: +clean-so:: +clean: clean-so clean-static clean-rb-default clean-rb + -$(Q)$(RM_RF) $(CLEANLIBS) $(CLEANOBJS) $(CLEANFILES) .*.time + +distclean-rb-default:: +distclean-rb:: +distclean-so:: +distclean-static:: +distclean: clean distclean-so distclean-static distclean-rb-default distclean-rb + -$(Q)$(RM) Makefile $(RUBY_EXTCONF_H) conftest.* mkmf.log + -$(Q)$(RM) core ruby$(EXEEXT) *~ $(DISTCLEANFILES) + -$(Q)$(RMDIRS) $(DISTCLEANDIRS) 2> /dev/null || true + +realclean: distclean +install: install-so install-rb + +install-so: $(DLLIB) $(TARGET_SO_DIR_TIMESTAMP) + $(INSTALL_PROG) $(DLLIB) $(RUBYARCHDIR) +clean-static:: + -$(Q)$(RM) $(STATIC_LIB) +install-rb: pre-install-rb do-install-rb install-rb-default +install-rb-default: pre-install-rb-default do-install-rb-default +pre-install-rb: Makefile +pre-install-rb-default: Makefile +do-install-rb: +do-install-rb-default: +pre-install-rb-default: + @$(NULLCMD) +$(TARGET_SO_DIR_TIMESTAMP): + $(Q) $(MAKEDIRS) $(@D) $(RUBYARCHDIR) + $(Q) $(TOUCH) $@ + +site-install: site-install-so site-install-rb +site-install-so: install-so +site-install-rb: install-rb + +.SUFFIXES: .c .m .cc .mm .cxx .cpp .o .S + +.cc.o: + $(ECHO) compiling $(<) + $(Q) $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) $(COUTFLAG)$@ -c $(CSRCFLAG)$< + +.cc.S: + $(ECHO) translating $(<) + $(Q) $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) $(COUTFLAG)$@ -S $(CSRCFLAG)$< + +.mm.o: + $(ECHO) compiling $(<) + $(Q) $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) $(COUTFLAG)$@ -c $(CSRCFLAG)$< + +.mm.S: + $(ECHO) translating $(<) + $(Q) $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) $(COUTFLAG)$@ -S $(CSRCFLAG)$< + +.cxx.o: + $(ECHO) compiling $(<) + $(Q) $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) $(COUTFLAG)$@ -c $(CSRCFLAG)$< + +.cxx.S: + $(ECHO) translating $(<) + $(Q) $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) $(COUTFLAG)$@ -S $(CSRCFLAG)$< + +.cpp.o: + $(ECHO) compiling $(<) + $(Q) $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) $(COUTFLAG)$@ -c $(CSRCFLAG)$< + +.cpp.S: + $(ECHO) translating $(<) + $(Q) $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) $(COUTFLAG)$@ -S $(CSRCFLAG)$< + +.c.o: + $(ECHO) compiling $(<) + $(Q) $(CC) $(INCFLAGS) $(CPPFLAGS) $(CFLAGS) $(COUTFLAG)$@ -c $(CSRCFLAG)$< + +.c.S: + $(ECHO) translating $(<) + $(Q) $(CC) $(INCFLAGS) $(CPPFLAGS) $(CFLAGS) $(COUTFLAG)$@ -S $(CSRCFLAG)$< + +.m.o: + $(ECHO) compiling $(<) + $(Q) $(CC) $(INCFLAGS) $(CPPFLAGS) $(CFLAGS) $(COUTFLAG)$@ -c $(CSRCFLAG)$< + +.m.S: + $(ECHO) translating $(<) + $(Q) $(CC) $(INCFLAGS) $(CPPFLAGS) $(CFLAGS) $(COUTFLAG)$@ -S $(CSRCFLAG)$< + +$(TARGET_SO): $(OBJS) Makefile + $(ECHO) linking shared-object sqlite3/$(DLLIB) + -$(Q)$(RM) $(@) + $(Q) $(LDSHARED) -o $@ $(OBJS) $(LIBPATH) $(DLDFLAGS) $(LOCAL_LIBS) $(LIBS) + + + +$(OBJS): $(HDRS) $(ruby_headers) diff --git a/ext/sqlite3/statement.c b/ext/sqlite3/statement.c index 7583f58e..7b2ac9fe 100644 --- a/ext/sqlite3/statement.c +++ b/ext/sqlite3/statement.c @@ -248,7 +248,8 @@ bind_param(VALUE self, VALUE key, VALUE value) switch (TYPE(value)) { case T_STRING: if (CLASS_OF(value) == cSqlite3Blob - || rb_enc_get_index(value) == rb_ascii8bit_encindex() + || (rb_enc_get_index(value) == rb_ascii8bit_encindex() + && !rb_enc_str_asciionly_p(value)) ) { status = sqlite3_bind_blob( ctx->st, diff --git a/test/test_statement.rb b/test/test_statement.rb index b273bc4e..0cec2a70 100644 --- a/test/test_statement.rb +++ b/test/test_statement.rb @@ -203,6 +203,26 @@ def test_bind_blob end end + def test_bind_ascii8bit_with_ascii_chars_binds_as_text + @db.execute("create table foo(text TEXT UNIQUE)") + @db.execute("insert into foo(text) values (?)", "hello") + rows = @db.execute("select * from foo where text = ?", ["hello".encode(Encoding::ASCII_8BIT)]) + assert_equal [["hello"]], rows + end + + def test_bind_ascii8bit_with_non_ascii_chars_binds_as_blob + @db.execute("create table foo(text BLOB)") + binary = "\xFF\xFE".b + stmt = SQLite3::Statement.new(@db, "insert into foo(text) values (?)") + stmt.bind_param(1, binary) + stmt.execute + stmt.close + @db.prepare("select * from foo") do |v| + assert_equal [binary], v.first + assert_equal ["blob"], v.types + end + end + def test_bind_64 stmt = SQLite3::Statement.new(@db, "select ?") stmt.bind_param(1, 2**31) From 4f76c4cbaa094510476bf97bd8031b3296629b27 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 19 Aug 2026 20:23:03 +0000 Subject: [PATCH 3/7] Revert behavior change; document ASCII-8BIT always binds as BLOB Co-authored-by: flavorjones <8207+flavorjones@users.noreply.github.com> --- ext/sqlite3/statement.c | 16 ++++++++++++++-- lib/sqlite3/statement.rb | 15 +++++++++++++++ test/test_statement.rb | 20 -------------------- 3 files changed, 29 insertions(+), 22 deletions(-) diff --git a/ext/sqlite3/statement.c b/ext/sqlite3/statement.c index 7b2ac9fe..496f46ba 100644 --- a/ext/sqlite3/statement.c +++ b/ext/sqlite3/statement.c @@ -216,6 +216,19 @@ step(VALUE self) * Fixnum, it is treated as an index for a positional placeholder. * Otherwise it is used as the name of the placeholder to bind to. * + * Type mapping from Ruby to SQLite3: + * - +nil+ → NULL + * - Integer → INTEGER + * - Float → REAL + * - SQLite3::Blob → BLOB + * - String with Encoding::ASCII_8BIT (a.k.a. BINARY) → BLOB + * - String (all other encodings) → TEXT (re-encoded as UTF-8 if necessary) + * + * Note: if you have a string with only ASCII characters but ASCII-8BIT + * encoding and want it bound as TEXT rather than BLOB, re-encode it first: + * + * stmt.bind_param(1, my_binary_str.encode(Encoding::UTF_8)) + * * See also #bind_params. */ static VALUE @@ -248,8 +261,7 @@ bind_param(VALUE self, VALUE key, VALUE value) switch (TYPE(value)) { case T_STRING: if (CLASS_OF(value) == cSqlite3Blob - || (rb_enc_get_index(value) == rb_ascii8bit_encindex() - && !rb_enc_str_asciionly_p(value)) + || rb_enc_get_index(value) == rb_ascii8bit_encindex() ) { status = sqlite3_bind_blob( ctx->st, diff --git a/lib/sqlite3/statement.rb b/lib/sqlite3/statement.rb index f0f1bcc0..882ae667 100644 --- a/lib/sqlite3/statement.rb +++ b/lib/sqlite3/statement.rb @@ -42,6 +42,21 @@ def initialize(db, sql) # See Database#execute for a description of the valid placeholder # syntaxes. # + # Type mapping from Ruby to SQLite3: + # - +nil+ → NULL + # - Integer → INTEGER + # - Float → REAL + # - SQLite3::Blob → BLOB + # - String with Encoding::BINARY + # (a.k.a. ASCII-8BIT) → BLOB + # - String (all other encodings) → TEXT (re-encoded as UTF-8 if needed) + # + # Note: a String with Encoding::BINARY (ASCII-8BIT) is always bound as a + # BLOB, even when its bytes are all valid ASCII. If you want such a string + # compared or stored as TEXT, re-encode it before binding: + # + # stmt.bind_params(my_binary_str.encode(Encoding::UTF_8)) + # # Example: # # stmt = db.prepare( "select * from table where a=? and b=?" ) diff --git a/test/test_statement.rb b/test/test_statement.rb index 0cec2a70..b273bc4e 100644 --- a/test/test_statement.rb +++ b/test/test_statement.rb @@ -203,26 +203,6 @@ def test_bind_blob end end - def test_bind_ascii8bit_with_ascii_chars_binds_as_text - @db.execute("create table foo(text TEXT UNIQUE)") - @db.execute("insert into foo(text) values (?)", "hello") - rows = @db.execute("select * from foo where text = ?", ["hello".encode(Encoding::ASCII_8BIT)]) - assert_equal [["hello"]], rows - end - - def test_bind_ascii8bit_with_non_ascii_chars_binds_as_blob - @db.execute("create table foo(text BLOB)") - binary = "\xFF\xFE".b - stmt = SQLite3::Statement.new(@db, "insert into foo(text) values (?)") - stmt.bind_param(1, binary) - stmt.execute - stmt.close - @db.prepare("select * from foo") do |v| - assert_equal [binary], v.first - assert_equal ["blob"], v.types - end - end - def test_bind_64 stmt = SQLite3::Statement.new(@db, "select ?") stmt.bind_param(1, 2**31) From 05be20fecb293e09e7c0828239b0090dfd075deb Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 19 Aug 2026 20:29:07 +0000 Subject: [PATCH 4/7] Remove accidentally committed ext/sqlite3/Makefile; add to .gitignore MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Document ASCII-8BIT → BLOB type mapping behavior in bind_param/bind_params Strings with Encoding::BINARY (ASCII-8BIT) are always bound as BLOB. Users who need TEXT comparison should re-encode to UTF-8 first. Co-authored-by: flavorjones <8207+flavorjones@users.noreply.github.com> --- .gitignore | 1 + ext/sqlite3/Makefile | 269 ------------------------------------------- 2 files changed, 1 insertion(+), 269 deletions(-) delete mode 100644 ext/sqlite3/Makefile diff --git a/.gitignore b/.gitignore index 0c7faa30..834a2481 100644 --- a/.gitignore +++ b/.gitignore @@ -15,3 +15,4 @@ pkg/ ports/ tmp/ vendor/ +ext/sqlite3/Makefile diff --git a/ext/sqlite3/Makefile b/ext/sqlite3/Makefile deleted file mode 100644 index 4207d2b1..00000000 --- a/ext/sqlite3/Makefile +++ /dev/null @@ -1,269 +0,0 @@ - -SHELL = /bin/sh - -# V=0 quiet, V=1 verbose. other values don't work. -V = 0 -V0 = $(V:0=) -Q1 = $(V:1=) -Q = $(Q1:0=@) -ECHO1 = $(V:1=@ :) -ECHO = $(ECHO1:0=@ echo) -NULLCMD = : - -#### Start of system configuration section. #### - -srcdir = . -topdir = /usr/include/ruby-3.2.0 -hdrdir = $(topdir) -arch_hdrdir = /usr/include/x86_64-linux-gnu/ruby-3.2.0 -PATH_SEPARATOR = : -VPATH = $(srcdir):$(arch_hdrdir)/ruby:$(hdrdir)/ruby -prefix = $(DESTDIR)/usr -rubysitearchprefix = $(sitearchlibdir)/$(RUBY_BASE_NAME) -rubyarchprefix = $(archlibdir)/$(RUBY_BASE_NAME) -rubylibprefix = $(libdir)/$(RUBY_BASE_NAME) -exec_prefix = $(prefix) -vendorarchhdrdir = $(sitearchincludedir)/$(RUBY_VERSION_NAME)/vendor_ruby -sitearchhdrdir = $(sitearchincludedir)/$(RUBY_VERSION_NAME)/site_ruby -rubyarchhdrdir = $(archincludedir)/$(RUBY_VERSION_NAME) -vendorhdrdir = $(rubyhdrdir)/vendor_ruby -sitehdrdir = $(rubyhdrdir)/site_ruby -rubyhdrdir = $(includedir)/$(RUBY_VERSION_NAME) -vendorarchdir = $(rubysitearchprefix)/vendor_ruby/$(ruby_version) -vendorlibdir = $(vendordir)/$(ruby_version) -vendordir = $(rubylibprefix)/vendor_ruby -sitearchdir = $(DESTDIR)/usr/local/lib/x86_64-linux-gnu/site_ruby -sitelibdir = $(sitedir)/$(ruby_version) -sitedir = $(DESTDIR)/usr/local/lib/site_ruby -rubyarchdir = $(rubyarchprefix)/$(ruby_version) -rubylibdir = $(rubylibprefix)/$(ruby_version) -sitearchincludedir = $(includedir)/$(sitearch) -archincludedir = $(includedir)/$(arch) -sitearchlibdir = $(libdir)/$(sitearch) -archlibdir = $(libdir)/$(arch) -ridir = $(datarootdir)/$(RI_BASE_NAME) -mandir = $(datarootdir)/man -localedir = $(datarootdir)/locale -libdir = $(exec_prefix)/lib -psdir = $(docdir) -pdfdir = $(docdir) -dvidir = $(docdir) -htmldir = $(docdir) -infodir = $(datarootdir)/info -docdir = $(datarootdir)/doc/$(PACKAGE) -oldincludedir = $(DESTDIR)/usr/include -includedir = $(prefix)/include -runstatedir = $(DESTDIR)/var/run -localstatedir = $(DESTDIR)/var -sharedstatedir = $(prefix)/com -sysconfdir = $(DESTDIR)/etc -datadir = $(datarootdir) -datarootdir = $(prefix)/share -libexecdir = $(exec_prefix)/libexec -sbindir = $(exec_prefix)/sbin -bindir = $(exec_prefix)/bin -archdir = $(rubyarchdir) - - -CC_WRAPPER = -CC = x86_64-linux-gnu-gcc -CXX = x86_64-linux-gnu-g++ -LIBRUBY = $(LIBRUBY_SO) -LIBRUBY_A = lib$(RUBY_SO_NAME)-static.a -LIBRUBYARG_SHARED = -l$(RUBY_SO_NAME) -LIBRUBYARG_STATIC = -l$(RUBY_SO_NAME)-static $(MAINLIBS) -empty = -OUTFLAG = -o $(empty) -COUTFLAG = -o $(empty) -CSRCFLAG = $(empty) - -RUBY_EXTCONF_H = -cflags = $(optflags) $(debugflags) $(warnflags) -cxxflags = -optflags = -O3 -fno-fast-math -debugflags = -ggdb3 -warnflags = -Wall -Wextra -Wdeprecated-declarations -Wdiv-by-zero -Wduplicated-cond -Wimplicit-function-declaration -Wimplicit-int -Wmisleading-indentation -Wpointer-arith -Wwrite-strings -Wold-style-definition -Wimplicit-fallthrough=0 -Wmissing-noreturn -Wno-cast-function-type -Wno-constant-logical-operand -Wno-long-long -Wno-missing-field-initializers -Wno-overlength-strings -Wno-packed-bitfield-compat -Wno-parentheses-equality -Wno-self-assign -Wno-tautological-compare -Wno-unused-parameter -Wno-unused-value -Wsuggest-attribute=format -Wsuggest-attribute=noreturn -Wunused-variable -Wundef -cppflags = -CCDLFLAGS = -fPIC -CFLAGS = $(CCDLFLAGS) -g -O2 -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer -ffile-prefix-map=BUILDDIR=. -fstack-protector-strong -fstack-clash-protection -Wformat -Werror=format-security -fcf-protection -fdebug-prefix-map=BUILDDIR=/usr/src/ruby3.2-3.2.3-1ubuntu0.24.04.8 -fPIC -fvisibility=hidden $(ARCH_FLAG) -INCFLAGS = -I. -I$(arch_hdrdir) -I$(hdrdir)/ruby/backward -I$(hdrdir) -I$(srcdir) -DEFS = -CPPFLAGS = -DHAVE_RB_ENC_INTERNED_STR_CSTR -DHAVE_RB_PROC_ARITY -DHAVE_RB_INTEGER_PACK -DHAVE_SQLITE3_INITIALIZE -DHAVE_SQLITE3_BACKUP_INIT -DHAVE_SQLITE3_COLUMN_DATABASE_NAME -DHAVE_SQLITE3_ENABLE_LOAD_EXTENSION -DHAVE_SQLITE3_LOAD_EXTENSION -DHAVE_SQLITE3_OPEN_V2 -DHAVE_SQLITE3_PREPARE_V2 -DHAVE_SQLITE3_DB_NAME -DHAVE_SQLITE3_ERROR_OFFSET -DHAVE_TYPE_SQLITE3_INT64 -DHAVE_TYPE_SQLITE3_UINT64 -Wdate-time -D_FORTIFY_SOURCE=3 $(DEFS) $(cppflags) -CXXFLAGS = $(CCDLFLAGS) -g -O2 -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer -ffile-prefix-map=BUILDDIR=. -fstack-protector-strong -fstack-clash-protection -Wformat -Werror=format-security -fcf-protection -fdebug-prefix-map=BUILDDIR=/usr/src/ruby3.2-3.2.3-1ubuntu0.24.04.8 $(ARCH_FLAG) -ldflags = -L. -Wl,-Bsymbolic-functions -Wl,-z,relro -Wl,-z,now -fstack-protector-strong -rdynamic -Wl,-export-dynamic -Wl,--no-as-needed -dldflags = -Wl,-Bsymbolic-functions -Wl,-z,relro -Wl,-z,now -ARCH_FLAG = -DLDFLAGS = $(ldflags) $(dldflags) $(ARCH_FLAG) -LDSHARED = $(CC) -shared -LDSHAREDXX = $(CXX) -shared -AR = x86_64-linux-gnu-gcc-ar -EXEEXT = - -RUBY_INSTALL_NAME = $(RUBY_BASE_NAME)3.2 -RUBY_SO_NAME = ruby-3.2 -RUBYW_INSTALL_NAME = -RUBY_VERSION_NAME = $(RUBY_BASE_NAME)-$(ruby_version) -RUBYW_BASE_NAME = rubyw -RUBY_BASE_NAME = ruby - -arch = x86_64-linux-gnu -sitearch = $(arch) -ruby_version = 3.2.0 -ruby = $(bindir)/$(RUBY_BASE_NAME)3.2 -RUBY = $(ruby) -BUILTRUBY = $(bindir)/$(RUBY_BASE_NAME)3.2 -ruby_headers = $(hdrdir)/ruby.h $(hdrdir)/ruby/backward.h $(hdrdir)/ruby/ruby.h $(hdrdir)/ruby/defines.h $(hdrdir)/ruby/missing.h $(hdrdir)/ruby/intern.h $(hdrdir)/ruby/st.h $(hdrdir)/ruby/subst.h $(arch_hdrdir)/ruby/config.h - -RM = rm -f -RM_RF = rm -fr -RMDIRS = rmdir --ignore-fail-on-non-empty -p -MAKEDIRS = /bin/mkdir -p -INSTALL = /usr/bin/install -c -INSTALL_PROG = $(INSTALL) -m 0755 -INSTALL_DATA = $(INSTALL) -m 644 -COPY = cp -TOUCH = exit > - -#### End of system configuration section. #### - -preload = -libpath = . $(archlibdir) -LIBPATH = -L. -L$(archlibdir) -DEFFILE = - -CLEANFILES = mkmf.log -DISTCLEANFILES = -DISTCLEANDIRS = - -extout = -extout_prefix = -target_prefix = /sqlite3 -LOCAL_LIBS = -LIBS = $(LIBRUBYARG_SHARED) -lsqlite3 -lsqlite3 -lm -lpthread -lc -ORIG_SRCS = aggregator.c backup.c database.c exception.c sqlite3.c statement.c -SRCS = $(ORIG_SRCS) -OBJS = aggregator.o backup.o database.o exception.o sqlite3.o statement.o -HDRS = $(srcdir)/aggregator.h $(srcdir)/backup.h $(srcdir)/database.h $(srcdir)/exception.h $(srcdir)/sqlite3_ruby.h $(srcdir)/statement.h $(srcdir)/timespec.h -LOCAL_HDRS = -TARGET = sqlite3_native -TARGET_NAME = sqlite3_native -TARGET_ENTRY = Init_$(TARGET_NAME) -DLLIB = $(TARGET).so -EXTSTATIC = -STATIC_LIB = - -TIMESTAMP_DIR = . -BINDIR = $(bindir) -RUBYCOMMONDIR = $(sitedir)$(target_prefix) -RUBYLIBDIR = $(sitelibdir)$(target_prefix) -RUBYARCHDIR = $(sitearchdir)$(target_prefix) -HDRDIR = $(sitehdrdir)$(target_prefix) -ARCHHDRDIR = $(sitearchhdrdir)$(target_prefix) -TARGET_SO_DIR = -TARGET_SO = $(TARGET_SO_DIR)$(DLLIB) -CLEANLIBS = $(TARGET_SO) false -CLEANOBJS = $(OBJS) *.bak -TARGET_SO_DIR_TIMESTAMP = $(TIMESTAMP_DIR)/.sitearchdir.-.sqlite3.time - -all: $(DLLIB) -static: $(STATIC_LIB) -.PHONY: all install static install-so install-rb -.PHONY: clean clean-so clean-static clean-rb - -clean-static:: -clean-rb-default:: -clean-rb:: -clean-so:: -clean: clean-so clean-static clean-rb-default clean-rb - -$(Q)$(RM_RF) $(CLEANLIBS) $(CLEANOBJS) $(CLEANFILES) .*.time - -distclean-rb-default:: -distclean-rb:: -distclean-so:: -distclean-static:: -distclean: clean distclean-so distclean-static distclean-rb-default distclean-rb - -$(Q)$(RM) Makefile $(RUBY_EXTCONF_H) conftest.* mkmf.log - -$(Q)$(RM) core ruby$(EXEEXT) *~ $(DISTCLEANFILES) - -$(Q)$(RMDIRS) $(DISTCLEANDIRS) 2> /dev/null || true - -realclean: distclean -install: install-so install-rb - -install-so: $(DLLIB) $(TARGET_SO_DIR_TIMESTAMP) - $(INSTALL_PROG) $(DLLIB) $(RUBYARCHDIR) -clean-static:: - -$(Q)$(RM) $(STATIC_LIB) -install-rb: pre-install-rb do-install-rb install-rb-default -install-rb-default: pre-install-rb-default do-install-rb-default -pre-install-rb: Makefile -pre-install-rb-default: Makefile -do-install-rb: -do-install-rb-default: -pre-install-rb-default: - @$(NULLCMD) -$(TARGET_SO_DIR_TIMESTAMP): - $(Q) $(MAKEDIRS) $(@D) $(RUBYARCHDIR) - $(Q) $(TOUCH) $@ - -site-install: site-install-so site-install-rb -site-install-so: install-so -site-install-rb: install-rb - -.SUFFIXES: .c .m .cc .mm .cxx .cpp .o .S - -.cc.o: - $(ECHO) compiling $(<) - $(Q) $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) $(COUTFLAG)$@ -c $(CSRCFLAG)$< - -.cc.S: - $(ECHO) translating $(<) - $(Q) $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) $(COUTFLAG)$@ -S $(CSRCFLAG)$< - -.mm.o: - $(ECHO) compiling $(<) - $(Q) $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) $(COUTFLAG)$@ -c $(CSRCFLAG)$< - -.mm.S: - $(ECHO) translating $(<) - $(Q) $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) $(COUTFLAG)$@ -S $(CSRCFLAG)$< - -.cxx.o: - $(ECHO) compiling $(<) - $(Q) $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) $(COUTFLAG)$@ -c $(CSRCFLAG)$< - -.cxx.S: - $(ECHO) translating $(<) - $(Q) $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) $(COUTFLAG)$@ -S $(CSRCFLAG)$< - -.cpp.o: - $(ECHO) compiling $(<) - $(Q) $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) $(COUTFLAG)$@ -c $(CSRCFLAG)$< - -.cpp.S: - $(ECHO) translating $(<) - $(Q) $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) $(COUTFLAG)$@ -S $(CSRCFLAG)$< - -.c.o: - $(ECHO) compiling $(<) - $(Q) $(CC) $(INCFLAGS) $(CPPFLAGS) $(CFLAGS) $(COUTFLAG)$@ -c $(CSRCFLAG)$< - -.c.S: - $(ECHO) translating $(<) - $(Q) $(CC) $(INCFLAGS) $(CPPFLAGS) $(CFLAGS) $(COUTFLAG)$@ -S $(CSRCFLAG)$< - -.m.o: - $(ECHO) compiling $(<) - $(Q) $(CC) $(INCFLAGS) $(CPPFLAGS) $(CFLAGS) $(COUTFLAG)$@ -c $(CSRCFLAG)$< - -.m.S: - $(ECHO) translating $(<) - $(Q) $(CC) $(INCFLAGS) $(CPPFLAGS) $(CFLAGS) $(COUTFLAG)$@ -S $(CSRCFLAG)$< - -$(TARGET_SO): $(OBJS) Makefile - $(ECHO) linking shared-object sqlite3/$(DLLIB) - -$(Q)$(RM) $(@) - $(Q) $(LDSHARED) -o $@ $(OBJS) $(LIBPATH) $(DLDFLAGS) $(LOCAL_LIBS) $(LIBS) - - - -$(OBJS): $(HDRS) $(ruby_headers) From a0973a03f5cd37ec98fdb2d69eeb5e0103d8fcbf Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 19 Aug 2026 20:42:35 +0000 Subject: [PATCH 5/7] Fix three doc errors in bind_param/bind_params type-mapping table - Integer: note REAL fallback for values outside signed int64 range - String: UTF-16LE/BE binds as UTF-16 TEXT, not re-encoded to UTF-8 - Any other type: raises RuntimeError Co-authored-by: flavorjones <8207+flavorjones@users.noreply.github.com> --- ext/sqlite3/statement.c | 6 ++++-- lib/sqlite3/statement.rb | 7 +++++-- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/ext/sqlite3/statement.c b/ext/sqlite3/statement.c index 496f46ba..aac10f1b 100644 --- a/ext/sqlite3/statement.c +++ b/ext/sqlite3/statement.c @@ -218,11 +218,13 @@ step(VALUE self) * * Type mapping from Ruby to SQLite3: * - +nil+ → NULL - * - Integer → INTEGER + * - Integer → INTEGER (or REAL when outside the signed int64 range) * - Float → REAL * - SQLite3::Blob → BLOB * - String with Encoding::ASCII_8BIT (a.k.a. BINARY) → BLOB - * - String (all other encodings) → TEXT (re-encoded as UTF-8 if necessary) + * - String with Encoding::UTF_16LE or Encoding::UTF_16BE → TEXT (bound as UTF-16) + * - String (all other encodings) → TEXT (re-encoded to UTF-8 if necessary) + * - Any other type → raises RuntimeError * * Note: if you have a string with only ASCII characters but ASCII-8BIT * encoding and want it bound as TEXT rather than BLOB, re-encode it first: diff --git a/lib/sqlite3/statement.rb b/lib/sqlite3/statement.rb index 882ae667..9129603d 100644 --- a/lib/sqlite3/statement.rb +++ b/lib/sqlite3/statement.rb @@ -44,12 +44,15 @@ def initialize(db, sql) # # Type mapping from Ruby to SQLite3: # - +nil+ → NULL - # - Integer → INTEGER + # - Integer → INTEGER (or REAL when outside the signed int64 range) # - Float → REAL # - SQLite3::Blob → BLOB # - String with Encoding::BINARY # (a.k.a. ASCII-8BIT) → BLOB - # - String (all other encodings) → TEXT (re-encoded as UTF-8 if needed) + # - String with Encoding::UTF_16LE + # or Encoding::UTF_16BE → TEXT (bound as UTF-16) + # - String (all other encodings) → TEXT (re-encoded to UTF-8 if needed) + # - Any other type → raises RuntimeError # # Note: a String with Encoding::BINARY (ASCII-8BIT) is always bound as a # BLOB, even when its bytes are all valid ASCII. If you want such a string From 9c98266279182e1344c62f1c97ea428b4a7dce85 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 19 Aug 2026 20:45:22 +0000 Subject: [PATCH 6/7] Normalize encoding name to ASCII_8BIT (a.k.a. BINARY) in both doc blocks Co-authored-by: flavorjones <8207+flavorjones@users.noreply.github.com> --- lib/sqlite3/statement.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/sqlite3/statement.rb b/lib/sqlite3/statement.rb index 9129603d..d322fa65 100644 --- a/lib/sqlite3/statement.rb +++ b/lib/sqlite3/statement.rb @@ -47,14 +47,14 @@ def initialize(db, sql) # - Integer → INTEGER (or REAL when outside the signed int64 range) # - Float → REAL # - SQLite3::Blob → BLOB - # - String with Encoding::BINARY - # (a.k.a. ASCII-8BIT) → BLOB + # - String with Encoding::ASCII_8BIT + # (a.k.a. BINARY) → BLOB # - String with Encoding::UTF_16LE # or Encoding::UTF_16BE → TEXT (bound as UTF-16) # - String (all other encodings) → TEXT (re-encoded to UTF-8 if needed) # - Any other type → raises RuntimeError # - # Note: a String with Encoding::BINARY (ASCII-8BIT) is always bound as a + # Note: a String with Encoding::ASCII_8BIT (BINARY) is always bound as a # BLOB, even when its bytes are all valid ASCII. If you want such a string # compared or stored as TEXT, re-encode it before binding: # From dd62a141a17ed2db5104e605790437f2aa803d07 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 19 Aug 2026 20:47:16 +0000 Subject: [PATCH 7/7] Remove ext/sqlite3/Makefile from .gitignore (out of scope) Co-authored-by: flavorjones <8207+flavorjones@users.noreply.github.com> --- .gitignore | 1 - 1 file changed, 1 deletion(-) diff --git a/.gitignore b/.gitignore index 834a2481..0c7faa30 100644 --- a/.gitignore +++ b/.gitignore @@ -15,4 +15,3 @@ pkg/ ports/ tmp/ vendor/ -ext/sqlite3/Makefile