Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add supporting SQL Server #91

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 14 additions & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
@@ -1,5 +1,18 @@
FROM ruby:2.3.1-slim
RUN apt-get update -qq && apt-get install -y build-essential libpq-dev libmysqlclient-dev nodejs nodejs-legacy npm git
RUN apt-get update -qq && \
apt-get install -y \
build-essential libpq-dev libmysqlclient-dev nodejs nodejs-legacy npm git \
freetds-dev freetds-bin unixodbc unixodbc-dev tdsodbc libc6-dev wget

RUN mkdir /tmp/freetds && \
cd /tmp/freetds && \
wget ftp://ftp.freetds.org/pub/freetds/stable/freetds-1.00.21.tar.gz && \
tar -xzf freetds-1.00.21.tar.gz && \
cd freetds-1.00.21 && \
./configure --prefix=/usr/local --with-tdsver=7.3 && \
make && \
make install

RUN mkdir /app

ADD Gemfile /tmp/Gemfile
Expand Down
2 changes: 2 additions & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ gem 'rails', '~> 4.2.6'
gem 'pg', '~> 0.15'
gem 'mysql2'
gem 'activerecord4-redshift-adapter', '~> 0.2.0'
gem 'activerecord-sqlserver-adapter', '~> 4.2.0'
gem 'tiny_tds'

gem 'sass-rails', '~> 5.0'
gem 'uglifier', '>= 1.3.0'
Expand Down
26 changes: 15 additions & 11 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ GEM
activemodel (= 4.2.10)
activesupport (= 4.2.10)
arel (~> 6.0)
activerecord-sqlserver-adapter (4.2.18)
activerecord (~> 4.2.1)
activerecord4-redshift-adapter (0.2.1)
activerecord (~> 4.2.0)
pg
Expand All @@ -46,7 +48,7 @@ GEM
sshkit (>= 1.6.1, != 1.7.0)
arel (6.0.4)
ast (2.3.0)
brakeman (4.0.1)
brakeman (4.1.0)
builder (3.2.3)
byebug (9.1.0)
callsite (0.0.11)
Expand Down Expand Up @@ -183,10 +185,10 @@ GEM
multi_json (~> 1.3)
omniauth (>= 1.1.1)
omniauth-oauth2 (>= 1.3.1)
omniauth-oauth2 (1.4.0)
oauth2 (~> 1.0)
omniauth-oauth2 (1.5.0)
oauth2 (~> 1.1)
omniauth (~> 1.2)
parallel (1.12.0)
parallel (1.12.1)
parser (2.4.0.2)
ast (~> 2.3)
pg (0.21.0)
Expand Down Expand Up @@ -236,8 +238,7 @@ GEM
activesupport (= 4.2.10)
rake (>= 0.8.7)
thor (>= 0.18.1, < 2.0)
rainbow (2.2.2)
rake
rainbow (3.0.0)
rake (12.3.0)
rb-fsevent (0.10.2)
rb-inotify (0.9.10)
Expand Down Expand Up @@ -266,18 +267,18 @@ GEM
rspec-mocks (~> 3.7.0)
rspec-support (~> 3.7.0)
rspec-support (3.7.0)
rubocop (0.51.0)
rubocop (0.52.0)
parallel (~> 1.10)
parser (>= 2.3.3.1, < 3.0)
parser (>= 2.4.0.2, < 3.0)
powerpack (~> 0.1)
rainbow (>= 2.2.2, < 3.0)
rainbow (>= 2.2.2, < 4.0)
ruby-progressbar (~> 1.7)
unicode-display_width (~> 1.0, >= 1.0.1)
ruby-prof (0.16.2)
ruby-prof (0.17.0)
ruby-progressbar (1.9.0)
ruby_parser (3.10.1)
sexp_processor (~> 4.9)
sass (3.5.3)
sass (3.5.4)
sass-listen (~> 4.0.0)
sass-listen (4.0.0)
rb-fsevent (~> 0.9, >= 0.9.4)
Expand Down Expand Up @@ -311,6 +312,7 @@ GEM
thread_safe (0.3.6)
tilt (2.0.8)
tins (1.16.3)
tiny_tds (2.1.0)
tzinfo (1.2.4)
thread_safe (~> 0.1)
uglifier (4.0.2)
Expand All @@ -325,6 +327,7 @@ PLATFORMS
DEPENDENCIES
action_args
active_decorator
activerecord-sqlserver-adapter (~> 4.2.0)
activerecord4-redshift-adapter (~> 0.2.0)
addressable
brakeman
Expand Down Expand Up @@ -365,6 +368,7 @@ DEPENDENCIES
ruby-prof
sass-rails (~> 5.0)
simplecov
tiny_tds
uglifier (>= 1.3.0)

