diff --git a/.github/workflows/specs_mssql_61.yml b/.github/workflows/specs_mssql_61.yml new file mode 100644 index 0000000..d3f780b --- /dev/null +++ b/.github/workflows/specs_mssql_61.yml @@ -0,0 +1,53 @@ +--- +name: Specs Rails 6.1 MSSQL + +on: + pull_request: + branches: [main] + push: + branches: [main] + +jobs: + tests: + runs-on: ubuntu-latest + + strategy: + matrix: + ruby: ['3.0', '3.1', '3.2'] + gemfile: ['rails_6_1_mssql'] + + env: + BUNDLE_GEMFILE: ${{ github.workspace }}/gemfiles/${{ matrix.gemfile }}.gemfile + DB_TEST: mssql + MSSQL_DB_HOST: 127.0.0.1 + MSSQL_DB_USERNAME: sa + MSSQL_DB_PASSWORD: Pa%%w0rd + RAILS: '6.1' + + services: + postgres: + image: mcr.microsoft.com/mssql/server:2022-latest + env: + ACCEPT_EULA: 'Y' + SA_PASSWORD: Pa%%w0rd + ports: + - 1433:1433 + + steps: + - name: Install FreeTDS + run: sudo apt-get install -y freetds-dev freetds-bin + + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Set up Ruby + uses: ruby/setup-ruby@v1 + with: + ruby-version: ${{ matrix.ruby }} + bundler-cache: true + + - name: Database setup + run: bundle exec rails db:create db:migrate + + - name: Run tests + run: bundle exec rspec --profile diff --git a/.github/workflows/specs_mssql_70.yml b/.github/workflows/specs_mssql_70.yml new file mode 100644 index 0000000..6e2e270 --- /dev/null +++ b/.github/workflows/specs_mssql_70.yml @@ -0,0 +1,53 @@ +--- +name: Specs Rails 7.0 MSSQL + +on: + pull_request: + branches: [main] + push: + branches: [main] + +jobs: + tests: + runs-on: ubuntu-latest + + strategy: + matrix: + ruby: ['3.0', '3.1', '3.2'] + gemfile: ['rails_7_0_mssql'] + + env: + BUNDLE_GEMFILE: ${{ github.workspace }}/gemfiles/${{ matrix.gemfile }}.gemfile + DB_TEST: mssql + MSSQL_DB_HOST: 127.0.0.1 + MSSQL_DB_USERNAME: sa + MSSQL_DB_PASSWORD: Pa%%w0rd + RAILS: '7.0' + + services: + postgres: + image: mcr.microsoft.com/mssql/server:2022-latest + env: + ACCEPT_EULA: 'Y' + SA_PASSWORD: Pa%%w0rd + ports: + - 1433:1433 + + steps: + - name: Install FreeTDS + run: sudo apt-get install -y freetds-dev freetds-bin + + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Set up Ruby + uses: ruby/setup-ruby@v1 + with: + ruby-version: ${{ matrix.ruby }} + bundler-cache: true + + - name: Database setup + run: bundle exec rails db:create db:migrate + + - name: Run tests + run: bundle exec rspec --profile diff --git a/Appraisals b/Appraisals index fbee1de..962c59d 100644 --- a/Appraisals +++ b/Appraisals @@ -29,3 +29,15 @@ appraise 'rails-7_1-mysql' do gem 'mysql2' gem 'rails', '~> 7.1.0' end + +appraise 'rails-6_1-mssql' do + gem 'activerecord-sqlserver-adapter', '~> 6.1.0' + gem 'rails', '~> 6.1.0' + gem 'tiny_tds' +end + +appraise 'rails-7_0-mssql' do + gem 'activerecord-sqlserver-adapter', '7.0.3.0' + gem 'rails', '~> 7.0.0' + gem 'tiny_tds' +end diff --git a/Gemfile b/Gemfile index 6885217..bbc87db 100644 --- a/Gemfile +++ b/Gemfile @@ -6,8 +6,13 @@ git_source(:github) { |repo| "https://github.com/#{repo}.git" } gemspec group :development, :test do + if ENV['DB_TEST'] == 'mssql' + gem 'activerecord-sqlserver-adapter', '7.0.3.0' + gem 'tiny_tds' + end gem 'mysql2' if ENV['DB_TEST'] == 'mysql' gem 'pg' if ['postgres', 'postgresql'].include? ENV['DB_TEST'] + gem 'simplecov' gem 'simplecov-lcov' diff --git a/README.md b/README.md index 5cd6353..3e6376d 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ [![specs Postgres](https://github.com/blocknotes/active_storage_db/actions/workflows/specs_postgres_71.yml/badge.svg)](https://github.com/blocknotes/active_storage_db/actions/workflows/specs_postgres_71.yml) [![specs MySQL](https://github.com/blocknotes/active_storage_db/actions/workflows/specs_mysql_71.yml/badge.svg)](https://github.com/blocknotes/active_storage_db/actions/workflows/specs_mysql_71.yml) -An Active Storage service upload/download plugin that stores files in a PostgreSQL or MySQL database. +An Active Storage service upload/download plugin that stores files in a PostgreSQL or MySQL database. Experimental support also for MSSQL. Main features: - attachment data stored in a binary field (or blob); diff --git a/extra/Dockerfile_32 b/extra/Dockerfile_32 index 2a96091..1aced9f 100644 --- a/extra/Dockerfile_32 +++ b/extra/Dockerfile_32 @@ -3,7 +3,7 @@ FROM ruby:3.2-slim ARG DB_TEST RUN apt-get update -RUN apt-get install --no-install-recommends -y build-essential curl file git nano netcat-traditional libmariadb-dev libpq-dev openssl tzdata +RUN apt-get install --no-install-recommends -y build-essential curl file freetds-dev freetds-bin git nano netcat-traditional libmariadb-dev libpq-dev openssl tzdata # App setup WORKDIR /usr/src/app diff --git a/extra/docker-compose.yml b/extra/docker-compose.yml index 149d1aa..8668b93 100644 --- a/extra/docker-compose.yml +++ b/extra/docker-compose.yml @@ -2,6 +2,33 @@ version: "3.3" x-defaults: + tests_mssql: &tests_mssql + environment: + CI: 1 + DB_TEST: mssql + DB_PORT: 1433 + MSSQL_DB_HOST: mssql + MSSQL_DB_NAME: test_db + MSSQL_DB_USERNAME: sa + MSSQL_DB_PASSWORD: Pa%%w0rd + RAILS: '7.0' + RAILS_ENV: test + command: + - sh + - -c + - | + while ! nc -z $${DB_TEST} $${DB_PORT} 6.1.0" +gem "rails", "~> 6.1.0" +gem "tiny_tds" + +group :development, :test do + gem "simplecov" + gem "simplecov-lcov" + gem "capybara" + gem "rspec_junit_formatter" + gem "rspec-rails" + gem "selenium-webdriver" + gem "brakeman" + gem "fasterer" + gem "rubocop" + gem "rubocop-packaging" + gem "rubocop-performance" + gem "rubocop-rails" + gem "rubocop-rspec" + gem "pry-rails" +end + +gemspec path: "../" diff --git a/gemfiles/rails_6_1_mssql.gemfile.lock b/gemfiles/rails_6_1_mssql.gemfile.lock new file mode 100644 index 0000000..fb39bbf --- /dev/null +++ b/gemfiles/rails_6_1_mssql.gemfile.lock @@ -0,0 +1,297 @@ +PATH + remote: .. + specs: + active_storage_db (1.2.0) + activestorage (>= 6.0) + rails (>= 6.0) + +GEM + remote: https://rubygems.org/ + specs: + actioncable (6.1.7.6) + actionpack (= 6.1.7.6) + activesupport (= 6.1.7.6) + nio4r (~> 2.0) + websocket-driver (>= 0.6.1) + actionmailbox (6.1.7.6) + actionpack (= 6.1.7.6) + activejob (= 6.1.7.6) + activerecord (= 6.1.7.6) + activestorage (= 6.1.7.6) + activesupport (= 6.1.7.6) + mail (>= 2.7.1) + actionmailer (6.1.7.6) + actionpack (= 6.1.7.6) + actionview (= 6.1.7.6) + activejob (= 6.1.7.6) + activesupport (= 6.1.7.6) + mail (~> 2.5, >= 2.5.4) + rails-dom-testing (~> 2.0) + actionpack (6.1.7.6) + actionview (= 6.1.7.6) + activesupport (= 6.1.7.6) + rack (~> 2.0, >= 2.0.9) + rack-test (>= 0.6.3) + rails-dom-testing (~> 2.0) + rails-html-sanitizer (~> 1.0, >= 1.2.0) + actiontext (6.1.7.6) + actionpack (= 6.1.7.6) + activerecord (= 6.1.7.6) + activestorage (= 6.1.7.6) + activesupport (= 6.1.7.6) + nokogiri (>= 1.8.5) + actionview (6.1.7.6) + activesupport (= 6.1.7.6) + builder (~> 3.1) + erubi (~> 1.4) + rails-dom-testing (~> 2.0) + rails-html-sanitizer (~> 1.1, >= 1.2.0) + activejob (6.1.7.6) + activesupport (= 6.1.7.6) + globalid (>= 0.3.6) + activemodel (6.1.7.6) + activesupport (= 6.1.7.6) + activerecord (6.1.7.6) + activemodel (= 6.1.7.6) + activesupport (= 6.1.7.6) + activerecord-sqlserver-adapter (6.1.3.0) + activerecord (~> 6.1.0) + tiny_tds + activestorage (6.1.7.6) + actionpack (= 6.1.7.6) + activejob (= 6.1.7.6) + activerecord (= 6.1.7.6) + activesupport (= 6.1.7.6) + marcel (~> 1.0) + mini_mime (>= 1.1.0) + activesupport (6.1.7.6) + concurrent-ruby (~> 1.0, >= 1.0.2) + i18n (>= 1.6, < 2) + minitest (>= 5.1) + tzinfo (~> 2.0) + zeitwerk (~> 2.3) + addressable (2.8.5) + public_suffix (>= 2.0.2, < 6.0) + appraisal (2.5.0) + bundler + rake + thor (>= 0.14.0) + ast (2.4.2) + brakeman (6.0.1) + builder (3.2.4) + capybara (3.39.2) + addressable + matrix + mini_mime (>= 0.1.3) + nokogiri (~> 1.8) + rack (>= 1.6.0) + rack-test (>= 0.6.3) + regexp_parser (>= 1.5, < 3.0) + xpath (~> 3.2) + coderay (1.1.3) + colorize (0.8.1) + concurrent-ruby (1.2.2) + crass (1.0.6) + date (3.3.3) + diff-lcs (1.5.0) + docile (1.4.0) + erubi (1.12.0) + factory_bot (6.2.1) + activesupport (>= 5.0.0) + factory_bot_rails (6.2.0) + factory_bot (~> 6.2.0) + railties (>= 5.0.0) + fasterer (0.10.1) + colorize (~> 0.7) + ruby_parser (>= 3.19.1) + globalid (1.2.1) + activesupport (>= 6.1) + i18n (1.14.1) + concurrent-ruby (~> 1.0) + json (2.6.3) + language_server-protocol (3.17.0.3) + loofah (2.21.4) + crass (~> 1.0.2) + nokogiri (>= 1.12.0) + mail (2.8.1) + mini_mime (>= 0.1.1) + net-imap + net-pop + net-smtp + marcel (1.0.2) + matrix (0.4.2) + method_source (1.0.0) + mini_mime (1.1.5) + minitest (5.20.0) + net-imap (0.4.3) + date + net-protocol + net-pop (0.1.2) + net-protocol + net-protocol (0.2.1) + timeout + net-smtp (0.4.0) + net-protocol + nio4r (2.5.9) + nokogiri (1.15.4-arm64-darwin) + racc (~> 1.4) + parallel (1.23.0) + parser (3.2.2.4) + ast (~> 2.4.1) + racc + pry (0.14.2) + coderay (~> 1.1) + method_source (~> 1.0) + pry-rails (0.3.9) + pry (>= 0.10.4) + public_suffix (5.0.3) + racc (1.7.2) + rack (2.2.8) + rack-test (2.1.0) + rack (>= 1.3) + rails (6.1.7.6) + actioncable (= 6.1.7.6) + actionmailbox (= 6.1.7.6) + actionmailer (= 6.1.7.6) + actionpack (= 6.1.7.6) + actiontext (= 6.1.7.6) + actionview (= 6.1.7.6) + activejob (= 6.1.7.6) + activemodel (= 6.1.7.6) + activerecord (= 6.1.7.6) + activestorage (= 6.1.7.6) + activesupport (= 6.1.7.6) + bundler (>= 1.15.0) + railties (= 6.1.7.6) + sprockets-rails (>= 2.0.0) + rails-dom-testing (2.2.0) + activesupport (>= 5.0.0) + minitest + nokogiri (>= 1.6) + rails-html-sanitizer (1.6.0) + loofah (~> 2.21) + nokogiri (~> 1.14) + railties (6.1.7.6) + actionpack (= 6.1.7.6) + activesupport (= 6.1.7.6) + method_source + rake (>= 12.2) + thor (~> 1.0) + rainbow (3.1.1) + rake (13.1.0) + regexp_parser (2.8.2) + rexml (3.2.6) + rspec-core (3.12.2) + rspec-support (~> 3.12.0) + rspec-expectations (3.12.3) + diff-lcs (>= 1.2.0, < 2.0) + rspec-support (~> 3.12.0) + rspec-mocks (3.12.6) + diff-lcs (>= 1.2.0, < 2.0) + rspec-support (~> 3.12.0) + rspec-rails (6.0.3) + actionpack (>= 6.1) + activesupport (>= 6.1) + railties (>= 6.1) + rspec-core (~> 3.12) + rspec-expectations (~> 3.12) + rspec-mocks (~> 3.12) + rspec-support (~> 3.12) + rspec-support (3.12.1) + rspec_junit_formatter (0.6.0) + rspec-core (>= 2, < 4, != 2.12.0) + rubocop (1.57.2) + json (~> 2.3) + language_server-protocol (>= 3.17.0) + parallel (~> 1.10) + parser (>= 3.2.2.4) + rainbow (>= 2.2.2, < 4.0) + regexp_parser (>= 1.8, < 3.0) + rexml (>= 3.2.5, < 4.0) + rubocop-ast (>= 1.28.1, < 2.0) + ruby-progressbar (~> 1.7) + unicode-display_width (>= 2.4.0, < 3.0) + rubocop-ast (1.30.0) + parser (>= 3.2.1.0) + rubocop-capybara (2.19.0) + rubocop (~> 1.41) + rubocop-factory_bot (2.24.0) + rubocop (~> 1.33) + rubocop-packaging (0.5.2) + rubocop (>= 1.33, < 2.0) + rubocop-performance (1.19.1) + rubocop (>= 1.7.0, < 2.0) + rubocop-ast (>= 0.4.0) + rubocop-rails (2.22.1) + activesupport (>= 4.2.0) + rack (>= 1.1) + rubocop (>= 1.33.0, < 2.0) + rubocop-rspec (2.25.0) + rubocop (~> 1.40) + rubocop-capybara (~> 2.17) + rubocop-factory_bot (~> 2.22) + ruby-progressbar (1.13.0) + ruby_parser (3.20.3) + sexp_processor (~> 4.16) + rubyzip (2.3.2) + selenium-webdriver (4.15.0) + rexml (~> 3.2, >= 3.2.5) + rubyzip (>= 1.2.2, < 3.0) + websocket (~> 1.0) + sexp_processor (4.17.0) + simplecov (0.22.0) + docile (~> 1.1) + simplecov-html (~> 0.11) + simplecov_json_formatter (~> 0.1) + simplecov-html (0.12.3) + simplecov-lcov (0.8.0) + simplecov_json_formatter (0.1.4) + sprockets (4.2.1) + concurrent-ruby (~> 1.0) + rack (>= 2.2.4, < 4) + sprockets-rails (3.4.2) + actionpack (>= 5.2) + activesupport (>= 5.2) + sprockets (>= 3.0.0) + thor (1.3.0) + timeout (0.4.0) + tiny_tds (2.1.5) + tzinfo (2.0.6) + concurrent-ruby (~> 1.0) + unicode-display_width (2.5.0) + websocket (1.2.10) + websocket-driver (0.7.6) + websocket-extensions (>= 0.1.0) + websocket-extensions (0.1.5) + xpath (3.2.0) + nokogiri (~> 1.8) + zeitwerk (2.6.12) + +PLATFORMS + arm64-darwin-22 + x86_64-linux + +DEPENDENCIES + active_storage_db! + activerecord-sqlserver-adapter (~> 6.1.0) + appraisal (~> 2.4) + brakeman + capybara + factory_bot_rails (~> 6.1) + fasterer + pry-rails + rails (~> 6.1.0) + rspec-rails + rspec_junit_formatter + rubocop + rubocop-packaging + rubocop-performance + rubocop-rails + rubocop-rspec + selenium-webdriver + simplecov + simplecov-lcov + tiny_tds + +BUNDLED WITH + 2.4.19 diff --git a/gemfiles/rails_7_0_mssql.gemfile b/gemfiles/rails_7_0_mssql.gemfile new file mode 100644 index 0000000..02a1349 --- /dev/null +++ b/gemfiles/rails_7_0_mssql.gemfile @@ -0,0 +1,26 @@ +# This file was generated by Appraisal + +source "https://rubygems.org" + +gem "activerecord-sqlserver-adapter", "7.0.3.0" +gem "rails", "~> 7.0.0" +gem "tiny_tds" + +group :development, :test do + gem "simplecov" + gem "simplecov-lcov" + gem "capybara" + gem "rspec_junit_formatter" + gem "rspec-rails" + gem "selenium-webdriver" + gem "brakeman" + gem "fasterer" + gem "rubocop" + gem "rubocop-packaging" + gem "rubocop-performance" + gem "rubocop-rails" + gem "rubocop-rspec" + gem "pry-rails" +end + +gemspec path: "../" diff --git a/gemfiles/rails_7_0_mssql.gemfile.lock b/gemfiles/rails_7_0_mssql.gemfile.lock new file mode 100644 index 0000000..fd58295 --- /dev/null +++ b/gemfiles/rails_7_0_mssql.gemfile.lock @@ -0,0 +1,298 @@ +PATH + remote: .. + specs: + active_storage_db (1.2.0) + activestorage (>= 6.0) + rails (>= 6.0) + +GEM + remote: https://rubygems.org/ + specs: + actioncable (7.0.8) + actionpack (= 7.0.8) + activesupport (= 7.0.8) + nio4r (~> 2.0) + websocket-driver (>= 0.6.1) + actionmailbox (7.0.8) + actionpack (= 7.0.8) + activejob (= 7.0.8) + activerecord (= 7.0.8) + activestorage (= 7.0.8) + activesupport (= 7.0.8) + mail (>= 2.7.1) + net-imap + net-pop + net-smtp + actionmailer (7.0.8) + actionpack (= 7.0.8) + actionview (= 7.0.8) + activejob (= 7.0.8) + activesupport (= 7.0.8) + mail (~> 2.5, >= 2.5.4) + net-imap + net-pop + net-smtp + rails-dom-testing (~> 2.0) + actionpack (7.0.8) + actionview (= 7.0.8) + activesupport (= 7.0.8) + rack (~> 2.0, >= 2.2.4) + rack-test (>= 0.6.3) + rails-dom-testing (~> 2.0) + rails-html-sanitizer (~> 1.0, >= 1.2.0) + actiontext (7.0.8) + actionpack (= 7.0.8) + activerecord (= 7.0.8) + activestorage (= 7.0.8) + activesupport (= 7.0.8) + globalid (>= 0.6.0) + nokogiri (>= 1.8.5) + actionview (7.0.8) + activesupport (= 7.0.8) + builder (~> 3.1) + erubi (~> 1.4) + rails-dom-testing (~> 2.0) + rails-html-sanitizer (~> 1.1, >= 1.2.0) + activejob (7.0.8) + activesupport (= 7.0.8) + globalid (>= 0.3.6) + activemodel (7.0.8) + activesupport (= 7.0.8) + activerecord (7.0.8) + activemodel (= 7.0.8) + activesupport (= 7.0.8) + activerecord-sqlserver-adapter (7.0.3.0) + activerecord (~> 7.0.0) + tiny_tds + activestorage (7.0.8) + actionpack (= 7.0.8) + activejob (= 7.0.8) + activerecord (= 7.0.8) + activesupport (= 7.0.8) + marcel (~> 1.0) + mini_mime (>= 1.1.0) + activesupport (7.0.8) + concurrent-ruby (~> 1.0, >= 1.0.2) + i18n (>= 1.6, < 2) + minitest (>= 5.1) + tzinfo (~> 2.0) + addressable (2.8.5) + public_suffix (>= 2.0.2, < 6.0) + appraisal (2.5.0) + bundler + rake + thor (>= 0.14.0) + ast (2.4.2) + brakeman (6.0.1) + builder (3.2.4) + capybara (3.39.2) + addressable + matrix + mini_mime (>= 0.1.3) + nokogiri (~> 1.8) + rack (>= 1.6.0) + rack-test (>= 0.6.3) + regexp_parser (>= 1.5, < 3.0) + xpath (~> 3.2) + coderay (1.1.3) + colorize (0.8.1) + concurrent-ruby (1.2.2) + crass (1.0.6) + date (3.3.3) + diff-lcs (1.5.0) + docile (1.4.0) + erubi (1.12.0) + factory_bot (6.2.1) + activesupport (>= 5.0.0) + factory_bot_rails (6.2.0) + factory_bot (~> 6.2.0) + railties (>= 5.0.0) + fasterer (0.10.1) + colorize (~> 0.7) + ruby_parser (>= 3.19.1) + globalid (1.2.1) + activesupport (>= 6.1) + i18n (1.14.1) + concurrent-ruby (~> 1.0) + json (2.6.3) + language_server-protocol (3.17.0.3) + loofah (2.21.4) + crass (~> 1.0.2) + nokogiri (>= 1.12.0) + mail (2.8.1) + mini_mime (>= 0.1.1) + net-imap + net-pop + net-smtp + marcel (1.0.2) + matrix (0.4.2) + method_source (1.0.0) + mini_mime (1.1.5) + minitest (5.20.0) + net-imap (0.4.3) + date + net-protocol + net-pop (0.1.2) + net-protocol + net-protocol (0.2.1) + timeout + net-smtp (0.4.0) + net-protocol + nio4r (2.5.9) + nokogiri (1.15.4-arm64-darwin) + racc (~> 1.4) + nokogiri (1.15.4-x86_64-linux) + racc (~> 1.4) + parallel (1.23.0) + parser (3.2.2.4) + ast (~> 2.4.1) + racc + pry (0.14.2) + coderay (~> 1.1) + method_source (~> 1.0) + pry-rails (0.3.9) + pry (>= 0.10.4) + public_suffix (5.0.3) + racc (1.7.2) + rack (2.2.8) + rack-test (2.1.0) + rack (>= 1.3) + rails (7.0.8) + actioncable (= 7.0.8) + actionmailbox (= 7.0.8) + actionmailer (= 7.0.8) + actionpack (= 7.0.8) + actiontext (= 7.0.8) + actionview (= 7.0.8) + activejob (= 7.0.8) + activemodel (= 7.0.8) + activerecord (= 7.0.8) + activestorage (= 7.0.8) + activesupport (= 7.0.8) + bundler (>= 1.15.0) + railties (= 7.0.8) + rails-dom-testing (2.2.0) + activesupport (>= 5.0.0) + minitest + nokogiri (>= 1.6) + rails-html-sanitizer (1.6.0) + loofah (~> 2.21) + nokogiri (~> 1.14) + railties (7.0.8) + actionpack (= 7.0.8) + activesupport (= 7.0.8) + method_source + rake (>= 12.2) + thor (~> 1.0) + zeitwerk (~> 2.5) + rainbow (3.1.1) + rake (13.1.0) + regexp_parser (2.8.2) + rexml (3.2.6) + rspec-core (3.12.2) + rspec-support (~> 3.12.0) + rspec-expectations (3.12.3) + diff-lcs (>= 1.2.0, < 2.0) + rspec-support (~> 3.12.0) + rspec-mocks (3.12.6) + diff-lcs (>= 1.2.0, < 2.0) + rspec-support (~> 3.12.0) + rspec-rails (6.0.3) + actionpack (>= 6.1) + activesupport (>= 6.1) + railties (>= 6.1) + rspec-core (~> 3.12) + rspec-expectations (~> 3.12) + rspec-mocks (~> 3.12) + rspec-support (~> 3.12) + rspec-support (3.12.1) + rspec_junit_formatter (0.6.0) + rspec-core (>= 2, < 4, != 2.12.0) + rubocop (1.57.2) + json (~> 2.3) + language_server-protocol (>= 3.17.0) + parallel (~> 1.10) + parser (>= 3.2.2.4) + rainbow (>= 2.2.2, < 4.0) + regexp_parser (>= 1.8, < 3.0) + rexml (>= 3.2.5, < 4.0) + rubocop-ast (>= 1.28.1, < 2.0) + ruby-progressbar (~> 1.7) + unicode-display_width (>= 2.4.0, < 3.0) + rubocop-ast (1.30.0) + parser (>= 3.2.1.0) + rubocop-capybara (2.19.0) + rubocop (~> 1.41) + rubocop-factory_bot (2.24.0) + rubocop (~> 1.33) + rubocop-packaging (0.5.2) + rubocop (>= 1.33, < 2.0) + rubocop-performance (1.19.1) + rubocop (>= 1.7.0, < 2.0) + rubocop-ast (>= 0.4.0) + rubocop-rails (2.22.1) + activesupport (>= 4.2.0) + rack (>= 1.1) + rubocop (>= 1.33.0, < 2.0) + rubocop-rspec (2.25.0) + rubocop (~> 1.40) + rubocop-capybara (~> 2.17) + rubocop-factory_bot (~> 2.22) + ruby-progressbar (1.13.0) + ruby_parser (3.20.3) + sexp_processor (~> 4.16) + rubyzip (2.3.2) + selenium-webdriver (4.15.0) + rexml (~> 3.2, >= 3.2.5) + rubyzip (>= 1.2.2, < 3.0) + websocket (~> 1.0) + sexp_processor (4.17.0) + simplecov (0.22.0) + docile (~> 1.1) + simplecov-html (~> 0.11) + simplecov_json_formatter (~> 0.1) + simplecov-html (0.12.3) + simplecov-lcov (0.8.0) + simplecov_json_formatter (0.1.4) + thor (1.3.0) + timeout (0.4.0) + tiny_tds (2.1.5) + tzinfo (2.0.6) + concurrent-ruby (~> 1.0) + unicode-display_width (2.5.0) + websocket (1.2.10) + websocket-driver (0.7.6) + websocket-extensions (>= 0.1.0) + websocket-extensions (0.1.5) + xpath (3.2.0) + nokogiri (~> 1.8) + zeitwerk (2.6.12) + +PLATFORMS + arm64-darwin-22 + x86_64-linux + +DEPENDENCIES + active_storage_db! + activerecord-sqlserver-adapter (= 7.0.3.0) + appraisal (~> 2.4) + brakeman + capybara + factory_bot_rails (~> 6.1) + fasterer + pry-rails + rails (~> 7.0.0) + rspec-rails + rspec_junit_formatter + rubocop + rubocop-packaging + rubocop-performance + rubocop-rails + rubocop-rspec + selenium-webdriver + simplecov + simplecov-lcov + tiny_tds + +BUNDLED WITH + 2.4.19 diff --git a/lib/active_storage/service/db_service.rb b/lib/active_storage/service/db_service.rb index d9e8b1a..3bd7458 100644 --- a/lib/active_storage/service/db_service.rb +++ b/lib/active_storage/service/db_service.rb @@ -45,7 +45,10 @@ def download(key, &block) def download_chunk(key, range) instrument :download_chunk, key: key, range: range do - record = object_for(key, fields: "SUBSTRING(data FROM #{range.begin + 1} FOR #{range.size}) AS chunk") + from = range.begin + 1 + size = range.size + args = adapter_sqlserver? ? "data, #{from}, #{size}" : "data FROM #{from} FOR #{size}" + record = object_for(key, fields: "SUBSTRING(#{args}) AS chunk") raise(ActiveStorage::FileNotFoundError) unless record record.chunk @@ -99,6 +102,10 @@ def headers_for_direct_upload(_key, content_type:, **) private + def adapter_sqlserver? + @adapter_sqlserver ||= ActiveStorageDB::File.connection.adapter_name == 'SQLServer' + end + def generate_url(key, expires_in:, filename:, content_type:, disposition:) content_disposition = content_disposition_with(type: disposition, filename: filename) verified_key_with_expiration = ActiveStorage.verifier.generate( @@ -144,7 +151,8 @@ def object_for(key, fields: nil) end def stream(key) - size = object_for(key, fields: 'OCTET_LENGTH(data) AS size')&.size || raise(ActiveStorage::FileNotFoundError) + data_size = adapter_sqlserver? ? 'DATALENGTH(data)' : 'OCTET_LENGTH(data)' + size = object_for(key, fields: "#{data_size} AS size")&.size || raise(ActiveStorage::FileNotFoundError) (size / @chunk_size.to_f).ceil.times.each do |i| range = (i * @chunk_size..((i + 1) * @chunk_size) - 1) yield download_chunk(key, range) diff --git a/spec/dummy61/config/database.yml b/spec/dummy61/config/database.yml index 8cc79a4..eeef139 100644 --- a/spec/dummy61/config/database.yml +++ b/spec/dummy61/config/database.yml @@ -1,5 +1,15 @@ <% case ENV['DB_TEST'] -when 'mysql' %> +when 'mssql' %> +test: &test + adapter: sqlserver + host: <%= ENV.fetch('MSSQL_DB_HOST') { '127.0.0.1' } %> + # port: <%= ENV.fetch('MSSQL_DB_PORT') { 1433 } %> + database: <%= ENV.fetch('MSSQL_DB_NAME') { ver = ENV.fetch('RAILS', '').tr('.', ''); "active_storage_db_#{ver}-test" } %> + username: <%= ENV.fetch('MSSQL_DB_USERNAME') { '' } %> + password: <%= ENV.fetch('MSSQL_DB_PASSWORD') { '' } %> + encoding: utf8 + pool: <%= ENV.fetch('RAILS_MAX_THREADS') { 5 } %> +<% when 'mysql' %> test: &test adapter: mysql2 host: <%= ENV.fetch('MYSQL_DB_HOST') { '127.0.0.1' } %> diff --git a/spec/dummy70/config/database.yml b/spec/dummy70/config/database.yml index 8cc79a4..eeef139 100644 --- a/spec/dummy70/config/database.yml +++ b/spec/dummy70/config/database.yml @@ -1,5 +1,15 @@ <% case ENV['DB_TEST'] -when 'mysql' %> +when 'mssql' %> +test: &test + adapter: sqlserver + host: <%= ENV.fetch('MSSQL_DB_HOST') { '127.0.0.1' } %> + # port: <%= ENV.fetch('MSSQL_DB_PORT') { 1433 } %> + database: <%= ENV.fetch('MSSQL_DB_NAME') { ver = ENV.fetch('RAILS', '').tr('.', ''); "active_storage_db_#{ver}-test" } %> + username: <%= ENV.fetch('MSSQL_DB_USERNAME') { '' } %> + password: <%= ENV.fetch('MSSQL_DB_PASSWORD') { '' } %> + encoding: utf8 + pool: <%= ENV.fetch('RAILS_MAX_THREADS') { 5 } %> +<% when 'mysql' %> test: &test adapter: mysql2 host: <%= ENV.fetch('MYSQL_DB_HOST') { '127.0.0.1' } %> diff --git a/spec/dummy70/db/schema.rb b/spec/dummy70/db/schema.rb index d617a9d..c0c3179 100644 --- a/spec/dummy70/db/schema.rb +++ b/spec/dummy70/db/schema.rb @@ -11,9 +11,6 @@ # It's strongly recommended that you check this file into your version control system. ActiveRecord::Schema[7.0].define(version: 2022_02_02_010101) do - # These are extensions that must be enabled in order to support this database - enable_extension "plpgsql" - create_table "active_storage_attachments", force: :cascade do |t| t.string "name", null: false t.string "record_type", null: false