{"id":13483751,"url":"https://github.com/rails-sqlserver/activerecord-sqlserver-adapter","last_synced_at":"2025-05-14T04:09:10.463Z","repository":{"id":452998,"uuid":"76404","full_name":"rails-sqlserver/activerecord-sqlserver-adapter","owner":"rails-sqlserver","description":"SQL Server Adapter For Rails","archived":false,"fork":false,"pushed_at":"2025-05-08T12:41:29.000Z","size":3974,"stargazers_count":980,"open_issues_count":22,"forks_count":565,"subscribers_count":53,"default_branch":"main","last_synced_at":"2025-05-11T00:42:02.463Z","etag":null,"topics":["activerecord","database","freetds","hacktoberfest","rails","ruby","sql","sql-server","tinytds"],"latest_commit_sha":null,"homepage":"","language":"Ruby","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/rails-sqlserver.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"MIT-LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2008-11-15T14:53:54.000Z","updated_at":"2025-05-10T14:04:53.000Z","dependencies_parsed_at":"2024-02-13T18:08:48.124Z","dependency_job_id":"59472623-bed6-4ef9-a5b8-59071f72a4c6","html_url":"https://github.com/rails-sqlserver/activerecord-sqlserver-adapter","commit_stats":{"total_commits":2003,"total_committers":104,"mean_commits":"19.259615384615383","dds":0.4802795806290564,"last_synced_commit":"c137deb9aec6e4c6971d2c5905463fca23a999ee"},"previous_names":[],"tags_count":186,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rails-sqlserver%2Factiverecord-sqlserver-adapter","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rails-sqlserver%2Factiverecord-sqlserver-adapter/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rails-sqlserver%2Factiverecord-sqlserver-adapter/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rails-sqlserver%2Factiverecord-sqlserver-adapter/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/rails-sqlserver","download_url":"https://codeload.github.com/rails-sqlserver/activerecord-sqlserver-adapter/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":253660027,"owners_count":21943734,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["activerecord","database","freetds","hacktoberfest","rails","ruby","sql","sql-server","tinytds"],"created_at":"2024-07-31T17:01:14.879Z","updated_at":"2025-05-14T04:09:05.445Z","avatar_url":"https://github.com/rails-sqlserver.png","language":"Ruby","readme":"# ActiveRecord SQL Server Adapter\n\n* [![CI](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/actions/workflows/ci.yml/badge.svg)](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/actions/workflows/ci.yml) - CI\n* [![Gem Version](http://img.shields.io/gem/v/activerecord-sqlserver-adapter.svg)](https://rubygems.org/gems/activerecord-sqlserver-adapter) - Gem Version\n* [![Gitter chat](https://img.shields.io/badge/%E2%8A%AA%20GITTER%20-JOIN%20CHAT%20%E2%86%92-brightgreen.svg?style=flat)](https://gitter.im/rails-sqlserver/activerecord-sqlserver-adapter) - Community\n\n## About The Adapter\n\nThe SQL Server adapter for ActiveRecord using SQL Server 2012 or higher.\n\nWe follow a rational versioning policy that tracks Rails. That means that our 7.x version of the adapter is only\nfor the latest 7.x version of Rails. We also have stable branches for each major/minor release of ActiveRecord.\n\nWe support the versions of the adapter that are in the Rails [Bug Fixes](https://rubyonrails.org/maintenance)\nmaintenance group.\n\nSee [Rubygems](https://rubygems.org/gems/activerecord-sqlserver-adapter/versions) for the latest version of the adapter for each Rails release.\n\n| Adapter Version | Rails Version | Support        | Branch                                                                                             |\n|-----------------|---------------|----------------|----------------------------------------------------------------------------------------------------|\n| Unreleased      | `8.1.x`       | In Development | [main](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/tree/main)                |\n| `8.0.x`         | `8.0.x`       | Active         | [8-0-stable](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/tree/8-0-stable) |\n| `7.2.x`         | `7.2.x`       | Active         | [7-2-stable](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/tree/7-2-stable)    |\n| `7.1.x`         | `7.1.x`       | Active         | [7-1-stable](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/tree/7-1-stable)    |\n| `7.0.x`         | `7.0.x`       | Ended          | [7-0-stable](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/tree/7-0-stable)    |\n| `6.1.x`         | `6.1.x`       | Ended          | [6-1-stable](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/tree/6-1-stable)    |\n| `6.0.x`         | `6.0.x`       | Ended          | [6-0-stable](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/tree/6-0-stable)    |\n| `5.2.x`         | `5.2.x`       | Ended          | [5-2-stable](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/tree/5-2-stable)    |\n| `5.1.x`         | `5.1.x`       | Ended          | [5-1-stable](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/tree/5-1-stable)    |\n| `4.2.x`         | `4.2.x`       | Ended          | [4-2-stable](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/tree/4-2-stable)    |\n| `4.1.x`         | `4.1.x`       | Ended          | [4-1-stable](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/tree/4-1-stable)    |\n\n\n#### Native Data Type Support\n\nWe support every data type supported by FreeTDS. All simplified Rails types in migrations will correspond to a matching SQL Server national (unicode) data type. Always check the `initialize_native_database_types` [(here)](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/blob/master/lib/active_record/connection_adapters/sqlserver/schema_statements.rb) for an updated list.\n\nThe following types (`date`, `datetime2`, `datetimeoffset`, `time`) all require TDS version `7.3` with TinyTDS. We recommend using FreeTDS 1.0 or higher which default to using `TDSVER` to `7.3`. The adapter also sets TinyTDS's `tds_version` to this as well if non is specified.\n\nThe adapter supports ActiveRecord's `datetime_with_precision` setting. This means that passing `:precision` to a datetime column is supported.\n\nBy default, precision 6 is used for `:datetime` types if precision is not specified. Any non-nil precision will tell\nthe adapter to use the `datetime2` column type. To create a `datetime` column using a migration a precision of `nil`\nshould be specified, otherwise the precision will default to 6 and a `datetime2` column will be created.\n\n\n#### Identity Inserts with Triggers\n\nThe adapter uses `OUTPUT INSERTED` so that we can select any data type key, for example UUID tables. However, this poses a problem with tables that use triggers. The solution requires that we use a more complex insert statement which uses a temporary table to select the inserted identity. To use this format you must declare your table exempt from the simple output inserted style with the table name into a concurrent hash. Optionally, you can set the data type of the table's primary key to return.\n\n```ruby\nadapter = ActiveRecord::ConnectionAdapters::SQLServerAdapter\n\n# Will assume `bigint` as the id key temp table type.\nadapter.exclude_output_inserted_table_names['my_table_name'] = true\n\n# Explicitly set the data type for the temporary key table.\nadapter.exclude_output_inserted_table_names['my_uuid_table_name'] = 'uniqueidentifier'\n\n\n# Explicitly set data types when data type is different for composite primary keys.\nadapter.exclude_output_inserted_table_names['my_composite_pk_table_name'] = { pk_col_one: \"uniqueidentifier\", pk_col_two: \"int\" }\n```\n\n\n#### Force Schema To Lowercase\n\nAlthough it is not necessary, the Ruby convention is to use lowercase method names. If your database schema is in upper or mixed case, we can force all table and column names during the schema reflection process to be lowercase. Add this to your config/initializers file for the adapter.\n\n```ruby\nActiveRecord::ConnectionAdapters::SQLServerAdapter.lowercase_schema_reflection = true\n```\n\n\n#### Schemas \u0026 Users\n\nDepending on your user and schema setup, it may be needed to use a table name prefix of `dbo.`. So something like this in your initializer file for ActiveRecord or the adapter.\n\n```ruby\nActiveRecord::Base.table_name_prefix = 'dbo.'\n```\n\nIt's also possible to create/change/drop a schema in the migration file as in the example below:\n\n```ruby\nclass CreateFooSchema \u003c ActiveRecord::Migration[7.0]\n  def up\n    create_schema('foo')\n\n    # Or you could move a table to a different schema\n\n    change_table_schema('foo', 'dbo.admin')\n  end\n\n  def down\n    drop_schema('foo')\n  end\nend\n```\n\n\n#### Configure Connection\n\nThe adapter conforms to the AbstractAdapter interface to configure connections. If you require additional connection\nconfiguration then implement the `configure_connection` method in an initializer like so. In the following\nexample we are setting the `TEXTSIZE` to 64 megabytes.\n\n```ruby\nActiveRecord::ConnectionAdapters::SQLServerAdapter.prepend(\n  Module.new do\n    def configure_connection\n      super\n      @raw_connection.execute(\"SET TEXTSIZE #{64.megabytes}\").do\n    end\n  end\n)\n```\n\n#### Configure Application Name\n\nTinyTDS supports an application name when it logs into SQL Server. This can be used to identify the connection in SQL Server's activity monitor. By default it will use the `appname` from your database.yml file or your Rails::Application name.\n\nBelow shows how you might use the database.yml file to use the process ID in your application name.\n\n```yaml\ndevelopment:\n  adapter: sqlserver\n  appname: \u003c%= \"myapp_#{Process.pid}\" %\u003e\n```\n\n#### Executing Stored Procedures\n\nEvery class that sub classes ActiveRecord::Base will now have an execute_procedure class method to use. This method takes the name of the stored procedure which can be a string or symbol and any number of variables to pass to the procedure. Arguments will automatically be quoted per the connection's standards as normal. For example:\n\n```ruby\nAccount.execute_procedure(:update_totals, 'admin', nil, true)\n# Or with named parameters.\nAccount.execute_procedure(:update_totals, named: 'params')\n```\n\n#### Explain Support (SHOWPLAN)\n\nThe 3.2 version of the adapter support ActiveRecord's explain features. In SQL Server, this is called the showplan. By default we use the `SHOWPLAN_ALL` option and format it using a simple table printer. So the following ruby would log the plan table below it.\n\n```ruby\nCar.where(id: 1).explain\n```\n\n```\nEXPLAIN for: SELECT [cars].* FROM [cars] WHERE [cars].[id] = 1\n+----------------------------------------------------+--------+--------+--------+----------------------+----------------------+----------------------------------------------------+----------------------------------------------------+--------------+---------------------+----------------------+------------+---------------------+----------------------------------------------------+----------+----------+----------+--------------------+\n| StmtText                                           | StmtId | NodeId | Parent | PhysicalOp           | LogicalOp            | Argument                                           | DefinedValues                                      | EstimateRows | EstimateIO          | EstimateCPU          | AvgRowSize | TotalSubtreeCost    | OutputList                                         | Warnings | Type     | Parallel | EstimateExecutions |\n+----------------------------------------------------+--------+--------+--------+----------------------+----------------------+----------------------------------------------------+----------------------------------------------------+--------------+---------------------+----------------------+------------+---------------------+----------------------------------------------------+----------+----------+----------+--------------------+\n| SELECT [cars].* FROM [cars] WHERE [cars].[id] = 1  |      1 |      1 |      0 | NULL                 | NULL                 | 2                                                  | NULL                                               |          1.0 | NULL                | NULL                 | NULL       | 0.00328309996984899 | NULL                                               | NULL     | SELECT   | false    | NULL               |\n|   |--Clustered Index Seek(OBJECT:([activerecord... |      1 |      2 |      1 | Clustered Index Seek | Clustered Index Seek | OBJECT:([activerecord_unittest].[dbo].[cars].[P... | [activerecord_unittest].[dbo].[cars].[id], [act... |          1.0 | 0.00312500004656613 | 0.000158099996042438 |        278 | 0.00328309996984899 | [activerecord_unittest].[dbo].[cars].[id], [act... | NULL     | PLAN_ROW | false    |                1.0 |\n+----------------------------------------------------+--------+--------+--------+----------------------+----------------------+----------------------------------------------------+----------------------------------------------------+--------------+---------------------+----------------------+------------+---------------------+----------------------------------------------------+----------+----------+----------+--------------------+\n```\n\nYou can configure a few options to your needs. First is the max column width for the logged table. The default value is 50 characters. You can change it like so.\n\n```ruby\nActiveRecord::ConnectionAdapters::SQLServer::Showplan::PrinterTable.max_column_width = 500\n```\n\nAnother configuration is the showplan option. Some might find the XML format more useful. If you have Nokogiri installed, we will format the XML string. I will gladly accept pathches that make the XML printer more useful!\n\n```ruby\nActiveRecord::ConnectionAdapters::SQLServerAdapter.showplan_option = 'SHOWPLAN_XML'\n```\n**NOTE:** The method we utilize to make SHOWPLANs work is very brittle to complex SQL. There is no getting around this as we have to deconstruct an already prepared statement for the sp_executesql method. If you find that explain breaks your app, simple disable it. Do not open a github issue unless you have a patch.  Please [consult the Rails guides](http://guides.rubyonrails.org/active_record_querying.html#running-explain) for more info.\n\n#### `insert_all` / `upsert_all` support\n\n`insert_all` and `upsert_all` on other database system like MySQL, SQlite or PostgreSQL use a clause with their `INSERT` statement to either skip duplicates (`ON DUPLICATE KEY IGNORE`) or to update the existing record (`ON DUPLICATE KEY UPDATE`). Microsoft SQL Server does not offer these clauses, so the support for these two options is implemented slightly different.\n\nBehind the scenes, we execute a `MERGE` query, which joins your data that you want to insert or update into the table existing on the server. The emphasis here is \"JOINING\", so we also need to remove any duplicates that might make the `JOIN` operation fail, e.g. something like this:\n\n```ruby\nBook.insert_all [\n  { id: 200, author_id: 8, name: \"Refactoring\" },\n  { id: 200, author_id: 8, name: \"Refactoring\" }\n]\n```\n\nThe removal of duplicates happens during the SQL query.\n\nBecause of this implementation, if you pass `on_duplicate` to `upsert_all`, make sure to assign your value to `target.[column_name]` (e.g. `target.status = GREATEST(target.status, 1)`). To access the values that you want to upsert, use `source.[column_name]`.\n\n## New Rails Applications\n\nWhen creating a new Rails application you need to perform the following steps to connect a Rails application to a\nSQL Server instance.\n\n1. Create new Rails application, the database defaults to `sqlite`.\n\n```bash\nrails new my_app\n```\n\n2. Update the Gemfile to install the adapter instead of the SQLite adapter. Remove the `sqlite3` gem from the Gemfile.\n\n```ruby\ngem 'activerecord-sqlserver-adapter'\n```\n\n3. Connect the application to your SQL Server instance by editing the `config/database.yml` file with the username,\npassword and host of your SQL Server instance.\n\nExample:\n\n```yaml\ndevelopment:\n  adapter: sqlserver\n  host: 'localhost'\n  port: 1433\n  database: my_app_development\n  username: 'frank_castle'\n  password: 'secret'\n```\n\n## Installation\n\nThe adapter has no strict gem dependencies outside of `ActiveRecord` and\n[TinyTDS](https://github.com/rails-sqlserver/tiny_tds).\n\n```ruby\ngem 'activerecord-sqlserver-adapter'\n```\n\n## Reporting an Issue\n\nHaving a way to reproduce your issue will help people confirm, investigate, and ultimately fix your issue. You\ncan do this by providing an executable test case. To make this process easier, we have prepared a bug report template\nfor you to use as a starting point at [How to report a bug](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/wiki/How-to-report-a-bug).\n\n## Contributing\n\nPlease contribute to the project by submitting bug fixes and features. To make sure your fix/feature has\na high chance of being added, please include tests in your pull request. To run the tests you will need to\nsetup your development environment.\n\n## Setting Up Your Development Environment\n\nTo run the test suite you can use any of the following methods below. See [RUNNING_UNIT_TESTS](RUNNING_UNIT_TESTS.md) for\nmore detailed information on running unit tests.\n\n### Dev Container CLI\n\nWith [Docker](https://www.docker.com) and [npm](https://github.com/npm/cli) installed, you can run [Dev Container CLI](https://github.com/devcontainers/cli) to\nutilize the [`.devcontainer`](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/tree/main/.devcontainer) configuration from the command line.\n\n```bash\n$ npm install -g @devcontainers/cli\n$ cd activerecord-sqlserver-adapter\n$ devcontainer up --workspace-folder .\n$ devcontainer exec --workspace-folder . bash\n```\n\nFrom within the container, you can run the tests using the following command:\n\n```bash\n$ bundle install\n$ bundle exec rake test\n```\n\n_Note: The setup we use is based on the [Rails Dev Container setup.](https://guides.rubyonrails.org/contributing_to_ruby_on_rails.html#using-dev-container-cli)_\n\n### VirtualBox \u0026 Vagrant\n\nThe [activerecord-sqlserver-adapter-dev-box](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter-dev-box)\nis a Vagrant/VirtualBox virtual machine that has MS SQL Server installed. However, the\nactiverecord-sqlserver-adapter-dev-box uses Vagrant and Virtual Box which will not work on Macs with Apple silicon.\n\n### Local Development\n\nSee the [RUNNING_UNIT_TESTS](RUNNING_UNIT_TESTS.md) file for the details of how to run the unit tests locally.\n\n## Community\n\nThere is a [Gitter channel](https://gitter.im/rails-sqlserver/activerecord-sqlserver-adapter) for the project where you are free to ask questions about the project.\n\n## Credits \u0026 Contributions\n\nMany many people have contributed. If you do not see your name here and it should be let us know. Also, many thanks go out to those that have pledged financial contributions.\n\nYou can see an up-to-date list of contributors here: http://github.com/rails-sqlserver/activerecord-sqlserver-adapter/contributors\n\n## License\n\nActiveRecord SQL Server Adapter is released under the [MIT License](https://opensource.org/licenses/MIT).\n","funding_links":[],"categories":["Ruby","SQL Server Web Resources","Database Drivers","Gems"],"sub_categories":["Articles"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frails-sqlserver%2Factiverecord-sqlserver-adapter","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frails-sqlserver%2Factiverecord-sqlserver-adapter","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frails-sqlserver%2Factiverecord-sqlserver-adapter/lists"}