Skip to content
Closed
Show file tree
Hide file tree
Changes from 12 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
205 changes: 45 additions & 160 deletions eng/pipelines/pr-validation-pipeline.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,163 +7,48 @@ trigger:
- main

jobs:
- job: PytestOnWindows
pool:
vmImage: 'windows-latest'

steps:
- task: UsePythonVersion@0
inputs:
# TODO: Remove this once Python 3.13 is available in ADO
# ADO indexing will take some time to reflect 3.13 as 3.13.5, right now it is pointing to 3.13.4.
# We're specifying to use Python 3.13.5 since 3.13.4 has issues with compilation
# See https://github.com/python/cpython/issues/135151, next release should fix it.
versionSpec: '3.13.5'
addToPath: true
githubToken: $(GITHUB_TOKEN)
displayName: 'Use Python 3.13'

- script: |
python -m pip install --upgrade pip
pip install -r requirements.txt
displayName: 'Install dependencies'

# Start LocalDB instance
- powershell: |
sqllocaldb create MSSQLLocalDB
sqllocaldb start MSSQLLocalDB
displayName: 'Start LocalDB instance'

# Create database and user
- powershell: |
sqlcmd -S "(localdb)\MSSQLLocalDB" -Q "CREATE DATABASE TestDB"
sqlcmd -S "(localdb)\MSSQLLocalDB" -Q "CREATE LOGIN testuser WITH PASSWORD = '$(DB_PASSWORD)'"
sqlcmd -S "(localdb)\MSSQLLocalDB" -d TestDB -Q "CREATE USER testuser FOR LOGIN testuser"
sqlcmd -S "(localdb)\MSSQLLocalDB" -d TestDB -Q "ALTER ROLE db_owner ADD MEMBER testuser"
displayName: 'Setup database and user'
env:
DB_PASSWORD: $(DB_PASSWORD)

- script: |
cd mssql_python\pybind
build.bat x64
displayName: 'Build .pyd file'

- script: |
python -m pytest -v --junitxml=test-results.xml --cov=. --cov-report=xml --capture=tee-sys --cache-clear
displayName: 'Run tests with coverage'
env:
DB_CONNECTION_STRING: 'Server=(localdb)\MSSQLLocalDB;Database=TestDB;Uid=testuser;Pwd=$(DB_PASSWORD);TrustServerCertificate=yes'

- task: PublishBuildArtifacts@1
inputs:
PathtoPublish: 'mssql_python/ddbc_bindings.cp313-amd64.pyd'
ArtifactName: 'ddbc_bindings'
publishLocation: 'Container'
displayName: 'Publish pyd file as artifact'

- task: PublishBuildArtifacts@1
inputs:
PathtoPublish: 'mssql_python/ddbc_bindings.cp313-amd64.pdb'
ArtifactName: 'ddbc_bindings'
publishLocation: 'Container'
displayName: 'Publish pdb file as artifact'

- task: PublishTestResults@2
condition: succeededOrFailed()
inputs:
testResultsFiles: '**/test-results.xml'
testRunTitle: 'Publish test results'

- task: PublishCodeCoverageResults@1
inputs:
codeCoverageTool: 'Cobertura'
summaryFileLocation: 'coverage.xml'
displayName: 'Publish code coverage results'

- job: PytestOnMacOS
pool:
vmImage: 'macos-latest'

steps:
- task: UsePythonVersion@0
inputs:
versionSpec: '3.13.5'
addToPath: true
displayName: 'Use Python 3.13 on macOS'

- script: |
brew update
brew install cmake
displayName: 'Install CMake'

# - script: |
# brew update
# brew install docker colima

# # Start Colima with extra resources
# colima start --cpu 4 --memory 8 --disk 50

# # Optional: set Docker context (usually automatic)
# docker context use colima >/dev/null || true

# # Confirm Docker is operational
# docker version
# docker ps
# displayName: 'Install and start Colima-based Docker'

# - script: |
# # Pull and run SQL Server container
# docker pull mcr.microsoft.com/mssql/server:2022-latest
# docker run \
# --name sqlserver \
# -e ACCEPT_EULA=Y \
# -e MSSQL_SA_PASSWORD="${DB_PASSWORD}" \
# -p 1433:1433 \
# -d mcr.microsoft.com/mssql/server:2022-latest

