Add SQLite support
- UUID support - Schema compatibility layer, ignore MySQL specific options - Search not working yet
This commit is contained in:
@@ -31,6 +31,9 @@
|
|||||||
!/tmp/storage/.keep
|
!/tmp/storage/.keep
|
||||||
/data
|
/data
|
||||||
|
|
||||||
|
*.sqlite3
|
||||||
|
*.sqlite3_*
|
||||||
|
|
||||||
/public/assets
|
/public/assets
|
||||||
|
|
||||||
# Ignore master key for decrypting credentials and more.
|
# Ignore master key for decrypting credentials and more.
|
||||||
|
|||||||
@@ -1,7 +1,12 @@
|
|||||||
class ApplicationRecord < ActiveRecord::Base
|
class ApplicationRecord < ActiveRecord::Base
|
||||||
primary_abstract_class
|
primary_abstract_class
|
||||||
|
|
||||||
connects_to database: { writing: :primary, reading: :replica }
|
# SQLite doesn't use separate replica databases
|
||||||
|
if ENV.fetch("DATABASE_ADAPTER", "mysql") == "sqlite"
|
||||||
|
connects_to database: { writing: :primary, reading: :primary }
|
||||||
|
else
|
||||||
|
connects_to database: { writing: :primary, reading: :replica }
|
||||||
|
end
|
||||||
|
|
||||||
attribute :id, :uuid, default: -> { ActiveRecord::Type::Uuid.generate }
|
attribute :id, :uuid, default: -> { ActiveRecord::Type::Uuid.generate }
|
||||||
end
|
end
|
||||||
|
|||||||
+25
-4
@@ -1,4 +1,7 @@
|
|||||||
<%
|
<%
|
||||||
|
database_adapter = ENV.fetch("DATABASE_ADAPTER", "mysql")
|
||||||
|
use_sqlite = database_adapter == "sqlite"
|
||||||
|
|
||||||
if ENV["MIGRATE"].present?
|
if ENV["MIGRATE"].present?
|
||||||
mysql_app_user_key = "MYSQL_ALTER_USER"
|
mysql_app_user_key = "MYSQL_ALTER_USER"
|
||||||
mysql_app_password_key = "MYSQL_ALTER_PASSWORD"
|
mysql_app_password_key = "MYSQL_ALTER_PASSWORD"
|
||||||
@@ -12,13 +15,24 @@
|
|||||||
%>
|
%>
|
||||||
|
|
||||||
default: &default
|
default: &default
|
||||||
|
<% if use_sqlite %>
|
||||||
|
adapter: sqlite3
|
||||||
|
pool: 50
|
||||||
|
timeout: 5000
|
||||||
|
<% else %>
|
||||||
adapter: trilogy
|
adapter: trilogy
|
||||||
host: <%= ENV.fetch "FIZZY_DB_HOST", "127.0.0.1" %>
|
host: <%= ENV.fetch "FIZZY_DB_HOST", "127.0.0.1" %>
|
||||||
port: <%= ENV.fetch "FIZZY_DB_PORT", 3306 %>
|
port: <%= ENV.fetch "FIZZY_DB_PORT", 3306 %>
|
||||||
pool: 50
|
pool: 50
|
||||||
timeout: 5000
|
timeout: 5000
|
||||||
|
<% end %>
|
||||||
|
|
||||||
development:
|
development:
|
||||||
|
<% if use_sqlite %>
|
||||||
|
primary:
|
||||||
|
<<: *default
|
||||||
|
database: db/development.sqlite3
|
||||||
|
<% else %>
|
||||||
primary:
|
primary:
|
||||||
<<: *default
|
<<: *default
|
||||||
database: fizzy_development
|
database: fizzy_development
|
||||||
@@ -26,28 +40,34 @@ development:
|
|||||||
replica:
|
replica:
|
||||||
<<: *default
|
<<: *default
|
||||||
database: fizzy_development
|
database: fizzy_development
|
||||||
replica: true
|
|
||||||
port: <%= ENV.fetch "FIZZY_DB_PORT", 33380 %>
|
port: <%= ENV.fetch "FIZZY_DB_PORT", 33380 %>
|
||||||
|
replica: true
|
||||||
cable:
|
cable:
|
||||||
<<: *default
|
<<: *default
|
||||||
database: development_cable
|
database: development_cable
|
||||||
migrations_paths: db/cable_migrate
|
|
||||||
port: <%= ENV.fetch "FIZZY_DB_PORT", 33380 %>
|
port: <%= ENV.fetch "FIZZY_DB_PORT", 33380 %>
|
||||||
|
migrations_paths: db/cable_migrate
|
||||||
cache:
|
cache:
|
||||||
<<: *default
|
<<: *default
|
||||||
database: development_cache
|
database: development_cache
|
||||||
migrations_paths: db/cache_migrate
|
|
||||||
port: <%= ENV.fetch "FIZZY_DB_PORT", 33380 %>
|
port: <%= ENV.fetch "FIZZY_DB_PORT", 33380 %>
|
||||||
|
migrations_paths: db/cache_migrate
|
||||||
queue:
|
queue:
|
||||||
<<: *default
|
<<: *default
|
||||||
database: development_queue
|
database: development_queue
|
||||||
migrations_paths: db/queue_migrate
|
|
||||||
port: <%= ENV.fetch "FIZZY_DB_PORT", 33380 %>
|
port: <%= ENV.fetch "FIZZY_DB_PORT", 33380 %>
|
||||||
|
migrations_paths: db/queue_migrate
|
||||||
|
<% end %>
|
||||||
|
|
||||||
# Warning: The database defined as "test" will be erased and
|
# Warning: The database defined as "test" will be erased and
|
||||||
# re-generated from your development database when you run "rake".
|
# re-generated from your development database when you run "rake".
|
||||||
# Do not set this db to the same as development or production.
|
# Do not set this db to the same as development or production.
|
||||||
test:
|
test:
|
||||||
|
<% if use_sqlite %>
|
||||||
|
primary:
|
||||||
|
<<: *default
|
||||||
|
database: db/test.sqlite3
|
||||||
|
<% else %>
|
||||||
primary:
|
primary:
|
||||||
<<: *default
|
<<: *default
|
||||||
database: fizzy_test
|
database: fizzy_test
|
||||||
@@ -57,6 +77,7 @@ test:
|
|||||||
database: fizzy_test
|
database: fizzy_test
|
||||||
port: <%= ENV.fetch "FIZZY_DB_PORT", 33380 %>
|
port: <%= ENV.fetch "FIZZY_DB_PORT", 33380 %>
|
||||||
replica: true
|
replica: true
|
||||||
|
<% end %>
|
||||||
|
|
||||||
production: &production
|
production: &production
|
||||||
primary:
|
primary:
|
||||||
|
|||||||
@@ -6,7 +6,12 @@ end
|
|||||||
|
|
||||||
# Use DB read/write splitting for Active Storage models
|
# Use DB read/write splitting for Active Storage models
|
||||||
ActiveSupport.on_load(:active_storage_record) do
|
ActiveSupport.on_load(:active_storage_record) do
|
||||||
connects_to database: { writing: :primary, reading: :replica }
|
# SQLite doesn't use separate replica databases
|
||||||
|
if ENV.fetch("DATABASE_ADAPTER", "mysql") == "sqlite"
|
||||||
|
connects_to database: { writing: :primary, reading: :primary }
|
||||||
|
else
|
||||||
|
connects_to database: { writing: :primary, reading: :replica }
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
module ActiveStorageControllerExtensions
|
module ActiveStorageControllerExtensions
|
||||||
|
|||||||
@@ -0,0 +1,54 @@
|
|||||||
|
# SQLite compatibility layer - filters out MySQL-specific options when using SQLite
|
||||||
|
|
||||||
|
# Define modules outside on_load so they're available immediately
|
||||||
|
module SQLiteCompatibility
|
||||||
|
module SQLiteTableDefinitionCompatibility
|
||||||
|
# Override column method to filter out MySQL-specific options
|
||||||
|
def column(name, type, **options)
|
||||||
|
# Check if we're using SQLite by checking the connection adapter
|
||||||
|
if @conn.is_a?(ActiveRecord::ConnectionAdapters::SQLite3Adapter)
|
||||||
|
# Remove MySQL-specific options that SQLite doesn't support
|
||||||
|
options = options.except(:size, :charset, :collation, :unsigned)
|
||||||
|
end
|
||||||
|
super(name, type, **options)
|
||||||
|
end
|
||||||
|
|
||||||
|
# Override index method to filter out MySQL-specific index options
|
||||||
|
def index(column_name, **options)
|
||||||
|
if @conn.is_a?(ActiveRecord::ConnectionAdapters::SQLite3Adapter)
|
||||||
|
# Skip fulltext indexes entirely for SQLite
|
||||||
|
return if options[:type] == :fulltext
|
||||||
|
# SQLite doesn't support length-limited indexes
|
||||||
|
options = options.except(:length)
|
||||||
|
end
|
||||||
|
super(column_name, **options)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
module SQLiteSchemaStatementCompatibility
|
||||||
|
# Override create_table to filter out MySQL-specific table options
|
||||||
|
def create_table(table_name, **options)
|
||||||
|
if is_a?(ActiveRecord::ConnectionAdapters::SQLite3Adapter)
|
||||||
|
# Remove MySQL-specific table options
|
||||||
|
options = options.except(:charset, :collation)
|
||||||
|
end
|
||||||
|
super(table_name, **options)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# Apply the prepends - both in on_load callback and immediately
|
||||||
|
def apply_sqlite_compatibility
|
||||||
|
if defined?(ActiveRecord::ConnectionAdapters::SQLite3Adapter)
|
||||||
|
ActiveRecord::ConnectionAdapters::TableDefinition.prepend(SQLiteCompatibility::SQLiteTableDefinitionCompatibility)
|
||||||
|
ActiveRecord::ConnectionAdapters::SQLite3Adapter.prepend(SQLiteCompatibility::SQLiteSchemaStatementCompatibility)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# Run immediately if ActiveRecord is already loaded
|
||||||
|
apply_sqlite_compatibility
|
||||||
|
|
||||||
|
# Also run when ActiveRecord loads (for cases where it loads later)
|
||||||
|
ActiveSupport.on_load(:active_record) do
|
||||||
|
apply_sqlite_compatibility
|
||||||
|
end
|
||||||
@@ -16,7 +16,42 @@ ActiveSupport.on_load(:active_record) do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
ActiveRecord::ConnectionAdapters::AbstractMysqlAdapter.prepend(MysqlUuidAdapter)
|
if defined?(ActiveRecord::ConnectionAdapters::AbstractMysqlAdapter)
|
||||||
|
ActiveRecord::ConnectionAdapters::AbstractMysqlAdapter.prepend(MysqlUuidAdapter)
|
||||||
|
end
|
||||||
|
|
||||||
|
module SqliteUuidAdapter
|
||||||
|
# Add UUID to SQLite's native database types
|
||||||
|
def native_database_types
|
||||||
|
@native_database_types_with_uuid ||= super.merge(uuid: { name: "blob", limit: 16 })
|
||||||
|
end
|
||||||
|
|
||||||
|
# Override lookup_cast_type to recognize BLOB as UUID type
|
||||||
|
def lookup_cast_type(sql_type)
|
||||||
|
if sql_type == "blob(16)"
|
||||||
|
ActiveRecord::Type.lookup(:uuid, adapter: :sqlite3)
|
||||||
|
else
|
||||||
|
super
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# Override fetch_type_metadata to preserve UUID type and limit
|
||||||
|
def fetch_type_metadata(sql_type)
|
||||||
|
if sql_type == "blob(16)"
|
||||||
|
ActiveRecord::ConnectionAdapters::SqlTypeMetadata.new(
|
||||||
|
sql_type: sql_type,
|
||||||
|
type: :uuid,
|
||||||
|
limit: 16
|
||||||
|
)
|
||||||
|
else
|
||||||
|
super
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if defined?(ActiveRecord::ConnectionAdapters::SQLite3Adapter)
|
||||||
|
ActiveRecord::ConnectionAdapters::SQLite3Adapter.prepend(SqliteUuidAdapter)
|
||||||
|
end
|
||||||
|
|
||||||
module SchemaDumperUuidType
|
module SchemaDumperUuidType
|
||||||
# Map binary(16) columns to :uuid type in schema.rb
|
# Map binary(16) columns to :uuid type in schema.rb
|
||||||
@@ -29,7 +64,9 @@ ActiveSupport.on_load(:active_record) do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
ActiveRecord::ConnectionAdapters::MySQL::SchemaDumper.prepend(SchemaDumperUuidType)
|
if defined?(ActiveRecord::ConnectionAdapters::MySQL::SchemaDumper)
|
||||||
|
ActiveRecord::ConnectionAdapters::MySQL::SchemaDumper.prepend(SchemaDumperUuidType)
|
||||||
|
end
|
||||||
|
|
||||||
module TableDefinitionUuidSupport
|
module TableDefinitionUuidSupport
|
||||||
def uuid(name, **options)
|
def uuid(name, **options)
|
||||||
|
|||||||
@@ -39,5 +39,6 @@ module ActiveRecord
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# Register the UUID type for Trilogy adapter
|
# Register the UUID type for Trilogy (MySQL) and SQLite3 adapters
|
||||||
ActiveRecord::Type.register(:uuid, ActiveRecord::Type::Uuid, adapter: :trilogy)
|
ActiveRecord::Type.register(:uuid, ActiveRecord::Type::Uuid, adapter: :trilogy)
|
||||||
|
ActiveRecord::Type.register(:uuid, ActiveRecord::Type::Uuid, adapter: :sqlite3)
|
||||||
|
|||||||
Vendored
+2
-2
@@ -7,5 +7,5 @@ kevin:
|
|||||||
jz:
|
jz:
|
||||||
identity: jz
|
identity: jz
|
||||||
|
|
||||||
jason:
|
mike:
|
||||||
identity: jason
|
identity: mike
|
||||||
|
|||||||
Reference in New Issue
Block a user