Skip to content

feat(mssql): use msodbcsql instead of freetds #872

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

Merged
merged 2 commits into from
Oct 31, 2024
Merged
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: 6 additions & 9 deletions .github/workflows/ibis-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -54,16 +54,13 @@ jobs:
~/.cargo/git/db/
wren-core-py/target/
key: ${{ runner.os }}-cargo-${{ hashFiles('wren-core-py/Cargo.lock') }}
- name: Install FreeTDS to be a ODBC driver
- name: Install MS ODBC SQL driver
run: |
sudo apt-get update -y && sudo apt-get install -y unixodbc-dev freetds-dev tdsodbc
cat << EOF > free.tds.ini
[FreeTDS]
Description = FreeTDS driver
Driver = /usr/lib/x86_64-linux-gnu/odbc/libtdsodbc.so
Setup = /usr/lib/x86_64-linux-gnu/odbc/libtdsodbc.so
EOF
sudo odbcinst -i -d -f free.tds.ini
sudo apt-get update
curl https://packages.microsoft.com/keys/microsoft.asc | sudo tee /etc/apt/trusted.gpg.d/microsoft.asc
curl https://packages.microsoft.com/config/ubuntu/$(lsb_release -rs)/prod.list | sudo tee /etc/apt/sources.list.d/mssql-release.list
sudo apt-get update
sudo ACCEPT_EULA=Y apt-get -y install unixodbc-dev msodbcsql18
- name: Install dependencies
run: |
just install
Expand Down
36 changes: 11 additions & 25 deletions ibis-server/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -35,33 +35,19 @@ RUN just install-core $RUST_PROFILE

FROM python:3.11-slim-buster AS runtime