# # Starting SQL Server container…
# for i in {1..30}; do
# docker exec sqlserver \
# /opt/mssql-tools18/bin/sqlcmd \
# -S localhost \
# -U SA \
# -P "$DB_PASSWORD" \
# -C -Q "SELECT 1" && break
# sleep 2
# done
# displayName: 'Pull & start SQL Server (Docker)'
# env:
# DB_PASSWORD: $(DB_PASSWORD)

- script: |
python -m pip install --upgrade pip
pip install -r requirements.txt
displayName: 'Install Python dependencies'

- script: |
cd mssql_python/pybind
./build.sh
displayName: 'Build pybind bindings (.so)'

- script: |
echo "Build successful, running tests now"
python -m pytest -v --junitxml=test-results.xml --cov=. --cov-report=xml --capture=tee-sys --cache-clear
displayName: 'Run pytest with coverage'
env:
# Temporarily Use Azure SQL Database connection string for testing purposes since Docker takes too long to install & start in MacOS
DB_CONNECTION_STRING: $(AZURE_CONNECTION_STRING)
# DB_CONNECTION_STRING: 'Driver=ODBC Driver 18 for SQL Server;Server=localhost;Database=master;Uid=SA;Pwd=$(DB_PASSWORD);TrustServerCertificate=yes'
DB_PASSWORD: $(DB_PASSWORD)

- task: PublishTestResults@2
condition: succeededOrFailed()
inputs:
testResultsFiles: '**/test-results.xml'
testRunTitle: 'Publish pytest results on macOS'

- task: PublishCodeCoverageResults@1
inputs:
codeCoverageTool: 'Cobertura'
summaryFileLocation: 'coverage.xml'
displayName: 'Publish code coverage results'
- job: TestMacOS
pool:
vmImage: 'macos-latest'

steps:
- task: UsePythonVersion@0
inputs:
versionSpec: '3.13.5'
addToPath: true
displayName: 'Use Python 3.13 on macOS'

- script: |
brew update
brew install cmake
displayName: 'Install CMake'

- script: |
python -m pip install --upgrade pip
pip install -r requirements.txt
displayName: 'Install Python dependencies'

- script: |
cd mssql_python/pybind
./build.sh
displayName: 'Build pybind bindings (.so)'

- script: |
echo "Running main.py on macOS"
python main.py
displayName: 'Run main.py to ensure Python is working'
env:
# Temporarily Use Azure SQL Database connection string for testing purposes since Docker takes too long to install & start in MacOS
DB_CONNECTION_STRING: $(AZURE_CONNECTION_STRING)
# DB_CONNECTION_STRING: 'Driver=ODBC Driver 18 for SQL Server;Server=localhost;Database=master;Uid=SA;Pwd=$(DB_PASSWORD);TrustServerCertificate=yes'
DB_PASSWORD: $(DB_PASSWORD)

- script: |
echo "Build successful, running tests now"
python -m pytest -v --junitxml=test-results.xml --cov=. --cov-report=xml --capture=tee-sys --cache-clear
displayName: 'Run pytest with coverage'
env:
# Temporarily Use Azure SQL Database connection string for testing purposes since Docker takes too long to install & start in MacOS
DB_CONNECTION_STRING: $(AZURE_CONNECTION_STRING)
# DB_CONNECTION_STRING: 'Driver=ODBC Driver 18 for SQL Server;Server=localhost;Database=master;Uid=SA;Pwd=$(DB_PASSWORD);TrustServerCertificate=yes'
DB_PASSWORD: $(DB_PASSWORD)
11 changes: 6 additions & 5 deletions mssql_python/db_connection.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,12 @@
Licensed under the MIT license.
This module provides a way to create a new connection object to interact with the database.
"""
import platform
if platform.system() == 'Windows':
from mssql_python.connection import Connection
else:
from mssql_python.connection_mac import Connection
from mssql_python.connection import Connection
# import platform
# if platform.system() == 'Windows':
# from mssql_python.connection import Connection
# else:
# from mssql_python.connection_mac import Connection

def connect(connection_str: str = "", autocommit: bool = True, attrs_before: dict = None, **kwargs) -> Connection:
"""
Expand Down
19 changes: 5 additions & 14 deletions mssql_python/pybind/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -178,20 +178,11 @@ endif()