BUNDLED WITH
Expand Down
8 changes: 8 additions & 0 deletions app/models/data_source.rb
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,14 @@ def source_table_names
) tables
ORDER BY schemaname, tablename;
SQL
when ActiveRecord::ConnectionAdapters::SQLServerAdapter
schemas_and_tables = source_base_class.connection.select_rows(<<-SQL, 'SCHEMA')
SELECT table_schema
, table_name
FROM information_schema.tables
WHERE table_type = 'BASE TABLE';
SQL
schemas_and_tables.map {|table_schema, table_name| [table_schema, table_name]}
else
source_base_class.connection.tables.map {|table_name| [dbname, table_name] }
end
Expand Down
16 changes: 12 additions & 4 deletions app/models/data_source_table.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,18 @@ def initialize(data_source, schema_name, table_name)
def fetch_rows(limit=20)
data_source.access_logging do
adapter = connection.pool.connections.first
column_names = columns.map {|column| adapter.quote_column_name(column.name) }.join(", ")
rows = connection.select_rows(<<-SQL, "#{table_name.classify} Load")
SELECT #{column_names} FROM #{adapter.quote_table_name(full_table_name)} LIMIT #{limit};
SQL
decode_with = data_source.encoding or 'UTF-8'
encode_to = Encoding.default_internal or 'UTF-8'
column_names = columns.map {|column| adapter.quote_column_name(column.name.encode(encode_to, decode_with)) }.join(", ")
if data_source[:adapter] == 'sqlserver'
rows = connection.select_rows(<<-SQL, "#{table_name.classify} Load")
SELECT TOP #{limit} #{column_names} FROM #{adapter.quote_table_name(full_table_name)};
SQL
else
rows = connection.select_rows(<<-SQL, "#{table_name.classify} Load")
SELECT #{column_names} FROM #{adapter.quote_table_name(full_table_name)} LIMIT #{limit};
SQL
end
rows.map {|row|
columns.zip(row).map {|column, value| column.type_cast_from_database(value) }
}
Expand Down
22 changes: 17 additions & 5 deletions app/models/table_memo_raw_dataset_column.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,24 @@ class TableMemoRawDatasetColumn < ActiveRecord::Base
belongs_to :table_memo_raw_dataset, class_name: "TableMemoRawDataset"

def format_value(value)
case sql_type
when 'timestamp without time zone'
d, t, z = value.to_s.split
"#{d} #{t}"
datasource_encoding = table_memo_raw_dataset.table_memo.database_memo.data_source.encoding
datasource_adapter = table_memo_raw_dataset.table_memo.database_memo.data_source.adapter
if datasource_adapter == 'sqlserver'
case sql_type
when 'timestamp'
'0x' + value.unpack('H*')[0]
else
dst_enc = Encoding.default_internal or 'UTF-8'
value.to_s.encode(dst_enc, datasource_encoding).gsub(/\u0000/, '')
end
else
value.to_s
case sql_type
when 'timestamp without time zone'
d, t, z = value.to_s.split
"#{d} #{t}"
else
value.to_s
end
end
end
end
2 changes: 1 addition & 1 deletion app/views/data_sources/_form.html.haml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
.col-sm-10= f.text_field :description, class: "form-control", placeholder: "localhost database"
.form-group
= f.label :adapter, class: "col-sm-2 control-label"
.col-sm-10= f.select :adapter, %w(redshift postgresql mysql2), {}, class: "form-control"
.col-sm-10= f.select :adapter, %w(redshift postgresql mysql2 sqlserver), {}, class: "form-control"
.form-group
= f.label :host, class: "col-sm-2 control-label"
.col-sm-10= f.text_field :host, class: "form-control", placeholder: "localhost"
Expand Down
1 change: 1 addition & 0 deletions config/database.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,5 @@ test:
database: dmemo_test

production:
<<: *default
url: <%= ENV["DATABASE_URL"] %>