# libpq-dev is required for psycopg2
# unixodbc-dev, freetds-dev and tdsodbc are required for pyodbc
RUN apt-get update \
&& apt-get -y install libpq-dev \
&& apt-get -y install unixodbc-dev freetds-dev tdsodbc \
&& rm -rf /var/lib/apt/lists/*
# Add microsoft package list
RUN apt-get update \
&& apt-get install -y curl gnupg \
&& curl https://packages.microsoft.com/keys/microsoft.asc | tee /etc/apt/trusted.gpg.d/microsoft.asc \
&& curl https://packages.microsoft.com/config/debian/11/prod.list | tee /etc/apt/sources.list.d/mssql-release.list \
&& apt-get update

ARG TARGETPLATFORM
# Install msodbcsql 18 driver for mssql
RUN ACCEPT_EULA=Y apt-get -y install unixodbc-dev msodbcsql18

# Install FreeTDS driver
RUN <<EOT
if [ "$TARGETPLATFORM" = "linux/amd64" ]; then
export FREE_TDS_PATH=/usr/lib/x86_64-linux-gnu/odbc/libtdsodbc.so;
elif [ "$TARGETPLATFORM" = "linux/arm64" ]; then
export FREE_TDS_PATH=/usr/lib/aarch64-linux-gnu/odbc/libtdsodbc.so;
else \
echo "Unsupported platform: $TARGETPLATFORM"; exit 1;
fi && \
echo "FREE_TDS_PATH is set to $FREE_TDS_PATH"
cat <<EOF > free.tds.ini
[FreeTDS]
Description = FreeTDS driver
Driver = ${FREE_TDS_PATH}
Setup = ${FREE_TDS_PATH}
EOF
odbcinst -i -d -f free.tds.ini
EOT
# libpq-dev is required for psycopg2
RUN apt-get -y install libpq-dev \
&& rm -rf /var/lib/apt/lists/*

ENV VIRTUAL_ENV=/app/.venv \
PATH="/app/.venv/bin:$PATH" \
Expand Down
5 changes: 1 addition & 4 deletions ibis-server/app/model/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,10 +82,7 @@ class MSSqlConnectionInfo(BaseModel):
database: SecretStr
user: SecretStr
password: SecretStr
driver: str = Field(
default="FreeTDS",
description="On Mac and Linux this is usually `FreeTDS. On Windows, it is usually `ODBC Driver 18 for SQL Server`",
)
driver: str = Field(default="ODBC Driver 18 for SQL Server")
tds_version: str = Field(default="8.0", alias="TDS_Version")
kwargs: dict[str, str] | None = Field(
description="Additional keyword arguments to pass to PyODBC", default=None
Expand Down
28 changes: 17 additions & 11 deletions ibis-server/docs/development.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,15 +59,21 @@ Please see [How to Add a New Data Source](how-to-add-data-source.md) for more in


## Troubleshooting
### MS SQL Server Tests
If you're having trouble running tests related to MS SQL Server, you may need to install the appropriate driver. For Linux or macOS, we recommend installing the `unixodbc` and `freetds` packages.
After installation, run `odbcinst -j` to check the path of the `odbcinst.ini` file. Then, find the path of `libtdsodbc.so` in freetds and add the following content to the odbcinst.ini file:
```ini
[FreeTDS]
Description = FreeTDS driver
Driver = /opt/homebrew/Cellar/freetds/1.4.17/lib/libtdsodbc.so
Setup = /opt/homebrew/Cellar/freetds/1.4.17/lib/libtdsodbc.so
FileUsage = 1
### No driver for MS SQL Server
If you want to run tests related to MS SQL Server, you may need to install the `Microsoft ODBC 18 driver`. \
You can follow the instructions to install the driver:
- [Microsoft ODBC driver for SQL Server (Linux)](https://learn.microsoft.com/en-us/sql/connect/odbc/linux-mac/installing-the-microsoft-odbc-driver-for-sql-server).
- [Microsoft ODBC driver for SQL Server (macOS)](https://learn.microsoft.com/en-us/sql/connect/odbc/linux-mac/install-microsoft-odbc-driver-sql-server-macos).
- [Microsoft ODBC driver for SQL Server (Windows)](https://learn.microsoft.com/en-us/sql/connect/odbc/download-odbc-driver-for-sql-server).

### [ODBC Driver 18 for SQL Server]SSL Provider: [error:1416F086:SSL routines:tls_process_server_certificate:certificate verify failed:self signed certificate]
If you encounter this error, you can add the `TrustServerCertificate` parameter to the connection string.
```json
{
"connectionInfo": {
"kwargs": {
"TrustServerCertificate": "YES"
}
}
}
```
Adjust the paths as necessary for your system.

7 changes: 5 additions & 2 deletions ibis-server/tests/routers/v2/connector/test_mssql.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,9 @@ def mssql(request) -> SqlServerContainer:
mssql = SqlServerContainer(
"mcr.microsoft.com/mssql/server:2019-CU27-ubuntu-20.04", dialect="mssql+pyodbc"
).start()
engine = sqlalchemy.create_engine(f"{mssql.get_connection_url()}?driver=FreeTDS")
engine = sqlalchemy.create_engine(
f"{mssql.get_connection_url()}?driver=ODBC+Driver+18+for+SQL+Server&TrustServerCertificate=YES"
)
pd.read_parquet(file_path("resource/tpch/data/orders.parquet")).to_sql(
"orders", engine, index=False
)
Expand Down Expand Up @@ -382,8 +384,9 @@ def _to_connection_info(mssql: SqlServerContainer):
"user": mssql.username,
"password": mssql.password,
"database": mssql.dbname,
"kwargs": {"TrustServerCertificate": "YES"},
}

def _to_connection_url(mssql: SqlServerContainer):
info = _to_connection_info(mssql)
return f"mssql://{info['user']}:{info['password']}@{info['host']}:{info['port']}/{info['database']}?driver=FreeTDS"
return f"mssql://{info['user']}:{info['password']}@{info['host']}:{info['port']}/{info['database']}?driver=ODBC+Driver+18+for+SQL+Server&TrustServerCertificate=YES"
Loading