message(STATUS "Final Python library directory: ${PYTHON_LIB_DIR}")

# Determine which source file to use based on platform
if(APPLE)
set(DDBC_SOURCE "ddbc_bindings_mac.cpp")
message(STATUS "Using macOS-specific source file: ${DDBC_SOURCE}")
# Only ddbc_bindings_mac.cpp is used on macOS
# TODO: Implement smart pointer in macOS
add_library(ddbc_bindings MODULE ${DDBC_SOURCE})
else()
# This is just windows block
set(DDBC_SOURCE "ddbc_bindings.cpp")
message(STATUS "Using standard source file: ${DDBC_SOURCE}")
# Include connection module for Windows
add_library(ddbc_bindings MODULE ${DDBC_SOURCE} connection/connection.cpp connection/connection_pool.cpp)
endif()
set(DDBC_SOURCE "ddbc_bindings.cpp")
message(STATUS "Using standard source file: ${DDBC_SOURCE}")
# Include connection module for Windows
add_library(ddbc_bindings MODULE ${DDBC_SOURCE} connection/connection.cpp connection/connection_pool.cpp)
# endif()

# Set the output name to include Python version and architecture
# Use appropriate file extension based on platform
Expand Down
22 changes: 17 additions & 5 deletions mssql_python/pybind/connection/connection.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,9 +67,20 @@ void Connection::connect(const py::dict& attrs_before) {
setAutocommit(_autocommit);
}
}
SQLWCHAR* connStrPtr;
#if defined(__APPLE__) // macOS specific code
LOG("Creating connection string buffer for macOS");
std::vector<SQLWCHAR> connStrBuffer = WStringToSQLWCHAR(_connStr);
// Ensure the buffer is null-terminated
LOG("Connection string buffer size - {}", connStrBuffer.size());
connStrPtr = connStrBuffer.data();
LOG("Connection string buffer created");
#else
connStrPtr = const_cast<SQLWCHAR*>(_connStr.c_str());
#endif
SQLRETURN ret = SQLDriverConnect_ptr(
_dbcHandle->get(), nullptr,
(SQLWCHAR*)_connStr.c_str(), SQL_NTS,
connStrPtr, SQL_NTS,
nullptr, 0, nullptr, SQL_DRIVER_NOPROMPT);
checkError(ret);
updateLastUsed();
Expand Down Expand Up @@ -236,12 +247,13 @@ std::chrono::steady_clock::time_point Connection::lastUsed() const {
return _lastUsed;
}

ConnectionHandle::ConnectionHandle(const std::wstring& connStr, bool usePool, const py::dict& attrsBefore)
: _connStr(connStr), _usePool(usePool) {
ConnectionHandle::ConnectionHandle(const std::string& connStr, bool usePool, const py::dict& attrsBefore)
: _usePool(usePool) {
_connStr = Utf8ToWString(connStr);
if (_usePool) {
_conn = ConnectionPoolManager::getInstance().acquireConnection(connStr, attrsBefore);
_conn = ConnectionPoolManager::getInstance().acquireConnection(_connStr, attrsBefore);
} else {
_conn = std::make_shared<Connection>(connStr, false);
_conn = std::make_shared<Connection>(_connStr, false);
_conn->connect(attrsBefore);
}
}
Expand Down
2 changes: 1 addition & 1 deletion mssql_python/pybind/connection/connection.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ class Connection {

class ConnectionHandle {
public:
ConnectionHandle(const std::wstring& connStr, bool usePool, const py::dict& attrsBefore = py::dict());
ConnectionHandle(const std::string& connStr, bool usePool, const py::dict& attrsBefore = py::dict());
~ConnectionHandle();

void close();
Expand Down
1 change: 0 additions & 1 deletion mssql_python/pybind/connection/connection_pool.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
// taken up in future.

#include "connection_pool.h"
#include <iostream>
#include <exception>

ConnectionPool::ConnectionPool(size_t max_size, int idle_timeout_secs)
Expand Down
Loading